Feature Tip: Add private address tag to any address under My Name Tag !
Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
SushiLPPool
Compiler Version
v0.8.4+commit.c7e474f2
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity 0.8.4; import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import { V2Migrator } from "./base/V2Migrator.sol"; import { CorePool } from "./base/CorePool.sol"; import { ErrorHandler } from "./libraries/ErrorHandler.sol"; import { ICorePoolV1 } from "./interfaces/ICorePoolV1.sol"; /** * @title The Sushi LP Pool. * * @dev Extends all functionality from V2Migrator contract, there isn't a lot of * additions compared to ILV pool. Sushi LP pool basically needs to be able * to be called by ILV pool in batch calls where we claim rewards from multiple * pools. */ contract SushiLPPool is Initializable, V2Migrator { using ErrorHandler for bytes4; /// @dev Calls __V2Migrator_init(). function initialize( address ilv_, address silv_, address _poolToken, address _factory, uint64 _initTime, uint32 _weight, address _corePoolV1, uint256 v1StakeMaxPeriod_ ) external initializer { __V2Migrator_init(ilv_, silv_, _poolToken, _corePoolV1, _factory, _initTime, _weight, v1StakeMaxPeriod_); } /// @inheritdoc CorePool function getTotalReserves() external view virtual override returns (uint256 totalReserves) { totalReserves = poolTokenReserve + ICorePoolV1(corePoolV1).poolTokenReserve(); } /** * @notice This function can be called only by ILV core pool. * * @dev Uses ILV pool as a router by receiving the _staker address and executing * the internal `_claimYieldRewards()`. * @dev Its usage allows claiming multiple pool contracts in one transaction. * * @param _staker user address * @param _useSILV whether it should claim pendingYield as ILV or sILV */ function claimYieldRewardsFromRouter(address _staker, bool _useSILV) external virtual { // checks if contract is paused _requireNotPaused(); // checks if caller is the ILV pool _requirePoolIsValid(); // calls internal _claimYieldRewards function (in CorePool.sol) _claimYieldRewards(_staker, _useSILV); } /** * @notice This function can be called only by ILV core pool. * * @dev Uses ILV pool as a router by receiving the _staker address and executing * the internal `_claimVaultRewards()`. * @dev Its usage allows claiming multiple pool contracts in one transaction. * * @param _staker user address */ function claimVaultRewardsFromRouter(address _staker) external virtual { // checks if contract is paused _requireNotPaused(); // checks if caller is the ILV pool _requirePoolIsValid(); // calls internal _claimVaultRewards function (in CorePool.sol) _claimVaultRewards(_staker); } /** * @dev Checks if caller is ILV pool. * @dev We are using an internal function instead of a modifier in order to * reduce the contract's bytecode size. */ function _requirePoolIsValid() internal view virtual { // we're using selector to simplify input and state validation // internal function simulated selector is `bytes4(keccak256("_requirePoolIsValid()"))` bytes4 fnSelector = 0x250f303f; // checks if pool is the ILV pool bool poolIsValid = address(_factory.pools(_ilv)) == msg.sender; fnSelector.verifyState(poolIsValid, 0); } /** * @dev Empty reserved space in storage. The size of the __gap array is calculated so that * the amount of storage used by a contract always adds up to the 50. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. */ bool private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Modifier to protect an initializer function from being invoked twice. */ modifier initializer() { require(_initializing || !_initialized, "Initializable: contract is already initialized"); bool isTopLevelCall = !_initializing; if (isTopLevelCall) { _initializing = true; _initialized = true; } _; if (isTopLevelCall) { _initializing = false; } } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.4; import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import { ICorePoolV1 } from "../interfaces/ICorePoolV1.sol"; import { ErrorHandler } from "../libraries/ErrorHandler.sol"; import { Stake } from "../libraries/Stake.sol"; import { CorePool } from "./CorePool.sol"; /** * @title V2Migrator * * @dev V2Migrator inherits all CorePool base contract functionaltiy, and adds * v1 to v2 migration related functions. This is a core smart contract of * Sushi LP and ILV pools, and manages users locked and yield weights coming * from v1. * @dev Parameters need to be reviewed carefully before deployment for the migration process. * @dev Users will migrate their locked stakes, which are stored in the contract, * and v1 total yield weights by data stored in a merkle tree using merkle proofs. */ abstract contract V2Migrator is Initializable, CorePool { using ErrorHandler for bytes4; using Stake for uint256; /// @dev Maps v1 addresses that are black listed for v2 migration. mapping(address => bool) public isBlacklisted; /// @dev Stores maximum timestamp of a v1 stake (yield) accepted in v2. uint256 internal _v1StakeMaxPeriod; /// @dev Stores maximum timestamp of a v1 stake (deposit) accepted in v2. uint256 internal constant _v1DepositMaxPeriod = 1648150500; /** * @dev logs `_migrateLockedStakes()` * * @param from user address * @param totalV1WeightAdded total amount of weight coming from locked stakes in v1 * */ event LogMigrateLockedStakes(address indexed from, uint256 totalV1WeightAdded); /** * @dev V2Migrator initializer function. * * @param v1StakeMaxPeriod_ max timestamp that we accept _lockedFrom values * in v1 stakes */ function __V2Migrator_init( address ilv_, address silv_, address _poolToken, address _corePoolV1, address factory_, uint64 _initTime, uint32 _weight, uint256 v1StakeMaxPeriod_ ) internal initializer { // call internal core pool intializar __CorePool_init(ilv_, silv_, _poolToken, _corePoolV1, factory_, _initTime, _weight); // sets max period for upgrading to V2 contracts i.e migrating _v1StakeMaxPeriod = v1StakeMaxPeriod_; } /** * @notice Blacklists a list of v1 user addresses by setting the * _isBlacklisted flag to true. * * @dev The intention is to prevent addresses that exploited v1 to be able to move * stake ids to the v2 contracts and to be able to mint any yield from a v1 * stake id with the isYield flag set to true. * * @param _users v1 users address array */ function blacklistUsers(address[] calldata _users) external virtual { // only the factory controller can blacklist users _requireIsFactoryController(); // we're using selector to simplify validation bytes4 fnSelector = this.blacklistUsers.selector; // gets each user in the array to be blacklisted for (uint256 i = 0; i < _users.length; i++) { // makes sure user passed isn't the address 0 fnSelector.verifyInput(_users[i] != address(0), 0); // updates mapping isBlacklisted[_users[i]] = true; } } /** * @dev External migrateLockedStakes call, used in the Sushi LP pool contract. * @dev The function is used by users that want to migrate locked stakes in v1, * but have no yield in the pool. This happens in two scenarios: * * 1 - The user pool is the Sushi LP pool, which only has stakes; * 2 - The user joined ILV pool recently, doesn't have much yield and * doesn't want to migrate their yield weight in the pool; * @notice Most of the times this function will be used in the inherited Sushi * LP pool contract (called by the v1 user coming from sushi pool), * but it's possible that a v1 user coming from the ILV pool decides * to use this function instead of `executeMigration()` defined in * the ILV pool contract. * * @param _stakeIds array of v1 stake ids */ function migrateLockedStakes(uint256[] calldata _stakeIds) external virtual { // verifies that user isn't a v1 blacklisted user _requireNotBlacklisted(msg.sender); // checks if contract is paused _requireNotPaused(); // uses v1 weight values for rewards calculations uint256 v1WeightToAdd = _useV1Weight(msg.sender); // update user state _updateReward(msg.sender, v1WeightToAdd); // call internal migrate locked stake function // which does the loop to store each v1 stake // reference in v2 and all required data _migrateLockedStakes(_stakeIds); } /** * @dev Reads v1 core pool locked stakes data (by looping through the `_stakeIds` array), * checks if it's a valid v1 stake to migrate and save the id to v2 user struct. * * @dev Only `msg.sender` can migrate v1 stakes to v2. * * @param _stakeIds array of v1 stake ids */ function _migrateLockedStakes(uint256[] calldata _stakeIds) internal virtual { User storage user = users[msg.sender]; // we're using selector to simplify input and state validation // internal function simulated selector is `bytes4(keccak256("_migrateLockedStakes(uint256[])"))` bytes4 fnSelector = 0x80812525; // initializes variable which will tell how much // weight in v1 the user is bringing to v2 uint256 totalV1WeightAdded; // loops over each v1 stake id passed to do the necessary validity checks // and store the values required in v2 to keep track of v1 weight in order // to include it in v2 rewards (yield and revenue distribution) calculations for (uint256 i = 0; i < _stakeIds.length; i++) { // reads the v1 stake by calling the v1 core pool getDeposit and separates // all required data in the struct to be used (, uint256 _weight, uint64 lockedFrom, , bool isYield) = ICorePoolV1(corePoolV1).getDeposit( msg.sender, _stakeIds[i] ); // checks if the v1 stake is in the valid period for migration fnSelector.verifyState(lockedFrom <= _v1DepositMaxPeriod, i * 3); // checks if the v1 stake has been locked originally and isn't a yield // stake, which are the requirements for moving to v2 through this function fnSelector.verifyState(lockedFrom > 0 && !isYield, i * 3 + 1); // checks if the user has already brought those v1 stakes to v2 fnSelector.verifyState(v1StakesWeights[msg.sender][_stakeIds[i]] == 0, i * 3 + 2); // adds v1 weight to the dynamic mapping which will be used in calculations v1StakesWeights[msg.sender][_stakeIds[i]] = _weight; // updates the variable keeping track of the total weight migrated totalV1WeightAdded += _weight; // update value keeping track of v1 stakes ids mapping length user.v1IdsLength++; // adds stake id to mapping keeping track of each v1 stake id user.v1StakesIds[user.v1IdsLength - 1] = _stakeIds[i]; } // emits an event emit LogMigrateLockedStakes(msg.sender, totalV1WeightAdded); } /** * @dev Utility used by functions that can't allow blacklisted users to call. * @dev Blocks user addresses stored in the _isBlacklisted mapping to call actions like * minting v1 yield stake ids and migrating locked stakes. */ function _requireNotBlacklisted(address _user) internal view virtual { // we're using selector to simplify input and access validation bytes4 fnSelector = this.migrateLockedStakes.selector; // makes sure that msg.sender isn't a blacklisted address fnSelector.verifyAccess(!isBlacklisted[_user]); } /** * @dev Empty reserved space in storage. The size of the __gap array is calculated so that * the amount of storage used by a contract always adds up to the 50. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[48] private __gap; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.4; import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import { IERC20Upgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol"; import { SafeERC20Upgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol"; import { SafeCast } from "../libraries/SafeCast.sol"; import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; import { ReentrancyGuardUpgradeable } from "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol"; import { PausableUpgradeable } from "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol"; import { Timestamp } from "./Timestamp.sol"; import { VaultRecipient } from "./VaultRecipient.sol"; import { ErrorHandler } from "../libraries/ErrorHandler.sol"; import { Stake } from "../libraries/Stake.sol"; import { IILVPool } from "../interfaces/IILVPool.sol"; import { IFactory } from "../interfaces/IFactory.sol"; import { ICorePool } from "../interfaces/ICorePool.sol"; import { ICorePoolV1 } from "../interfaces/ICorePoolV1.sol"; /** * @title Core Pool * * @notice An abstract contract containing common logic for ILV and ILV/ETH SLP pools. * * @dev Base smart contract for ILV and LP pool. Stores each pool user by mapping * its address to the user struct. User struct stores v2 stakes, which fit * in 1 storage slot each (by using the Stake lib), total weights, pending * yield and revenue distributions, and v1 stake ids. ILV and LP stakes can * be made through flexible stake mode, which only increments the flexible * balance of a given user, or through locked staking. Locked staking creates * a new Stake element fitting 1 storage slot with its value and lock duration. * When calculating pending rewards, CorePool checks v1 locked stakes weights * to increment in the calculations and stores pending yield and pending revenue * distributions. Every time a stake or unstake related function is called, * it updates pending values, but don't require instant claimings. Rewards * claiming are executed in separate functions, and in the case of yield, * it also requires the user checking whether ILV or sILV is wanted as the yield reward. * * @dev Deployment and initialization. * After proxy is deployed and attached to the implementation, it should be * registered by the PoolFactory contract * Additionally, 3 token instance addresses must be defined on deployment: * - ILV token address * - sILV token address, used to mint sILV rewards * - pool token address, it can be ILV token address, ILV/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 ILV pool and 80% for ILV/ETH pool initially. * It can be changed through ICCPs and new flash pools added in the protocol. * 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 ILV Pool we use 200 as weight and for ILV/ETH SLP pool - 800. * */ abstract contract CorePool is Initializable, UUPSUpgradeable, VaultRecipient, ReentrancyGuardUpgradeable, PausableUpgradeable, Timestamp { using SafeERC20Upgradeable for IERC20Upgradeable; using SafeCast for uint256; using Stake for Stake.Data; using ErrorHandler for bytes4; using Stake for uint256; /// @dev Data structure representing token holder using a pool. struct User { /// @dev pending yield rewards to be claimed uint128 pendingYield; /// @dev pending revenue distribution to be claimed uint128 pendingRevDis; /// @dev Total weight uint248 totalWeight; /// @dev number of v1StakesIds uint8 v1IdsLength; /// @dev Checkpoint variable for yield calculation uint256 yieldRewardsPerWeightPaid; /// @dev Checkpoint variable for vault rewards calculation uint256 vaultRewardsPerWeightPaid; /// @dev An array of holder's stakes Stake.Data[] stakes; /// @dev A mapping of holder's stakes ids in V1 mapping(uint256 => uint256) v1StakesIds; } /// @dev Data structure used in `unstakeLockedMultiple()` function. struct UnstakeParameter { uint256 stakeId; uint256 value; } /// @dev Token holder storage, maps token holder address to their data record. mapping(address => User) public users; /// @dev Maps `keccak256(userAddress,stakeId)` to a uint256 value that tells /// a v1 locked stake weight that has already been migrated to v2 /// and is updated through _useV1Weight. mapping(address => mapping(uint256 => uint256)) public v1StakesWeights; /// @dev Link to sILV ERC20 Token instance. address internal _silv; /// @dev Link to ILV ERC20 Token instance. address internal _ilv; /// @dev Address of v1 core pool with same poolToken. address internal corePoolV1; /// @dev Link to the pool token instance, for example ILV or ILV/ETH pair. address public poolToken; /// @dev Pool weight, initial values are 200 for ILV pool and 800 for ILV/ETH. uint32 public weight; /// @dev Timestamp of the last yield distribution event. uint64 public lastYieldDistribution; /// @dev Used to calculate yield rewards. /// @dev This value is different from "reward per token" used in flash pool. /// @dev Note: stakes are different in duration and "weight" reflects that. uint256 public yieldRewardsPerWeight; /// @dev Used to calculate rewards, keeps track of the tokens weight locked in staking. uint256 public globalWeight; /// @dev Used to calculate rewards, keeps track of the correct token weight in the v1 /// core pool. uint256 public v1GlobalWeight; /// @dev Pool tokens value available in the pool; /// pool token examples are ILV (ILV core pool) or ILV/ETH pair (LP core pool). /// @dev For LP core pool this value doesnt' count for ILV tokens received as Vault rewards /// while for ILV core pool it does count for such tokens as well. uint256 public poolTokenReserve; /// @dev Flag indicating pool type, false means "core pool". bool public constant isFlashPool = false; /** * @dev Fired in _stake() and stakeAsPool() in ILVPool contract. * @param by address that executed the stake function (user or pool) * @param from token holder address, the tokens will be returned to that address * @param stakeId id of the new stake created * @param value value of tokens staked * @param lockUntil timestamp indicating when tokens should unlock (max 2 years) */ event LogStake(address indexed by, address indexed from, uint256 stakeId, uint256 value, uint64 lockUntil); /** * @dev Fired in `unstakeLocked()`. * * @param to address receiving the tokens (user) * @param stakeId id value of the stake * @param value number of tokens unstaked * @param isYield whether stake struct unstaked was coming from yield or not */ event LogUnstakeLocked(address indexed to, uint256 stakeId, uint256 value, bool isYield); /** * @dev Fired in `unstakeLockedMultiple()`. * * @param to address receiving the tokens (user) * @param totalValue total number of tokens unstaked * @param unstakingYield whether unstaked tokens had isYield flag true or false */ event LogUnstakeLockedMultiple(address indexed to, uint256 totalValue, bool unstakingYield); /** * @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 timestamp */ event LogSync(address indexed by, uint256 yieldRewardsPerWeight, uint64 lastYieldDistribution); /** * @dev Fired in `_claimYieldRewards()`. * * @param by an address which claimed the rewards (staker or ilv pool contract * in case of a multiple claim call) * @param from an address which received the yield * @param sILV flag indicating if reward was paid (minted) in sILV * @param value value of yield paid */ event LogClaimYieldRewards(address indexed by, address indexed from, bool sILV, uint256 value); /** * @dev Fired in `_claimVaultRewards()`. * * @param by an address which claimed the rewards (staker or ilv pool contract * in case of a multiple claim call) * @param from an address which received the yield * @param value value of yield paid */ event LogClaimVaultRewards(address indexed by, address indexed from, uint256 value); /** * @dev Fired in `_updateRewards()`. * * @param by an address which processed the rewards (staker or ilv pool contract * in case of a multiple claim call) * @param from an address which received the yield * @param yieldValue value of yield processed * @param revDisValue value of revenue distribution processed */ event LogUpdateRewards(address indexed by, address indexed from, uint256 yieldValue, uint256 revDisValue); /** * @dev fired in `moveFundsFromWallet()`. * * @param from user asking migration * @param to new user address * @param previousTotalWeight total weight of `from` before moving to a new address * @param newTotalWeight total weight of `to` after moving to a new address * @param previousYield pending yield of `from` before moving to a new address * @param newYield pending yield of `to` after moving to a new address * @param previousRevDis pending revenue distribution of `from` before moving to a new address * @param newRevDis pending revenue distribution of `to` after moving to a new address */ event LogMoveFundsFromWallet( address indexed from, address indexed to, uint248 previousTotalWeight, uint248 newTotalWeight, uint128 previousYield, uint128 newYield, uint128 previousRevDis, uint128 newRevDis ); /** * @dev Fired in `receiveVaultRewards()`. * * @param by an address that sent the rewards, always a vault * @param value amount of tokens received */ event LogReceiveVaultRewards(address indexed by, uint256 value); /** * @dev Used in child contracts to initialize the pool. * * @param ilv_ ILV ERC20 Token address * @param silv_ sILV ERC20 Token address * @param _poolToken token the pool operates on, for example ILV or ILV/ETH pair * @param _corePoolV1 v1 core pool address * @param factory_ PoolFactory contract address * @param _initTime initial timestamp used to calculate the rewards * note: _initTime is set to the future effectively meaning _sync() calls will do nothing * before _initTime * @param _weight number representing the pool's weight, which in _sync calls * is used by checking the total pools weight in the PoolFactory contract */ function __CorePool_init( address ilv_, address silv_, address _poolToken, address _corePoolV1, address factory_, uint64 _initTime, uint32 _weight ) internal initializer { // we're using selector to simplify input and state validation // internal function simulated selector is // `bytes4(keccak256("__CorePool_init(address,address,address,address,address,uint64,uint32)"))` bytes4 fnSelector = 0x1512be06; // verify the inputs fnSelector.verifyNonZeroInput(uint160(_poolToken), 2); fnSelector.verifyNonZeroInput(uint160(_corePoolV1), 3); fnSelector.verifyNonZeroInput(_initTime, 5); fnSelector.verifyNonZeroInput(_weight, 6); __FactoryControlled_init(factory_); __ReentrancyGuard_init(); __Pausable_init(); // save the inputs into internal state variables _ilv = ilv_; _silv = silv_; poolToken = _poolToken; corePoolV1 = _corePoolV1; weight = _weight; // init the dependent internal state variables lastYieldDistribution = _initTime; } /** * @notice Calculates current yield rewards value available for address specified. * * @dev See `_pendingRewards()` for further details. * * @dev External `pendingRewards()` returns pendingYield and pendingRevDis * accumulated with already stored user.pendingYield and user.pendingRevDis. * * @param _staker an address to calculate yield rewards value for */ function pendingRewards(address _staker) external view virtual returns (uint256 pendingYield, uint256 pendingRevDis) { this.pendingRewards.selector.verifyNonZeroInput(uint160(_staker), 0); // `newYieldRewardsPerWeight` will be the stored or recalculated value for `yieldRewardsPerWeight` uint256 newYieldRewardsPerWeight; // gas savings uint256 _lastYieldDistribution = lastYieldDistribution; // based on the rewards per weight value, calculate pending rewards; User storage user = users[_staker]; // initializes both variables from one storage slot (uint256 v1StakesLength, uint256 userWeight) = (uint256(user.v1IdsLength), uint256(user.totalWeight)); // total user v1 weight to be used uint256 totalV1Weight; if (v1StakesLength > 0) { // loops through v1StakesIds and adds v1 weight for (uint256 i = 0; i < v1StakesLength; i++) { uint256 stakeId = user.v1StakesIds[i]; (, uint256 _weight, , , ) = ICorePoolV1(corePoolV1).getDeposit(_staker, stakeId); uint256 storedWeight = v1StakesWeights[_staker][stakeId]; totalV1Weight += _weight <= storedWeight ? _weight : storedWeight; } } // 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 (_now256() > _lastYieldDistribution && globalWeight != 0) { uint256 endTime = _factory.endTime(); uint256 multiplier = _now256() > endTime ? endTime - _lastYieldDistribution : _now256() - _lastYieldDistribution; uint256 ilvRewards = (multiplier * weight * _factory.ilvPerSecond()) / _factory.totalWeight(); // recalculated value for `yieldRewardsPerWeight` newYieldRewardsPerWeight = ilvRewards.getRewardPerWeight((globalWeight + v1GlobalWeight)) + yieldRewardsPerWeight; } else { // if smart contract state is up to date, we don't recalculate newYieldRewardsPerWeight = yieldRewardsPerWeight; } pendingYield = (userWeight + totalV1Weight).earned(newYieldRewardsPerWeight, user.yieldRewardsPerWeightPaid) + user.pendingYield; pendingRevDis = (userWeight + totalV1Weight).earned(vaultRewardsPerWeight, user.vaultRewardsPerWeightPaid) + user.pendingRevDis; } /** * @notice Returns total staked token balance for the given address. * @dev Loops through stakes and returns total balance. * @notice Expected to be called externally through `eth_call`. Gas shouldn't * be an issue here. * * @param _user an address to query balance for * @return balance total staked token balance */ function balanceOf(address _user) external view virtual returns (uint256 balance) { // gets storage pointer to _user User storage user = users[_user]; // loops over each user stake and adds to the total balance. for (uint256 i = 0; i < user.stakes.length; i++) { balance += user.stakes[i].value; } } /** * @dev Returns the sum of poolTokenReserve with the deposit reserves in v1. * @dev In ILV Pool contract the eDAO stores the v1 reserve value, and * in the SLP pool we're able to query it from the v1 lp pool contract. */ function getTotalReserves() external view virtual returns (uint256 totalReserves); /** * @notice Returns information on the given stake for the given address. * * @dev See getStakesLength. * * @param _user an address to query stake for * @param _stakeId zero-indexed stake ID for the address specified * @return stake info as Stake structure */ function getStake(address _user, uint256 _stakeId) external view virtual returns (Stake.Data memory) { // read stake at specified index and return return users[_user].stakes[_stakeId]; } /** * @notice Returns a v1 stake id in the `user.v1StakesIds` array. * * @dev Get v1 stake id position through `getV1StakePosition()`. * * @param _user an address to query stake for * @param _position position index in the array * @return stakeId value */ function getV1StakeId(address _user, uint256 _position) external view virtual returns (uint256) { // returns the v1 stake id indicated at _position value return users[_user].v1StakesIds[_position]; } /** * @notice Returns a v1 stake position in the `user.v1StakesIds` array. * * @dev Helper function to call `getV1StakeId()`. * @dev Reverts if stakeId isn't found. * * @param _user an address to query stake for * @param _desiredId desired stakeId position in the array to find * @return position stake info as Stake structure */ function getV1StakePosition(address _user, uint256 _desiredId) external view virtual returns (uint256 position) { // gets storage pointer to user User storage user = users[_user]; // loops over each v1 stake id and checks if it's the one // that the caller is looking for for (uint256 i = 0; i < user.v1IdsLength; i++) { if (user.v1StakesIds[i] == _desiredId) { // if it's the desired stake id, return the array index (i.e position) return i; } } revert(); } /** * @notice Returns number of stakes for the given address. Allows iteration over stakes. * * @dev See `getStake()`. * * @param _user an address to query stake length for * @return number of stakes for the given address */ function getStakesLength(address _user) external view virtual returns (uint256) { // read stakes array length and return return users[_user].stakes.length; } /** * @dev Set paused/unpaused state in the pool contract. * * @param _shouldPause whether the contract should be paused/unpausd */ function pause(bool _shouldPause) external { // checks if caller is authorized to pause _requireIsFactoryController(); // checks bool input and pause/unpause the contract depending on // msg.sender's request if (_shouldPause) { _pause(); } else { _unpause(); } } /** * @notice Stakes specified value of tokens for the specified value of time, * and pays pending yield rewards if any. * * @dev Requires value to stake and lock duration to be greater than zero. * * @param _value value of tokens to stake * @param _lockDuration stake duration as unix timestamp */ function stake(uint256 _value, uint64 _lockDuration) external virtual nonReentrant { // checks if the contract is in a paused state _requireNotPaused(); // we're using selector to simplify input and state validation bytes4 fnSelector = this.stake.selector; // validate the inputs fnSelector.verifyNonZeroInput(_value, 1); fnSelector.verifyInput(_lockDuration >= Stake.MIN_STAKE_PERIOD && _lockDuration <= Stake.MAX_STAKE_PERIOD, 2); // get a link to user data struct, we will write to it later User storage user = users[msg.sender]; // uses v1 weight values for rewards calculations uint256 v1WeightToAdd = _useV1Weight(msg.sender); // update user state _updateReward(msg.sender, v1WeightToAdd); // calculates until when a stake is going to be locked uint64 lockUntil = (_now256()).toUint64() + _lockDuration; // stake weight formula rewards for locking uint256 stakeWeight = (((lockUntil - _now256()) * Stake.WEIGHT_MULTIPLIER) / Stake.MAX_STAKE_PERIOD + Stake.BASE_WEIGHT) * _value; // makes sure stakeWeight is valid assert(stakeWeight > 0); // create and save the stake (append it to stakes array) Stake.Data memory userStake = Stake.Data({ value: (_value).toUint120(), lockedFrom: (_now256()).toUint64(), lockedUntil: lockUntil, isYield: false }); // pushes new stake to `stakes` array user.stakes.push(userStake); // update user weight user.totalWeight += (stakeWeight).toUint248(); // update global weight value and global pool token count globalWeight += stakeWeight; poolTokenReserve += _value; // transfer `_value` IERC20Upgradeable(poolToken).safeTransferFrom(address(msg.sender), address(this), _value); // emit an event emit LogStake(msg.sender, msg.sender, (user.stakes.length - 1), _value, lockUntil); } /** * @dev Moves msg.sender stake data to a new address. * @dev V1 stakes are never migrated to the new address. We process all rewards, * clean the previous user (msg.sender), add the previous user data to * the desired address and update subYieldRewards/subVaultRewards values * in order to make sure both addresses will have rewards cleaned. * * @param _to new user address, needs to be a fresh address with no stakes */ function moveFundsFromWallet(address _to) public virtual { // checks if the contract is in a paused state _requireNotPaused(); // gets storage pointer to msg.sender user struct User storage previousUser = users[msg.sender]; // gets storage pointer to desired address user struct User storage newUser = users[_to]; // uses v1 weight values for rewards calculations uint256 v1WeightToAdd = _useV1Weight(msg.sender); // We process update global and user's rewards // before moving the user funds to a new wallet. // This way we can ensure that all v1 ids weight have been used before the v2 // stakes to a new address. _updateReward(msg.sender, v1WeightToAdd); // we're using selector to simplify input and state validation bytes4 fnSelector = this.moveFundsFromWallet.selector; // validate input is set fnSelector.verifyNonZeroInput(uint160(_to), 0); // verify new user records are empty fnSelector.verifyState( newUser.totalWeight == 0 && newUser.v1IdsLength == 0 && newUser.stakes.length == 0 && newUser.yieldRewardsPerWeightPaid == 0 && newUser.vaultRewardsPerWeightPaid == 0, 0 ); // saves previous user total weight uint248 previousTotalWeight = previousUser.totalWeight; // saves previous user pending yield uint128 previousYield = previousUser.pendingYield; // saves previous user pending rev dis uint128 previousRevDis = previousUser.pendingRevDis; // It's expected to have all previous user values // migrated to the new user address (_to). // We recalculate yield and vault rewards values // to make sure new user pending yield and pending rev dis to be stored // at newUser.pendingYield and newUser.pendingRevDis is 0, since we just processed // all pending rewards calling _updateReward. newUser.totalWeight = previousTotalWeight; newUser.pendingYield = previousYield; newUser.pendingRevDis = previousRevDis; newUser.yieldRewardsPerWeightPaid = yieldRewardsPerWeight; newUser.vaultRewardsPerWeightPaid = vaultRewardsPerWeight; newUser.stakes = previousUser.stakes; delete previousUser.totalWeight; delete previousUser.pendingYield; delete previousUser.pendingRevDis; delete previousUser.stakes; // emits an event emit LogMoveFundsFromWallet( msg.sender, _to, previousTotalWeight, newUser.totalWeight, previousYield, newUser.pendingYield, previousRevDis, newUser.pendingRevDis ); } /** * @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 second 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 time), function doesn't throw and exits silently. */ function sync() external virtual { _requireNotPaused(); // calls internal function _sync(); } /** * @dev Calls internal `_claimYieldRewards()` passing `msg.sender` as `_staker`. * * @notice Pool state is updated before calling the internal function. */ function claimYieldRewards(bool _useSILV) external virtual { // checks if the contract is in a paused state _requireNotPaused(); // calls internal function _claimYieldRewards(msg.sender, _useSILV); } /** * @dev Calls internal `_claimVaultRewards()` passing `msg.sender` as `_staker`. * * @notice Pool state is updated before calling the internal function. */ function claimVaultRewards() external virtual { // checks if the contract is in a paused state _requireNotPaused(); // calls internal function _claimVaultRewards(msg.sender); } /** * @dev Claims both revenue distribution and yield rewards in one call. * */ function claimAllRewards(bool _useSILV) external virtual { // checks if the contract is in a paused state _requireNotPaused(); // calls internal yield and vault rewards functions _claimVaultRewards(msg.sender); _claimYieldRewards(msg.sender, _useSILV); } /** * @dev Executed by the vault to transfer vault rewards ILV from the vault * into the pool. * * @dev This function is executed only for ILV core pools. * * @param _value amount of ILV rewards to transfer into the pool */ function receiveVaultRewards(uint256 _value) external virtual { // always sync the pool state vars before moving forward _sync(); // checks if the contract is in a paused state _requireNotPaused(); // checks if msg.sender is the vault contract _requireIsVault(); // we're using selector to simplify input and state validation bytes4 fnSelector = this.receiveVaultRewards.selector; // return silently if there is no reward to receive if (_value == 0) { return; } // verify weight is not zero fnSelector.verifyState(globalWeight > 0 || v1GlobalWeight > 0, 0); // we update vaultRewardsPerWeight value using v1 and v2 global weight, // expecting to distribute revenue distribution correctly to all users // coming from v1 and new v2 users. vaultRewardsPerWeight += _value.getRewardPerWeight(globalWeight + v1GlobalWeight); // transfers ILV from the Vault contract to the pool IERC20Upgradeable(_ilv).safeTransferFrom(msg.sender, address(this), _value); // emits an event emit LogReceiveVaultRewards(msg.sender, _value); } /** * @dev Updates value that keeps track of v1 global locked tokens weight. * * @param _v1GlobalWeight new value to be stored */ function setV1GlobalWeight(uint256 _v1GlobalWeight) external virtual { // only factory controller can update the _v1GlobalWeight _requireIsFactoryController(); // update v1GlobalWeight state variable v1GlobalWeight = _v1GlobalWeight; } /** * @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(uint32 _weight) external virtual { // update pool state using current weight value _sync(); // verify function is executed by the factory this.setWeight.selector.verifyAccess(msg.sender == address(_factory)); // set the new weight value weight = _weight; } /** * @dev Unstakes a stake that has been previously locked, and is now in an unlocked * state. If the stake has the isYield flag set to true, then the contract * requests ILV to be minted by the PoolFactory. Otherwise it transfers ILV or LP * from the contract balance. * * @param _stakeId stake ID to unstake from, zero-indexed * @param _value value of tokens to unstake */ function unstake(uint256 _stakeId, uint256 _value) external virtual { // checks if the contract is in a paused state _requireNotPaused(); // we're using selector to simplify input and state validation bytes4 fnSelector = this.unstake.selector; // verify a value is set fnSelector.verifyNonZeroInput(_value, 0); // get a link to user data struct, we will write to it later User storage user = users[msg.sender]; // get a link to the corresponding stake, we may write to it later Stake.Data storage userStake = user.stakes[_stakeId]; // checks if stake is unlocked already fnSelector.verifyState(_now256() > userStake.lockedUntil, 0); // stake structure may get deleted, so we save isYield flag to be able to use it // we also save stakeValue for gasSavings (uint120 stakeValue, bool isYield) = (userStake.value, userStake.isYield); // verify available balance fnSelector.verifyInput(stakeValue >= _value, 1); // uses v1 weight values for rewards calculations uint256 v1WeightToAdd = _useV1Weight(msg.sender); // and process current pending rewards if any _updateReward(msg.sender, v1WeightToAdd); // store stake weight uint256 previousWeight = userStake.weight(); // value used to save new weight after updates in storage uint256 newWeight; // update the stake, or delete it if its depleted if (stakeValue - _value == 0) { // deletes stake struct, no need to save new weight because it stays 0 delete user.stakes[_stakeId]; } else { userStake.value -= (_value).toUint120(); // saves new weight to memory newWeight = userStake.weight(); } // update user record user.totalWeight = uint248(user.totalWeight - previousWeight + newWeight); // update global weight variable globalWeight = globalWeight - previousWeight + newWeight; // update global pool token count poolTokenReserve -= _value; // if the stake was created by the pool itself as a yield reward if (isYield) { // mint the yield via the factory _factory.mintYieldTo(msg.sender, _value, false); } else { // otherwise just return tokens back to holder IERC20Upgradeable(poolToken).safeTransfer(msg.sender, _value); } // emits an event emit LogUnstakeLocked(msg.sender, _stakeId, _value, isYield); } /** * @dev Executes unstake on multiple stakeIds. See `unstakeLocked()`. * @dev Optimizes gas by requiring all unstakes to be made either in yield stakes * or in non yield stakes. That way we can transfer or mint tokens in one call. * * @notice User is required to either mint ILV or unstake pool tokens in the function call. * There's no way to do both operations in one call. * * @param _stakes array of stakeIds and values to be unstaked in each stake from * the msg.sender * @param _unstakingYield whether all stakeIds have isYield flag set to true or false, * i.e if we're minting ILV or transferring pool tokens */ function unstakeMultiple(UnstakeParameter[] calldata _stakes, bool _unstakingYield) external virtual { // checks if the contract is in a paused state _requireNotPaused(); // we're using selector to simplify input and state validation bytes4 fnSelector = this.unstakeMultiple.selector; // verifies if user has passed any value to be unstaked fnSelector.verifyNonZeroInput(_stakes.length, 0); // gets storage pointer to the user User storage user = users[msg.sender]; // uses v1 weight values for rewards calculations uint256 v1WeightToAdd = _useV1Weight(msg.sender); _updateReward(msg.sender, v1WeightToAdd); // initialize variables that expect to receive the total // weight to be removed from the user and the value to be // unstaked from the pool. uint256 weightToRemove; uint256 valueToUnstake; for (uint256 i = 0; i < _stakes.length; i++) { // destructure calldata parameters (uint256 _stakeId, uint256 _value) = (_stakes[i].stakeId, _stakes[i].value); Stake.Data storage userStake = user.stakes[_stakeId]; // checks if stake is unlocked already fnSelector.verifyState(_now256() > userStake.lockedUntil, i * 3); // checks if unstaking value is valid fnSelector.verifyNonZeroInput(_value, 1); // stake structure may get deleted, so we save isYield flag to be able to use it // we also save stakeValue for gas savings (uint120 stakeValue, bool isYield) = (userStake.value, userStake.isYield); // verifies if the selected stake is yield (i.e ILV to be minted) // or not, the function needs to either mint yield or transfer tokens // and can't do both operations at the same time. fnSelector.verifyState(isYield == _unstakingYield, i * 3 + 1); // checks if there's enough tokens to unstake fnSelector.verifyState(stakeValue >= _value, i * 3 + 2); // store stake weight uint256 previousWeight = userStake.weight(); // value used to save new weight after updates in storage uint256 newWeight; // update the stake, or delete it if its depleted if (stakeValue - _value == 0) { // deletes stake struct, no need to save new weight because it stays 0 delete user.stakes[_stakeId]; } else { // removes _value from the stake with safe cast userStake.value -= (_value).toUint120(); // saves new weight to memory newWeight = userStake.weight(); } // updates the values initialized earlier with the amounts that // need to be subtracted (weight) and transferred (value to unstake) weightToRemove += previousWeight - newWeight; valueToUnstake += _value; } // subtracts weight user.totalWeight -= (weightToRemove).toUint248(); // update global variable globalWeight -= weightToRemove; // update pool token count poolTokenReserve -= valueToUnstake; // if the stake was created by the pool itself as a yield reward if (_unstakingYield) { // mint the yield via the factory _factory.mintYieldTo(msg.sender, valueToUnstake, false); } else { // otherwise just return tokens back to holder IERC20Upgradeable(poolToken).safeTransfer(msg.sender, valueToUnstake); } // emits an event emit LogUnstakeLockedMultiple(msg.sender, valueToUnstake, _unstakingYield); } /** * @dev Used internally, mostly by children implementations, see `sync()`. * * @dev Updates smart contract state (`yieldRewardsPerWeight`, `lastYieldDistribution`), * updates factory state via `updateILVPerSecond` */ function _sync() internal virtual { // gas savings IFactory factory_ = _factory; // update ILV per second value in factory if required if (factory_.shouldUpdateRatio()) { factory_.updateILVPerSecond(); } // check bound conditions and if these are not met - // exit silently, without emitting an event uint256 endTime = factory_.endTime(); if (lastYieldDistribution >= endTime) { return; } if (_now256() <= lastYieldDistribution) { return; } // if locking weight is zero - update only `lastYieldDistribution` and exit if (globalWeight == 0 && v1GlobalWeight == 0) { lastYieldDistribution = (_now256()).toUint64(); return; } // to calculate the reward we need to know how many seconds passed, and reward per second uint256 currentTimestamp = _now256() > endTime ? endTime : _now256(); uint256 secondsPassed = currentTimestamp - lastYieldDistribution; uint256 ilvPerSecond = factory_.ilvPerSecond(); // calculate the reward uint256 ilvReward = (secondsPassed * ilvPerSecond * weight) / factory_.totalWeight(); // update rewards per weight and `lastYieldDistribution` yieldRewardsPerWeight += ilvReward.getRewardPerWeight((globalWeight + v1GlobalWeight)); lastYieldDistribution = (currentTimestamp).toUint64(); // emit an event emit LogSync(msg.sender, yieldRewardsPerWeight, lastYieldDistribution); } /** * @dev claims all pendingYield from _staker using ILV or sILV. * * @notice sILV is minted straight away to _staker wallet, ILV is created as * a new stake and locked for Stake.MAX_STAKE_PERIOD. * * @param _staker user address * @param _useSILV whether the user wants to claim ILV or sILV */ function _claimYieldRewards(address _staker, bool _useSILV) internal virtual { // get link to a user data structure, we will write into it later User storage user = users[_staker]; // uses v1 weight values for rewards calculations uint256 v1WeightToAdd = _useV1Weight(_staker); // update user state _updateReward(_staker, v1WeightToAdd); // check pending yield rewards to claim and save to memory uint256 pendingYieldToClaim = uint256(user.pendingYield); // if pending yield is zero - just return silently if (pendingYieldToClaim == 0) return; // clears user pending yield user.pendingYield = 0; // if sILV is requested if (_useSILV) { // - mint sILV _factory.mintYieldTo(_staker, pendingYieldToClaim, true); } else if (poolToken == _ilv) { // calculate pending yield weight, // 2e6 is the bonus weight when staking for 1 year uint256 stakeWeight = pendingYieldToClaim * Stake.YIELD_STAKE_WEIGHT_MULTIPLIER; // if the pool is ILV Pool - create new ILV stake // and save it - push it into stakes array Stake.Data memory newStake = Stake.Data({ value: (pendingYieldToClaim).toUint120(), lockedFrom: (_now256()).toUint64(), lockedUntil: (_now256() + Stake.MAX_STAKE_PERIOD).toUint64(), // staking yield for 1 year isYield: true }); // add memory stake to storage user.stakes.push(newStake); // updates total user weight with the newly created stake's weight user.totalWeight += (stakeWeight).toUint248(); // update global variable globalWeight += stakeWeight; // update reserve count poolTokenReserve += pendingYieldToClaim; } else { // for other pools - stake as pool address ilvPool = _factory.getPoolAddress(_ilv); IILVPool(ilvPool).stakeAsPool(_staker, pendingYieldToClaim); } // emits an event emit LogClaimYieldRewards(msg.sender, _staker, _useSILV, pendingYieldToClaim); } /** * @dev Claims all pendingRevDis from _staker using ILV. * @dev ILV is sent straight away to _staker address. * * @param _staker user address */ function _claimVaultRewards(address _staker) internal virtual { // get link to a user data structure, we will write into it later User storage user = users[_staker]; // uses v1 weight values for rewards calculations uint256 v1WeightToAdd = _useV1Weight(_staker); // update user state _updateReward(_staker, v1WeightToAdd); // check pending yield rewards to claim and save to memory uint256 pendingRevDis = uint256(user.pendingRevDis); // if pending yield is zero - just return silently if (pendingRevDis == 0) return; // clears user pending revenue distribution user.pendingRevDis = 0; IERC20Upgradeable(_ilv).safeTransfer(_staker, pendingRevDis); // emits an event emit LogClaimVaultRewards(msg.sender, _staker, pendingRevDis); } /** * @dev Calls CorePoolV1 contract, gets v1 stake ids weight and returns. * @dev Used by `_pendingRewards()` to calculate yield and revenue distribution * rewards taking v1 weights into account. * * @notice If v1 weights have changed since last call, we use latest v1 weight for * yield and revenue distribution rewards calculations, and recalculate * user sub rewards values in order to have correct rewards estimations. * * @param _staker user address passed * * @return totalV1Weight uint256 value of v1StakesIds weights */ function _useV1Weight(address _staker) internal virtual returns (uint256 totalV1Weight) { // gets user storage pointer User storage user = users[_staker]; // gas savings uint256 v1StakesLength = user.v1IdsLength; // checks if user has any migrated stake from v1 if (v1StakesLength > 0) { // loops through v1StakesIds and adds v1 weight for (uint256 i = 0; i < v1StakesLength; i++) { // saves v1 stake id to memory uint256 stakeId = user.v1StakesIds[i]; (, uint256 _weight, , , ) = ICorePoolV1(corePoolV1).getDeposit(_staker, stakeId); // gets weight stored initially in the v1StakesWeights mapping // through V2Migrator contract uint256 storedWeight = v1StakesWeights[_staker][stakeId]; // only stores the current v1 weight that is going to be used for calculations // if current v1 weight is equal to or less than the stored weight. // This way we make sure that v1 weight never increases for any reason // (e.g increasing a v1 stake lock through v1 contract) and messes up calculations. totalV1Weight += _weight <= storedWeight ? _weight : storedWeight; // if _weight has updated in v1 to a lower value, we also update // stored weight in v2 for next calculations if (storedWeight > _weight) { // if deposit has been completely unstaked in v1, set stake id weight to 1 // so we can keep track that it has been already migrated. // otherwise just update value to _weight v1StakesWeights[_staker][stakeId] = _weight == 0 ? 1 : _weight; } } } } /** * @dev Checks if pool is paused. * @dev We use this internal function instead of the modifier coming from * Pausable contract in order to decrease contract's bytecode size. */ function _requireNotPaused() internal view virtual { // we're using selector to simplify input and state validation // internal function simulated selector is `bytes4(keccak256("_requireNotPaused()"))` bytes4 fnSelector = 0xabb87a6f; // checks paused variable value from Pausable Open Zeppelin fnSelector.verifyState(!paused(), 0); } /** * @dev Must be called every time user.totalWeight is changed. * @dev Syncs the global pool state, processes the user pending rewards (if any), * and updates check points values stored in the user struct. * @dev If user is coming from v1 pool, it expects to receive this v1 user weight * to include in rewards calculations. * * @param _staker user address * @param _v1WeightToAdd v1 weight to be added to calculations */ function _updateReward(address _staker, uint256 _v1WeightToAdd) internal virtual { // update pool state _sync(); // gets storage reference to the user User storage user = users[_staker]; // gas savings uint256 userTotalWeight = uint256(user.totalWeight) + _v1WeightToAdd; // calculates pending yield to be added uint256 pendingYield = userTotalWeight.earned(yieldRewardsPerWeight, user.yieldRewardsPerWeightPaid); // calculates pending reenue distribution to be added uint256 pendingRevDis = userTotalWeight.earned(vaultRewardsPerWeight, user.vaultRewardsPerWeightPaid); // increases stored user.pendingYield with value returned user.pendingYield += pendingYield.toUint128(); // increases stored user.pendingRevDis with value returned user.pendingRevDis += pendingRevDis.toUint128(); // updates user checkpoint values for future calculations user.yieldRewardsPerWeightPaid = yieldRewardsPerWeight; user.vaultRewardsPerWeightPaid = vaultRewardsPerWeight; // emit an event emit LogUpdateRewards(msg.sender, _staker, pendingYield, pendingRevDis); } /** * @dev See UUPSUpgradeable `_authorizeUpgrade()`. * @dev Just checks if `msg.sender` == `factory.owner()` i.e eDAO multisig address. * @dev eDAO multisig is responsible by handling upgrades and executing other * admin actions approved by the Council. */ function _authorizeUpgrade(address) internal view virtual override { // checks caller is factory.owner() _requireIsFactoryController(); } /** * @dev Empty reserved space in storage. The size of the __gap array is calculated so that * the amount of storage used by a contract always adds up to the 50. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[39] private __gap; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.4; /** * @title Errors Library. * * @notice Introduces some very common input and state validation for smart contracts, * such as non-zero input validation, general boolean expression validation, access validation. * * @notice Throws pre-defined errors instead of string error messages to reduce gas costs. * * @notice Since the library handles only very common errors, concrete smart contracts may * also introduce their own error types and handling. * * @author Basil Gorin */ library ErrorHandler { /** * @notice Thrown on zero input at index specified in a function specified. * * @param fnSelector function selector, defines a function where error was thrown * @param paramIndex function parameter index which caused an error thrown */ error ZeroInput(bytes4 fnSelector, uint8 paramIndex); /** * @notice Thrown on invalid input at index specified in a function specified. * * @param fnSelector function selector, defines a function where error was thrown * @param paramIndex function parameter index which caused an error thrown */ error InvalidInput(bytes4 fnSelector, uint8 paramIndex); /** * @notice Thrown on invalid state in a function specified. * * @param fnSelector function selector, defines a function where error was thrown * @param errorCode unique error code determining the exact place in code where error was thrown */ error InvalidState(bytes4 fnSelector, uint256 errorCode); /** * @notice Thrown on invalid access to a function specified. * * @param fnSelector function selector, defines a function where error was thrown * @param addr an address which access was denied, usually transaction sender */ error AccessDenied(bytes4 fnSelector, address addr); /** * @notice Verifies an input is set (non-zero). * * @param fnSelector function selector, defines a function which called the verification * @param value a value to check if it's set (non-zero) * @param paramIndex function parameter index which is verified */ function verifyNonZeroInput( bytes4 fnSelector, uint256 value, uint8 paramIndex ) internal pure { if (value == 0) { revert ZeroInput(fnSelector, paramIndex); } } /** * @notice Verifies an input is correct. * * @param fnSelector function selector, defines a function which called the verification * @param expr a boolean expression used to verify the input * @param paramIndex function parameter index which is verified */ function verifyInput( bytes4 fnSelector, bool expr, uint8 paramIndex ) internal pure { if (!expr) { revert InvalidInput(fnSelector, paramIndex); } } /** * @notice Verifies smart contract state is correct. * * @param fnSelector function selector, defines a function which called the verification * @param expr a boolean expression used to verify the contract state * @param errorCode unique error code determining the exact place in code which is verified */ function verifyState( bytes4 fnSelector, bool expr, uint256 errorCode ) internal pure { if (!expr) { revert InvalidState(fnSelector, errorCode); } } /** * @notice Verifies an access to the function. * * @param fnSelector function selector, defines a function which called the verification * @param expr a boolean expression used to verify the access */ function verifyAccess(bytes4 fnSelector, bool expr) internal view { if (!expr) { revert AccessDenied(fnSelector, msg.sender); } } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.4; interface ICorePoolV1 { struct V1Stake { // @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; } struct V1User { // @dev Total staked amount uint256 tokenAmount; // @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 V1Stake[] deposits; } function users(address _who) external view returns ( uint256, uint256, uint256, uint256 ); function getDeposit(address _from, uint256 _stakeId) external view returns ( uint256, uint256, uint64, uint64, bool ); function poolToken() external view returns (address); function usersLockingWeight() external view returns (uint256); function poolTokenReserve() external view returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.4; /** * @dev Stake library used by ILV pool and Sushi LP Pool. * * @dev Responsible to manage weight calculation and store important constants * related to stake period, base weight and multipliers utilized. */ library Stake { struct Data { /// @dev token amount staked uint120 value; /// @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; } /** * @dev Stake weight is proportional to stake value and time locked, precisely * "stake value 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 1e6 constant, as an integer. * @dev Corner case 1: if time locked is zero, weight is stake value multiplied by 1e6 + base weight * @dev Corner case 2: if time locked is two years, division of (lockedUntil - lockedFrom) / MAX_STAKE_PERIOD is 1e6, and * weight is a stake value multiplied by 2 * 1e6. */ uint256 internal constant WEIGHT_MULTIPLIER = 1e6; /** * @dev Minimum weight value, if result of multiplication using WEIGHT_MULTIPLIER * is 0 (e.g stake flexible), then BASE_WEIGHT is used. */ uint256 internal constant BASE_WEIGHT = 1e6; /** * @dev Minimum period that someone can lock a stake for. */ uint256 internal constant MIN_STAKE_PERIOD = 30 days; /** * @dev Maximum period that someone can lock a stake for. */ uint256 internal constant MAX_STAKE_PERIOD = 365 days; /** * @dev Rewards per weight are stored multiplied by 1e20 as uint. */ uint256 internal constant REWARD_PER_WEIGHT_MULTIPLIER = 1e20; /** * @dev When we know beforehand that staking is done for yield instead of * executing `weight()` function we use the following constant. */ uint256 internal constant YIELD_STAKE_WEIGHT_MULTIPLIER = 2 * 1e6; function weight(Data storage _self) internal view returns (uint256) { return uint256( (((_self.lockedUntil - _self.lockedFrom) * WEIGHT_MULTIPLIER) / MAX_STAKE_PERIOD + BASE_WEIGHT) * _self.value ); } /** * @dev Converts stake weight (not to be mixed with the pool weight) to * ILV reward value, applying the 10^12 division on weight * * @param _weight stake weight * @param _rewardPerWeight ILV reward per weight * @param _rewardPerWeightPaid last reward per weight value used for user earnings * @return reward value normalized to 10^12 */ function earned( uint256 _weight, uint256 _rewardPerWeight, uint256 _rewardPerWeightPaid ) internal pure returns (uint256) { // apply the formula and return return (_weight * (_rewardPerWeight - _rewardPerWeightPaid)) / REWARD_PER_WEIGHT_MULTIPLIER; } /** * @dev Converts reward ILV value to stake weight (not to be mixed with the pool weight), * applying the 10^12 multiplication on the reward. * - OR - * @dev Converts reward ILV value to reward/weight if stake weight is supplied as second * function parameter instead of reward/weight. * * @param _reward yield reward * @param _globalWeight total weight in the pool * @return reward per weight value */ function getRewardPerWeight(uint256 _reward, uint256 _globalWeight) internal pure returns (uint256) { // apply the reverse formula and return return (_reward * REWARD_PER_WEIGHT_MULTIPLIER) / _globalWeight; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20Upgradeable { /** * @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; import "../IERC20Upgradeable.sol"; import "../../../utils/AddressUpgradeable.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 SafeERC20Upgradeable { using AddressUpgradeable for address; function safeTransfer( IERC20Upgradeable token, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom( IERC20Upgradeable 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( IERC20Upgradeable 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( IERC20Upgradeable 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( IERC20Upgradeable 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(IERC20Upgradeable token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/math/SafeCast.sol) pragma solidity 0.8.4; import { ErrorHandler } from "./ErrorHandler.sol"; /** * @notice Copied from OpenZeppelin's SafeCast.sol, adapted to use just in the required * uint sizes. * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow * checks. * * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can * easily result in undesired exploitation or bugs, since developers usually * assume that overflows raise errors. `SafeCast` restores this intuition by * reverting the transaction when such an operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. * * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing * all math on `uint256` and `int256` and then downcasting. */ library SafeCast { using ErrorHandler for bytes4; /** * @dev Returns the downcasted uint248 from uint256, reverting on * overflow (when the input is greater than largest uint248). * * Counterpart to Solidity's `uint248` operator. * * Requirements: * * - input must fit into 248 bits */ function toUint248(uint256 _value) internal pure returns (uint248) { // we're using selector to simplify input and state validation // internal function simulated selector is `bytes4(keccak256("toUint248(uint256))"))` bytes4 fnSelector = 0x3fd72672; fnSelector.verifyInput(_value <= type(uint248).max, 0); return uint248(_value); } /** * @dev Returns the downcasted uint128 from uint256, reverting on * overflow (when the input is greater than largest uint128). * * Counterpart to Solidity's `uint128` operator. * * Requirements: * * - input must fit into 128 bits */ function toUint128(uint256 _value) internal pure returns (uint128) { // we're using selector to simplify input and state validation // internal function simulated selector is `bytes4(keccak256("toUint128(uint256))"))` bytes4 fnSelector = 0x809fdd33; fnSelector.verifyInput(_value <= type(uint128).max, 0); return uint128(_value); } /** * @dev Returns the downcasted uint120 from uint256, reverting on * overflow (when the input is greater than largest uint120). * * Counterpart to Solidity's `uint120` operator. * * Requirements: * * - input must fit into 120 bits */ function toUint120(uint256 _value) internal pure returns (uint120) { // we're using selector to simplify input and state validation // internal function simulated selector is `bytes4(keccak256("toUint120(uint256))"))` bytes4 fnSelector = 0x1e4e4bad; fnSelector.verifyInput(_value <= type(uint120).max, 0); return uint120(_value); } /** * @dev Returns the downcasted uint64 from uint256, reverting on * overflow (when the input is greater than largest uint64). * * Counterpart to Solidity's `uint64` operator. * * Requirements: * * - input must fit into 64 bits */ function toUint64(uint256 _value) internal pure returns (uint64) { // we're using selector to simplify input and state validation // internal function simulated selector is `bytes4(keccak256("toUint64(uint256))"))` bytes4 fnSelector = 0x2665fad0; fnSelector.verifyInput(_value <= type(uint64).max, 0); return uint64(_value); } /** * @dev Returns the downcasted uint32 from uint256, reverting on * overflow (when the input is greater than largest uint32). * * Counterpart to Solidity's `uint32` operator. * * Requirements: * * - input must fit into 32 bits */ function toUint32(uint256 _value) internal pure returns (uint32) { // we're using selector to simplify input and state validation // internal function simulated selector is `bytes4(keccak256("toUint32(uint256))"))` bytes4 fnSelector = 0xc8193255; fnSelector.verifyInput(_value <= type(uint32).max, 0); return uint32(_value); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../ERC1967/ERC1967UpgradeUpgradeable.sol"; import "./Initializable.sol"; /** * @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an * {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy. * * A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is * reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing * `UUPSUpgradeable` with a custom implementation of upgrades. * * The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism. * * _Available since v4.1._ */ abstract contract UUPSUpgradeable is Initializable, ERC1967UpgradeUpgradeable { function __UUPSUpgradeable_init() internal initializer { __ERC1967Upgrade_init_unchained(); __UUPSUpgradeable_init_unchained(); } function __UUPSUpgradeable_init_unchained() internal initializer { } /// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment address private immutable __self = address(this); /** * @dev Check that the execution is being performed through a delegatecall call and that the execution context is * a proxy contract with an implementation (as defined in ERC1967) pointing to self. This should only be the case * for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a * function through ERC1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to * fail. */ modifier onlyProxy() { require(address(this) != __self, "Function must be called through delegatecall"); require(_getImplementation() == __self, "Function must be called through active proxy"); _; } /** * @dev Upgrade the implementation of the proxy to `newImplementation`. * * Calls {_authorizeUpgrade}. * * Emits an {Upgraded} event. */ function upgradeTo(address newImplementation) external virtual onlyProxy { _authorizeUpgrade(newImplementation); _upgradeToAndCallSecure(newImplementation, new bytes(0), false); } /** * @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call * encoded in `data`. * * Calls {_authorizeUpgrade}. * * Emits an {Upgraded} event. */ function upgradeToAndCall(address newImplementation, bytes memory data) external payable virtual onlyProxy { _authorizeUpgrade(newImplementation); _upgradeToAndCallSecure(newImplementation, data, true); } /** * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by * {upgradeTo} and {upgradeToAndCall}. * * Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}. * * ```solidity * function _authorizeUpgrade(address) internal override onlyOwner {} * ``` */ function _authorizeUpgrade(address newImplementation) internal virtual; uint256[50] private __gap; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../proxy/utils/Initializable.sol"; /** * @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 ReentrancyGuardUpgradeable is Initializable { // 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; function __ReentrancyGuard_init() internal initializer { __ReentrancyGuard_init_unchained(); } function __ReentrancyGuard_init_unchained() internal initializer { _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; } uint256[49] private __gap; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../utils/ContextUpgradeable.sol"; import "../proxy/utils/Initializable.sol"; /** * @dev Contract module which allows children to implement an emergency stop * mechanism that can be triggered by an authorized account. * * This module is used through inheritance. It will make available the * modifiers `whenNotPaused` and `whenPaused`, which can be applied to * the functions of your contract. Note that they will not be pausable by * simply including this module, only once the modifiers are put in place. */ abstract contract PausableUpgradeable is Initializable, ContextUpgradeable { /** * @dev Emitted when the pause is triggered by `account`. */ event Paused(address account); /** * @dev Emitted when the pause is lifted by `account`. */ event Unpaused(address account); bool private _paused; /** * @dev Initializes the contract in unpaused state. */ function __Pausable_init() internal initializer { __Context_init_unchained(); __Pausable_init_unchained(); } function __Pausable_init_unchained() internal initializer { _paused = false; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view virtual returns (bool) { return _paused; } /** * @dev Modifier to make a function callable only when the contract is not paused. * * Requirements: * * - The contract must not be paused. */ modifier whenNotPaused() { require(!paused(), "Pausable: paused"); _; } /** * @dev Modifier to make a function callable only when the contract is paused. * * Requirements: * * - The contract must be paused. */ modifier whenPaused() { require(paused(), "Pausable: not paused"); _; } /** * @dev Triggers stopped state. * * Requirements: * * - The contract must not be paused. */ function _pause() internal virtual whenNotPaused { _paused = true; emit Paused(_msgSender()); } /** * @dev Returns to normal state. * * Requirements: * * - The contract must be paused. */ function _unpause() internal virtual whenPaused { _paused = false; emit Unpaused(_msgSender()); } uint256[49] private __gap; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.4; /// @title Function for getting block timestamp. /// @dev Base contract that is overridden for tests. abstract contract Timestamp { /** * @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() internal view virtual returns (uint256) { // return current block timestamp return block.timestamp; } /** * @dev Empty reserved space in storage. The size of the __gap array is calculated so that * the amount of storage used by a contract always adds up to the 50. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.4; import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import { FactoryControlled } from "./FactoryControlled.sol"; import { ErrorHandler } from "../libraries/ErrorHandler.sol"; abstract contract VaultRecipient is Initializable, FactoryControlled { using ErrorHandler for bytes4; /// @dev Link to deployed IlluviumVault instance. address internal _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 Fired in `setVault()`. * * @param by an address which executed the function, always a factory owner * @param previousVault previous vault contract address * @param newVault new vault address */ event LogSetVault(address indexed by, address previousVault, address newVault); /** * @dev Executed only by the factory owner to Set the vault. * * @param vault_ an address of deployed IlluviumVault instance */ function setVault(address vault_) external virtual { // we're using selector to simplify input and state validation bytes4 fnSelector = this.setVault.selector; // verify function is executed by the factory owner fnSelector.verifyState(_factory.owner() == msg.sender, 0); // verify input is set fnSelector.verifyInput(vault_ != address(0), 0); // saves current vault to memory address previousVault = vault_; // update vault address _vault = vault_; // emit an event emit LogSetVault(msg.sender, previousVault, _vault); } /// @dev Utility function to check if caller is the Vault contract function _requireIsVault() internal view virtual { // we're using selector to simplify input and state validation // internal function simulated selector is `bytes4(keccak256("_requireIsVault()"))` bytes4 fnSelector = 0xeeea774b; // checks if caller is the same stored vault address fnSelector.verifyAccess(msg.sender == _vault); } /** * @dev Empty reserved space in storage. The size of the __gap array is calculated so that * the amount of storage used by a contract always adds up to the 50. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[48] private __gap; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.4; import { ICorePool } from "./ICorePool.sol"; interface IILVPool is ICorePool { function stakeAsPool(address _staker, uint256 _value) external; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.4; import { ICorePool } from "./ICorePool.sol"; interface IFactory { function owner() external view returns (address); function ilvPerSecond() external view returns (uint192); function totalWeight() external view returns (uint32); function secondsPerUpdate() external view returns (uint32); function endTime() external view returns (uint32); function lastRatioUpdate() external view returns (uint32); function pools(address _poolToken) external view returns (ICorePool); function poolExists(address _poolAddress) external view returns (bool); function getPoolAddress(address poolToken) external view returns (address); function getPoolData(address _poolToken) external view returns ( address, address, uint32, bool ); function shouldUpdateRatio() external view returns (bool); function registerPool(ICorePool pool) external; function updateILVPerSecond() external; function mintYieldTo( address _to, uint256 _value, bool _useSILV ) external; function changePoolWeight(address pool, uint32 weight) external; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.4; import { Stake } from "../libraries/Stake.sol"; interface ICorePool { function users(address _user) external view returns ( uint128, uint128, uint128, uint248, uint8, uint256, uint256 ); function poolToken() external view returns (address); function isFlashPool() external view returns (bool); function weight() external view returns (uint32); function lastYieldDistribution() external view returns (uint64); function yieldRewardsPerWeight() external view returns (uint256); function globalWeight() external view returns (uint256); function pendingRewards(address _user) external view returns (uint256, uint256); function poolTokenReserve() external view returns (uint256); function balanceOf(address _user) external view returns (uint256); function getTotalReserves() external view returns (uint256); function getStake(address _user, uint256 _stakeId) external view returns (Stake.Data memory); function getStakesLength(address _user) external view returns (uint256); function sync() external; function setWeight(uint32 _weight) external; function receiveVaultRewards(uint256 value) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Collection of functions related to the address type */ library AddressUpgradeable { /** * @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 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.2; import "../beacon/IBeaconUpgradeable.sol"; import "../../utils/AddressUpgradeable.sol"; import "../../utils/StorageSlotUpgradeable.sol"; import "../utils/Initializable.sol"; /** * @dev This abstract contract provides getters and event emitting update functions for * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots. * * _Available since v4.1._ * * @custom:oz-upgrades-unsafe-allow delegatecall */ abstract contract ERC1967UpgradeUpgradeable is Initializable { function __ERC1967Upgrade_init() internal initializer { __ERC1967Upgrade_init_unchained(); } function __ERC1967Upgrade_init_unchained() internal initializer { } // This is the keccak-256 hash of "eip1967.proxy.rollback" subtracted by 1 bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143; /** * @dev Storage slot with the address of the current implementation. * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is * validated in the constructor. */ bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; /** * @dev Emitted when the implementation is upgraded. */ event Upgraded(address indexed implementation); /** * @dev Returns the current implementation address. */ function _getImplementation() internal view returns (address) { return StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value; } /** * @dev Stores a new address in the EIP1967 implementation slot. */ function _setImplementation(address newImplementation) private { require(AddressUpgradeable.isContract(newImplementation), "ERC1967: new implementation is not a contract"); StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; } /** * @dev Perform implementation upgrade * * Emits an {Upgraded} event. */ function _upgradeTo(address newImplementation) internal { _setImplementation(newImplementation); emit Upgraded(newImplementation); } /** * @dev Perform implementation upgrade with additional setup call. * * Emits an {Upgraded} event. */ function _upgradeToAndCall( address newImplementation, bytes memory data, bool forceCall ) internal { _upgradeTo(newImplementation); if (data.length > 0 || forceCall) { _functionDelegateCall(newImplementation, data); } } /** * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call. * * Emits an {Upgraded} event. */ function _upgradeToAndCallSecure( address newImplementation, bytes memory data, bool forceCall ) internal { address oldImplementation = _getImplementation(); // Initial upgrade and setup call _setImplementation(newImplementation); if (data.length > 0 || forceCall) { _functionDelegateCall(newImplementation, data); } // Perform rollback test if not already in progress StorageSlotUpgradeable.BooleanSlot storage rollbackTesting = StorageSlotUpgradeable.getBooleanSlot(_ROLLBACK_SLOT); if (!rollbackTesting.value) { // Trigger rollback using upgradeTo from the new implementation rollbackTesting.value = true; _functionDelegateCall( newImplementation, abi.encodeWithSignature("upgradeTo(address)", oldImplementation) ); rollbackTesting.value = false; // Check rollback was effective require(oldImplementation == _getImplementation(), "ERC1967Upgrade: upgrade breaks further upgrades"); // Finally reset to the new implementation and log the upgrade _upgradeTo(newImplementation); } } /** * @dev Storage slot with the admin of the contract. * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is * validated in the constructor. */ bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; /** * @dev Emitted when the admin account has changed. */ event AdminChanged(address previousAdmin, address newAdmin); /** * @dev Returns the current admin. */ function _getAdmin() internal view returns (address) { return StorageSlotUpgradeable.getAddressSlot(_ADMIN_SLOT).value; } /** * @dev Stores a new address in the EIP1967 admin slot. */ function _setAdmin(address newAdmin) private { require(newAdmin != address(0), "ERC1967: new admin is the zero address"); StorageSlotUpgradeable.getAddressSlot(_ADMIN_SLOT).value = newAdmin; } /** * @dev Changes the admin of the proxy. * * Emits an {AdminChanged} event. */ function _changeAdmin(address newAdmin) internal { emit AdminChanged(_getAdmin(), newAdmin); _setAdmin(newAdmin); } /** * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy. * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor. */ bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50; /** * @dev Emitted when the beacon is upgraded. */ event BeaconUpgraded(address indexed beacon); /** * @dev Returns the current beacon. */ function _getBeacon() internal view returns (address) { return StorageSlotUpgradeable.getAddressSlot(_BEACON_SLOT).value; } /** * @dev Stores a new beacon in the EIP1967 beacon slot. */ function _setBeacon(address newBeacon) private { require(AddressUpgradeable.isContract(newBeacon), "ERC1967: new beacon is not a contract"); require( AddressUpgradeable.isContract(IBeaconUpgradeable(newBeacon).implementation()), "ERC1967: beacon implementation is not a contract" ); StorageSlotUpgradeable.getAddressSlot(_BEACON_SLOT).value = newBeacon; } /** * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that). * * Emits a {BeaconUpgraded} event. */ function _upgradeBeaconToAndCall( address newBeacon, bytes memory data, bool forceCall ) internal { _setBeacon(newBeacon); emit BeaconUpgraded(newBeacon); if (data.length > 0 || forceCall) { _functionDelegateCall(IBeaconUpgradeable(newBeacon).implementation(), data); } } /** * @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) private returns (bytes memory) { require(AddressUpgradeable.isContract(target), "Address: delegate call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.delegatecall(data); return AddressUpgradeable.verifyCallResult(success, returndata, "Address: low-level delegate call failed"); } uint256[50] private __gap; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev This is the interface that {BeaconProxy} expects of its beacon. */ interface IBeaconUpgradeable { /** * @dev Must return an address that can be used as a delegate call target. * * {BeaconProxy} will check that this address is a contract. */ function implementation() external view returns (address); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Library for reading and writing primitive types to specific storage slots. * * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts. * This library helps with reading and writing to such slots without the need for inline assembly. * * The functions in this library return Slot structs that contain a `value` member that can be used to read or write. * * Example usage to set ERC1967 implementation slot: * ``` * contract ERC1967 { * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; * * function _getImplementation() internal view returns (address) { * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; * } * * function _setImplementation(address newImplementation) internal { * require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract"); * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; * } * } * ``` * * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._ */ library StorageSlotUpgradeable { struct AddressSlot { address value; } struct BooleanSlot { bool value; } struct Bytes32Slot { bytes32 value; } struct Uint256Slot { uint256 value; } /** * @dev Returns an `AddressSlot` with member `value` located at `slot`. */ function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) { assembly { r.slot := slot } } /** * @dev Returns an `BooleanSlot` with member `value` located at `slot`. */ function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) { assembly { r.slot := slot } } /** * @dev Returns an `Bytes32Slot` with member `value` located at `slot`. */ function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) { assembly { r.slot := slot } } /** * @dev Returns an `Uint256Slot` with member `value` located at `slot`. */ function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) { assembly { r.slot := slot } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../proxy/utils/Initializable.sol"; /** * @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 ContextUpgradeable is Initializable { function __Context_init() internal initializer { __Context_init_unchained(); } function __Context_init_unchained() internal initializer { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } uint256[50] private __gap; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.4; import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import { IFactory } from "../interfaces/IFactory.sol"; import { ErrorHandler } from "../libraries/ErrorHandler.sol"; /** * @title FactoryControlled * * @dev Abstract smart contract responsible to hold IFactory factory address. * @dev Stores PoolFactory address on initialization. * */ abstract contract FactoryControlled is Initializable { using ErrorHandler for bytes4; /// @dev Link to the pool factory IlluviumPoolFactory instance. IFactory internal _factory; /// @dev Attachs PoolFactory address to the FactoryControlled contract. function __FactoryControlled_init(address factory_) internal initializer { // we're using selector to simplify input and state validation // internal function simulated selector is `bytes4(keccak256("__FactoryControlled_init(address)"))` bytes4 fnSelector = 0xbb6c0dbf; fnSelector.verifyNonZeroInput(uint160(factory_), 0); _factory = IFactory(factory_); } /// @dev checks if caller is factory admin (eDAO multisig address). function _requireIsFactoryController() internal view virtual { // we're using selector to simplify input and state validation // internal function simulated selector is `bytes4(keccak256("_requireIsFactoryController()"))` bytes4 fnSelector = 0x39e71deb; fnSelector.verifyAccess(msg.sender == _factory.owner()); } /** * @dev Empty reserved space in storage. The size of the __gap array is calculated so that * the amount of storage used by a contract always adds up to the 50. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; }
{ "metadata": { "bytecodeHash": "none" }, "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"bytes4","name":"fnSelector","type":"bytes4"},{"internalType":"address","name":"addr","type":"address"}],"name":"AccessDenied","type":"error"},{"inputs":[{"internalType":"bytes4","name":"fnSelector","type":"bytes4"},{"internalType":"uint8","name":"paramIndex","type":"uint8"}],"name":"InvalidInput","type":"error"},{"inputs":[{"internalType":"bytes4","name":"fnSelector","type":"bytes4"},{"internalType":"uint256","name":"errorCode","type":"uint256"}],"name":"InvalidState","type":"error"},{"inputs":[{"internalType":"bytes4","name":"fnSelector","type":"bytes4"},{"internalType":"uint8","name":"paramIndex","type":"uint8"}],"name":"ZeroInput","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"previousAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"}],"name":"AdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"beacon","type":"address"}],"name":"BeaconUpgraded","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":"value","type":"uint256"}],"name":"LogClaimVaultRewards","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"by","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"bool","name":"sILV","type":"bool"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"LogClaimYieldRewards","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint256","name":"totalV1WeightAdded","type":"uint256"}],"name":"LogMigrateLockedStakes","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint248","name":"previousTotalWeight","type":"uint248"},{"indexed":false,"internalType":"uint248","name":"newTotalWeight","type":"uint248"},{"indexed":false,"internalType":"uint128","name":"previousYield","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"newYield","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"previousRevDis","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"newRevDis","type":"uint128"}],"name":"LogMoveFundsFromWallet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"by","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"LogReceiveVaultRewards","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"by","type":"address"},{"indexed":false,"internalType":"address","name":"previousVault","type":"address"},{"indexed":false,"internalType":"address","name":"newVault","type":"address"}],"name":"LogSetVault","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":"stakeId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":false,"internalType":"uint64","name":"lockUntil","type":"uint64"}],"name":"LogStake","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"by","type":"address"},{"indexed":false,"internalType":"uint256","name":"yieldRewardsPerWeight","type":"uint256"},{"indexed":false,"internalType":"uint64","name":"lastYieldDistribution","type":"uint64"}],"name":"LogSync","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"stakeId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":false,"internalType":"bool","name":"isYield","type":"bool"}],"name":"LogUnstakeLocked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"totalValue","type":"uint256"},{"indexed":false,"internalType":"bool","name":"unstakingYield","type":"bool"}],"name":"LogUnstakeLockedMultiple","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":"yieldValue","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"revDisValue","type":"uint256"}],"name":"LogUpdateRewards","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"balance","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"_users","type":"address[]"}],"name":"blacklistUsers","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_useSILV","type":"bool"}],"name":"claimAllRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimVaultRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_staker","type":"address"}],"name":"claimVaultRewardsFromRouter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_useSILV","type":"bool"}],"name":"claimYieldRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_staker","type":"address"},{"internalType":"bool","name":"_useSILV","type":"bool"}],"name":"claimYieldRewardsFromRouter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"},{"internalType":"uint256","name":"_stakeId","type":"uint256"}],"name":"getStake","outputs":[{"components":[{"internalType":"uint120","name":"value","type":"uint120"},{"internalType":"uint64","name":"lockedFrom","type":"uint64"},{"internalType":"uint64","name":"lockedUntil","type":"uint64"},{"internalType":"bool","name":"isYield","type":"bool"}],"internalType":"struct Stake.Data","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"getStakesLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalReserves","outputs":[{"internalType":"uint256","name":"totalReserves","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"},{"internalType":"uint256","name":"_position","type":"uint256"}],"name":"getV1StakeId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"},{"internalType":"uint256","name":"_desiredId","type":"uint256"}],"name":"getV1StakePosition","outputs":[{"internalType":"uint256","name":"position","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"globalWeight","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"ilv_","type":"address"},{"internalType":"address","name":"silv_","type":"address"},{"internalType":"address","name":"_poolToken","type":"address"},{"internalType":"address","name":"_factory","type":"address"},{"internalType":"uint64","name":"_initTime","type":"uint64"},{"internalType":"uint32","name":"_weight","type":"uint32"},{"internalType":"address","name":"_corePoolV1","type":"address"},{"internalType":"uint256","name":"v1StakeMaxPeriod_","type":"uint256"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isBlacklisted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isFlashPool","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastYieldDistribution","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_stakeIds","type":"uint256[]"}],"name":"migrateLockedStakes","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"}],"name":"moveFundsFromWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_shouldPause","type":"bool"}],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_staker","type":"address"}],"name":"pendingRewards","outputs":[{"internalType":"uint256","name":"pendingYield","type":"uint256"},{"internalType":"uint256","name":"pendingRevDis","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":[{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"receiveVaultRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_v1GlobalWeight","type":"uint256"}],"name":"setV1GlobalWeight","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"vault_","type":"address"}],"name":"setVault","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_weight","type":"uint32"}],"name":"setWeight","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_value","type":"uint256"},{"internalType":"uint64","name":"_lockDuration","type":"uint64"}],"name":"stake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"sync","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakeId","type":"uint256"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"unstake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"stakeId","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct CorePool.UnstakeParameter[]","name":"_stakes","type":"tuple[]"},{"internalType":"bool","name":"_unstakingYield","type":"bool"}],"name":"unstakeMultiple","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"}],"name":"upgradeTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"upgradeToAndCall","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"users","outputs":[{"internalType":"uint128","name":"pendingYield","type":"uint128"},{"internalType":"uint128","name":"pendingRevDis","type":"uint128"},{"internalType":"uint248","name":"totalWeight","type":"uint248"},{"internalType":"uint8","name":"v1IdsLength","type":"uint8"},{"internalType":"uint256","name":"yieldRewardsPerWeightPaid","type":"uint256"},{"internalType":"uint256","name":"vaultRewardsPerWeightPaid","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"v1GlobalWeight","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"v1StakesWeights","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vaultRewardsPerWeight","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"weight","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"yieldRewardsPerWeight","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
60a06040523060601b60805234801561001757600080fd5b5060805160601c61488f61004b6000396000818161130e0152818161134e0152818161160c015261164c015261488f6000f3fe60806040526004361061023a5760003560e01c806370a082311161012e578063bb3d676a116100ab578063ed91b7de1161006f578063ed91b7de146107ee578063ef0c792414610805578063fa213bd61461084d578063fe575a8714610864578063fff6cae91461089557600080fd5b8063bb3d676a146106d9578063cbdf382c146106f9578063ce11154114610732578063cfd4766314610749578063dc60e2cb146107b557600080fd5b8063a1aab33f116100f2578063a1aab33f14610594578063a4292812146105ce578063a87430ba146105ee578063ae9f245a146106a2578063b1aca504146106b957600080fd5b806370a08231146104da57806374bd128f146104fa578063909767d91461051a578063952e68cf146105545780639e2c8a5b1461057457600080fd5b80633021a560116101bc5780634f1ef286116101805780634f1ef2861461044e57806353961e06146104615780635c975abb146104815780636817031b1461049a5780636955cf92146104ba57600080fd5b80633021a5601461039957806331d7a262146103b95780633659cfe6146103ee5780633b350f901461040e5780634087aeb71461042e57600080fd5b80631965a599116102035780631965a599146102ea5780631bfe80b8146102ff5780631da10d911461031f578063242693d31461034457806329eb5f2c1461035957600080fd5b806251ccba1461023f57806302329a291461026157806305472358146102815780630834ef45146102aa578063114952be146102ca575b600080fd5b34801561024b57600080fd5b5061025f61025a366004614375565b6108aa565b005b34801561026d57600080fd5b5061025f61027c366004614375565b6108bf565b34801561028d57600080fd5b5061029760985481565b6040519081526020015b60405180910390f35b3480156102b657600080fd5b5061025f6102c53660046140be565b6108dd565b3480156102d657600080fd5b5061025f6102e53660046140f6565b6108f6565b3480156102f657600080fd5b5061025f610983565b34801561030b57600080fd5b5061025f61031a3660046142f5565b610996565b34801561032b57600080fd5b50610334600081565b60405190151581526020016102a1565b34801561035057600080fd5b50610297610d68565b34801561036557600080fd5b506101965461038190600160c01b90046001600160401b031681565b6040516001600160401b0390911681526020016102a1565b3480156103a557600080fd5b5061025f6103b43660046143d4565b610df9565b3480156103c557600080fd5b506103d96103d43660046140be565b610ed1565b604080519283526020830191909152016102a1565b3480156103fa57600080fd5b5061025f6104093660046140be565b611303565b34801561041a57600080fd5b5061025f6104293660046140be565b6113c9565b34801561043a57600080fd5b5061025f6104493660046144a9565b6115b2565b61025f61045c3660046141cd565b611601565b34801561046d57600080fd5b5061025f61047c366004614195565b6116bb565b34801561048d57600080fd5b5061012d5460ff16610334565b3480156104a657600080fd5b5061025f6104b53660046140be565b6116d5565b3480156104c657600080fd5b5061025f6104d53660046142b6565b611803565b3480156104e657600080fd5b506102976104f53660046140be565b61183a565b34801561050657600080fd5b5061025f6105153660046143d4565b6118be565b34801561052657600080fd5b506102976105353660046140be565b6001600160a01b03166000908152610191602052604090206004015490565b34801561056057600080fd5b5061025f61056f366004614485565b6118cc565b34801561058057600080fd5b5061025f61058f366004614404565b611c00565b3480156105a057600080fd5b50610196546105b990600160a01b900463ffffffff1681565b60405163ffffffff90911681526020016102a1565b3480156105da57600080fd5b5061025f6105e9366004614375565b611edf565b3480156105fa57600080fd5b506106596106093660046140be565b6101916020526000908152604090208054600182015460028301546003909301546001600160801b0380841694600160801b90940416926001600160f81b03831692600160f81b900460ff169186565b604080516001600160801b0397881681529690951660208701526001600160f81b039093169385019390935260ff166060840152608083019190915260a082015260c0016102a1565b3480156106ae57600080fd5b506102976101985481565b3480156106c557600080fd5b506102976106d436600461428b565b611ef0565b3480156106e557600080fd5b5061025f6106f43660046142b6565b611f60565b34801561070557600080fd5b506101965461071a906001600160a01b031681565b6040516001600160a01b0390911681526020016102a1565b34801561073e57600080fd5b5061029761019a5481565b34801561075557600080fd5b5061076961076436600461428b565b612052565b6040805182516001600160781b031681526020808401516001600160401b03908116918301919091528383015116918101919091526060918201511515918101919091526080016102a1565b3480156107c157600080fd5b506102976107d036600461428b565b61019260209081526000928352604080842090915290825290205481565b3480156107fa57600080fd5b506102976101995481565b34801561081157600080fd5b5061029761082036600461428b565b6001600160a01b039190911660009081526101916020908152604080832093835260059093019052205490565b34801561085957600080fd5b506102976101975481565b34801561087057600080fd5b5061033461087f3660046140be565b6101c26020526000908152604090205460ff1681565b3480156108a157600080fd5b5061025f612114565b6108b2612124565b6108bc3382612150565b50565b6108c76124f6565b80156108d5576108bc61259c565b6108bc612636565b6108e5612124565b6108ed6126b2565b6108bc81612762565b600054610100900460ff168061090f575060005460ff16155b6109345760405162461bcd60e51b815260040161092b906145c8565b60405180910390fd5b600054610100900460ff16158015610956576000805461ffff19166101011790555b610966898989868a8a8a89612819565b8015610978576000805461ff00191690555b505050505050505050565b61098b612124565b61099433612762565b565b61099e612124565b63037fd01760e31b6109b2818460006128a1565b33600081815261019160205260408120916109cc906128d4565b90506109d83382612a4b565b60008060005b87811015610c17576000808a8a84818110610a0957634e487b7160e01b600052603260045260246000fd5b905060400201600001358b8b85818110610a3357634e487b7160e01b600052603260045260246000fd5b90506040020160200135915091506000876004018381548110610a6657634e487b7160e01b600052603260045260246000fd5b60009182526020909120018054909150610aa990600160b81b90046001600160401b03164211610a978660036146bd565b6001600160e01b03198c169190612bbe565b610abf6001600160e01b03198a168360016128a1565b80546001600160781b03811690600160f81b900460ff16610b088c151582151514610aeb8860036146bd565b610af6906001614663565b6001600160e01b03198e169190612bbe565b610b2e6001600160781b038316851115610b238860036146bd565b610af6906002614663565b6000610b3984612bef565b90506000610b50866001600160781b038616614724565b610b87578b6004018781548110610b7757634e487b7160e01b600052603260045260246000fd5b6000918252602082200155610bdb565b610b9086612c60565b85548690600090610bab9084906001600160781b03166146dc565b92506101000a8154816001600160781b0302191690836001600160781b03160217905550610bd885612bef565b90505b610be58183614724565b610bef908b614663565b9950610bfb868a614663565b9850505050505050508080610c0f906147aa565b9150506109de565b50610c2182612c86565b600185018054600090610c3e9084906001600160f81b0316614704565b92506101000a8154816001600160f81b0302191690836001600160f81b03160217905550816101986000828254610c759190614724565b925050819055508061019a6000828254610c8f9190614724565b90915550508515610d0a576065546040516362cf156560e11b815233600482015260248101839052600060448201526001600160a01b039091169063c59e2aca90606401600060405180830381600087803b158015610ced57600080fd5b505af1158015610d01573d6000803e3d6000fd5b50505050610d22565b61019654610d22906001600160a01b03163383612ca5565b60408051828152871515602082015233917f30d438cf38db3f29630029343ab01e801276913697f489030c0613ddc4aadaaf910160405180910390a25050505050505050565b610195546040805163ce11154160e01b815290516000926001600160a01b03169163ce111541916004808301926020929190829003018186803b158015610dae57600080fd5b505afa158015610dc2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610de691906143ec565b61019a54610df49190614663565b905090565b610e01612d08565b610e09612124565b610e116130f3565b6301810d2b60e51b81610e22575050565b610e4d6000610198541180610e3a5750600061019954115b6001600160e01b03198316906000612bbe565b610e696101995461019854610e629190614663565b8390613115565b60986000828254610e7a9190614663565b909155505061019454610e98906001600160a01b031633308561313c565b60405182815233907f55fd0bec59e0b2fdf9406c9890f568c6ec6f92c752012ef7e3ebaee44d4d6cad9060200160405180910390a25050565b600080610eef6318ebd13160e11b6001600160a01b038516836128a1565b610196546001600160a01b03841660009081526101916020526040812060018101549192600160c01b90046001600160401b031691600160f81b810460ff16906001600160f81b03168482156110455760005b83811015611043576000818152600586016020526040808220546101955491516313935a8360e11b81526001600160a01b038e81166004830152602482018390529193929190911690632726b5069060440160a06040518083038186803b158015610fac57600080fd5b505afa158015610fc0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fe49190614425565b5050506001600160a01b038e1660009081526101926020908152604080832087845290915290205490925090508082111561101f5780611021565b815b61102b9086614663565b9450505050808061103b906147aa565b915050610f42565b505b844211801561105657506101985415155b1561128357606554604080516318cbe5db60e11b815290516000926001600160a01b031691633197cbb6916004808301926020929190829003018186803b1580156110a057600080fd5b505afa1580156110b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d891906144c5565b63ffffffff16905060008142116110f8576110f38742614724565b611102565b6111028783614724565b90506000606560009054906101000a90046001600160a01b03166001600160a01b03166396c82e576040518163ffffffff1660e01b815260040160206040518083038186803b15801561115457600080fd5b505afa158015611168573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061118c91906144c5565b63ffffffff16606560009054906101000a90046001600160a01b03166001600160a01b0316634251342f6040518163ffffffff1660e01b815260040160206040518083038186803b1580156111e057600080fd5b505afa1580156111f4573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061121891906143ad565b610196546001600160c01b03919091169061124090600160a01b900463ffffffff16856146bd565b61124a91906146bd565b611254919061469d565b90506101975461126f6101995461019854610e629190614663565b6112799190614663565b985050505061128a565b6101975495505b835460028501546001600160801b03909116906112b49088906112ad8587614663565b9190613174565b6112be9190614663565b84546098546003870154929a50600160801b9091046001600160801b0316916112ec91906112ad8587614663565b6112f69190614663565b9650505050505050915091565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016141561134c5760405162461bcd60e51b815260040161092b90614530565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661137e6131a6565b6001600160a01b0316146113a45760405162461bcd60e51b815260040161092b9061457c565b6113ad816131d4565b604080516000808252602082019092526108bc918391906131dc565b6113d1612124565b33600081815261019160205260408082206001600160a01b038516835290822090929091906113ff906128d4565b905061140b3382612a4b565b6303b350f960e41b611428816001600160a01b03871660006128a1565b600183015461148f906001600160f81b031615801561145357506001840154600160f81b900460ff16155b801561146157506004840154155b801561146f57506002840154155b8015610e3a57506003840154156001600160e01b03198316906000612bbe565b600180850154855491850180546001600160f81b0319166001600160f81b039092169182179055600160801b8083046001600160801b03908116918202931692831786556101975460028701556098546003870155600480880180549394936114fb9289019190613f57565b506001870180546001600160f81b03191690556000808855611521906004890190614046565b60018601548654604080516001600160f81b03878116825290931660208401526001600160801b038581168483015280831660608501528481166080850152600160801b90920490911660a0830152516001600160a01b038a169133917fb0ddca6540feadff203fffcc5cf7f1e9ba1bc3011800d146734f13e4ddfc7b6d9181900360c00190a35050505050505050565b6115ba612d08565b6065546115da90634087aeb760e01b906001600160a01b03163314613327565b610196805463ffffffff909216600160a01b0263ffffffff60a01b19909216919091179055565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016141561164a5760405162461bcd60e51b815260040161092b90614530565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661167c6131a6565b6001600160a01b0316146116a25760405162461bcd60e51b815260040161092b9061457c565b6116ab826131d4565b6116b7828260016131dc565b5050565b6116c3612124565b6116cb6126b2565b6116b78282612150565b60655460408051638da5cb5b60e01b81529051636817031b60e01b926117819233926001600160a01b0390921691638da5cb5b91600480820192602092909190829003018186803b15801561172957600080fd5b505afa15801561173d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061176191906140da565b6001600160e01b03198416916001600160a01b0391909116146000612bbe565b6117a26001600160e01b031982166001600160a01b03841615156000613357565b609780546001600160a01b0319166001600160a01b038416908117909155604080518281526020810192909252839133917faa55cb88c5664f8f0bbaf57c2fb02459d3a8dd15bfc1e4490335358804da3234910160405180910390a2505050565b61180c3361338a565b611814612124565b600061181f336128d4565b905061182b3382612a4b565b61183583836133bc565b505050565b6001600160a01b038116600090815261019160205260408120815b60048201548110156118b75781600401818154811061188457634e487b7160e01b600052603260045260246000fd5b6000918252602090912001546118a3906001600160781b031684614663565b9250806118af816147aa565b915050611855565b5050919050565b6118c66124f6565b61019955565b600260c954141561191f5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640161092b565b600260c95561192c612124565b63952e68cf60e01b611940818460016128a1565b61197f62278d00836001600160401b03161015801561196c57506301e13380836001600160401b031611155b6001600160e01b03198316906002613357565b3360008181526101916020526040812091611999906128d4565b90506119a53382612a4b565b6000846119b6426136b2565b6136b2565b6119c0919061467b565b9050600086620f42406301e13380816119e2426001600160401b038816614724565b6119ec91906146bd565b6119f6919061469d565b611a009190614663565b611a0a91906146bd565b905060008111611a2a57634e487b7160e01b600052600160045260246000fd5b60006040518060800160405280611a408a612c60565b6001600160781b03168152602001611a57426136b2565b6001600160401b0390811682528581166020808401919091526000604093840181905260048a01805460018101825590825290829020855191018054928601519486015160608701511515600160f81b026001600160f81b03918616600160b81b02919091166001600160b81b0396909516600160781b026001600160b81b03199094166001600160781b03909316929092179290921793909316919091179190911790559050611b0782612c86565b600186018054600090611b249084906001600160f81b0316614641565b92506101000a8154816001600160f81b0302191690836001600160f81b03160217905550816101986000828254611b5b9190614663565b925050819055508761019a6000828254611b759190614663565b909155505061019654611b93906001600160a01b031633308b61313c565b6004850154339081907f47ee2438657f63a52980ec1ed6e4424262f81f621308d91694c410db5bfa401b90611bca90600190614724565b60408051918252602082018d90526001600160401b0388169082015260600160405180910390a35050600160c955505050505050565b611c08612124565b639e2c8a5b60e01b611c1c818360006128a1565b3360009081526101916020526040812060048101805491929186908110611c5357634e487b7160e01b600052603260045260246000fd5b60009182526020909120018054909150611c8c90600160b81b90046001600160401b0316426001600160e01b0319861691106000612bbe565b80546001600160781b03811690600160f81b900460ff16611cbc6001600160e01b03198616878410156001613357565b6000611cc7336128d4565b9050611cd33382612a4b565b6000611cde85612bef565b90506000611cf5896001600160781b038716614724565b611d2c57866004018a81548110611d1c57634e487b7160e01b600052603260045260246000fd5b6000918252602082200155611d80565b611d3589612c60565b86548790600090611d509084906001600160781b03166146dc565b92506101000a8154816001600160781b0302191690836001600160781b03160217905550611d7d86612bef565b90505b60018701548190611d9b9084906001600160f81b0316614724565b611da59190614663565b6001880180546001600160f81b0319166001600160f81b0392909216919091179055610198548190611dd8908490614724565b611de29190614663565b610198819055508861019a6000828254611dfc9190614724565b90915550508315611e77576065546040516362cf156560e11b8152336004820152602481018b9052600060448201526001600160a01b039091169063c59e2aca90606401600060405180830381600087803b158015611e5a57600080fd5b505af1158015611e6e573d6000803e3d6000fd5b50505050611e8f565b61019654611e8f906001600160a01b0316338b612ca5565b604080518b8152602081018b905285151581830152905133917f729ab3b283445a8f221b97237248ecc12a89cafc93156a0c77e1174a01ef1c16919081900360600190a250505050505050505050565b611ee7612124565b6108b233612762565b6001600160a01b038216600090815261019160205260408120815b6001820154600160f81b900460ff16811015611f54576000818152600583016020526040902054841415611f42579150611f5a9050565b80611f4c816147aa565b915050611f0b565b50600080fd5b92915050565b611f686124f6565b635d9eb3b560e11b60005b8281101561204c57611fd66000858584818110611fa057634e487b7160e01b600052603260045260246000fd5b9050602002016020810190611fb591906140be565b6001600160e01b03198516916001600160a01b039190911614156000613357565b60016101c26000868685818110611ffd57634e487b7160e01b600052603260045260246000fd5b905060200201602081019061201291906140be565b6001600160a01b031681526020810191909152604001600020805460ff191691151591909117905580612044816147aa565b915050611f73565b50505050565b6040805160808101825260008082526020808301829052828401829052606083018290526001600160a01b03861682526101919052919091206004018054839081106120ae57634e487b7160e01b600052603260045260246000fd5b60009182526020918290206040805160808101825292909101546001600160781b0381168352600160781b81046001600160401b0390811694840194909452600160b81b810490931690820152600160f81b90910460ff16151560608201529392505050565b61211c612124565b610994612d08565b63abb87a6f60e01b6108bc61213c61012d5460ff1690565b6001600160e01b0319831690156000612bbe565b6001600160a01b03821660009081526101916020526040812090612173846128d4565b905061217f8482612a4b565b81546001600160801b031680612196575050505050565b82546fffffffffffffffffffffffffffffffff191683558315612225576065546040516362cf156560e11b81526001600160a01b03878116600483015260248201849052600160448301529091169063c59e2aca90606401600060405180830381600087803b15801561220857600080fd5b505af115801561221c573d6000803e3d6000fd5b505050506124a7565b61019454610196546001600160a01b03908116911614156123ba57600061224f621e8480836146bd565b90506000604051806080016040528061226785612c60565b6001600160781b0316815260200161227e426136b2565b6001600160401b0316815260200161229d6119b16301e1338042614663565b6001600160401b039081168252600160209283018190526004890180549182018155600090815283902084519101805493850151604086015160608701511515600160f81b026001600160f81b03918616600160b81b02919091166001600160b81b0392909516600160781b026001600160b81b03199096166001600160781b0390941693909317949094179390931691909117179055905061233f82612c86565b60018601805460009061235c9084906001600160f81b0316614641565b92506101000a8154816001600160f81b0302191690836001600160f81b031602179055508161019860008282546123939190614663565b925050819055508261019a60008282546123ad9190614663565b909155506124a792505050565b6065546101945460405163091465f760e11b81526001600160a01b0391821660048201526000929190911690631228cbee9060240160206040518083038186803b15801561240757600080fd5b505afa15801561241b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061243f91906140da565b6040516344cc892d60e01b81526001600160a01b03888116600483015260248201859052919250908216906344cc892d90604401600060405180830381600087803b15801561248d57600080fd5b505af11580156124a1573d6000803e3d6000fd5b50505050505b604080518515158152602081018390526001600160a01b0387169133917f7aa2446843f85ab4372b9a9eddbe072a35cd062fb199eaddea2ad3b8d0396fa2910160405180910390a35050505050565b60655460408051638da5cb5b60e01b815290516339e71deb60e01b926108bc926001600160a01b0390911691638da5cb5b91600480820192602092909190829003018186803b15801561254857600080fd5b505afa15801561255c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061258091906140da565b6001600160e01b03198316906001600160a01b03163314613327565b61012d5460ff16156125e35760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015260640161092b565b61012d805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586126193390565b6040516001600160a01b03909116815260200160405180910390a1565b61012d5460ff166126805760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b604482015260640161092b565b61012d805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa33612619565b606554610194546040516329018f6f60e21b81526001600160a01b03918216600482015263250f303f60e01b92600092339291169063a4063dbc9060240160206040518083038186803b15801561270857600080fd5b505afa15801561271c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061274091906140da565b6001600160a01b03161490506116b76001600160e01b03198316826000612bbe565b6001600160a01b03811660009081526101916020526040812090612785836128d4565b90506127918382612a4b565b8154600160801b90046001600160801b0316806127ae5750505050565b82546001600160801b03168355610194546127d3906001600160a01b03168583612ca5565b6040518181526001600160a01b0385169033907fa69db2085ef89718710bae5b78f2032cf155ff99feca17d718e69f8ba375c11e9060200160405180910390a350505050565b600054610100900460ff1680612832575060005460ff16155b61284e5760405162461bcd60e51b815260040161092b906145c8565b600054610100900460ff16158015612870576000805461ffff19166101011790555b61287f898989898989896136d1565b6101c38290558015610978576000805461ff0019169055505050505050505050565b8161183557604051633bd8dd9360e21b81526001600160e01b03198416600482015260ff8216602482015260440161092b565b6001600160a01b0381166000908152610191602052604081206001810154600160f81b900460ff1680156118b75760005b81811015612a43576000818152600584016020526040808220546101955491516313935a8360e11b81526001600160a01b038981166004830152602482018390529193929190911690632726b5069060440160a06040518083038186803b15801561296f57600080fd5b505afa158015612983573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129a79190614425565b5050506001600160a01b0389166000908152610192602090815260408083208784529091529020549092509050808211156129e257806129e4565b815b6129ee9088614663565b965081811115612a2d578115612a045781612a07565b60015b6001600160a01b0389166000908152610192602090815260408083208784529091529020555b5050508080612a3b906147aa565b915050612905565b505050919050565b612a53612d08565b6001600160a01b0382166000908152610191602052604081206001810154909190612a889084906001600160f81b0316614663565b90506000612aa8610197548460020154846131749092919063ffffffff16565b90506000612ac76098548560030154856131749092919063ffffffff16565b9050612ad282613857565b84548590600090612aed9084906001600160801b0316614616565b92506101000a8154816001600160801b0302191690836001600160801b03160217905550612b1a81613857565b84548590601090612b3c908490600160801b90046001600160801b0316614616565b82546001600160801b039182166101009390930a928302919092021990911617905550610197546002850155609854600385015560408051838152602081018390526001600160a01b0388169133917f31eeb6a0d26c29b4c243d704ff4ae6feebcc2e8b123df7ea0bd12083c3083cb8910160405180910390a3505050505050565b8161183557604051631db762fb60e31b81526001600160e01b0319841660048201526024810182905260440161092b565b80546000906001600160781b03811690620f4240906301e13380908290612c2f906001600160401b03600160781b8204811691600160b81b90041661473b565b6001600160401b0316612c4291906146bd565b612c4c919061469d565b612c569190614663565b611f5a91906146bd565b6000631e4e4bad60e01b612c7f816001600160781b0385111584613357565b5090919050565b6000631feb933960e11b612c7f816001600160f81b0385111584613357565b6040516001600160a01b03831660248201526044810182905261183590849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152613876565b60655460408051639f1dc9bd60e01b815290516001600160a01b03909216918291639f1dc9bd916004808301926020929190829003018186803b158015612d4e57600080fd5b505afa158015612d62573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d869190614391565b15612ddf57806001600160a01b031663a83c76646040518163ffffffff1660e01b8152600401600060405180830381600087803b158015612dc657600080fd5b505af1158015612dda573d6000803e3d6000fd5b505050505b6000816001600160a01b0316633197cbb66040518163ffffffff1660e01b815260040160206040518083038186803b158015612e1a57600080fd5b505afa158015612e2e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e5291906144c5565b6101965463ffffffff919091169150600160c01b90046001600160401b03168111612e7b575050565b61019654600160c01b90046001600160401b03164211612e99575050565b61019854158015612eab575061019954155b15612ee457612eb9426136b2565b61019660186101000a8154816001600160401b0302191690836001600160401b031602179055505050565b6000814211612ef35742612ef5565b815b61019654909150600090612f1990600160c01b90046001600160401b031683614724565b90506000846001600160a01b0316634251342f6040518163ffffffff1660e01b815260040160206040518083038186803b158015612f5657600080fd5b505afa158015612f6a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f8e91906143ad565b6001600160c01b031690506000856001600160a01b03166396c82e576040518163ffffffff1660e01b815260040160206040518083038186803b158015612fd457600080fd5b505afa158015612fe8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061300c91906144c5565b6101965463ffffffff91821691600160a01b9091041661302c84866146bd565b61303691906146bd565b613040919061469d565b905061305e61019954610198546130579190614663565b8290613115565b61019760008282546130709190614663565b9091555061307f9050846136b2565b61019680546001600160c01b0316600160c01b6001600160401b0393841681029190911791829055610197546040805191825291909204909216602082015233917f33e6f269701b611439c5bd9eae485d1b2f10d29b632a6f0d5688c93c2d77af1f910160405180910390a2505050505050565b60975463eeea774b60e01b906108bc9082906001600160a01b03163314613327565b60008161312b68056bc75e2d63100000856146bd565b613135919061469d565b9392505050565b6040516001600160a01b038085166024830152831660448201526064810182905261204c9085906323b872dd60e01b90608401612cd1565b600068056bc75e2d6310000061318a8385614724565b61319490866146bd565b61319e919061469d565b949350505050565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b6108bc6124f6565b60006131e66131a6565b90506131f184613948565b6000835111806131fe5750815b1561320f5761320d84846139ed565b505b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143805460ff1661332057805460ff191660011781556040516001600160a01b038316602482015261328e90869060440160408051601f198184030181529190526020810180516001600160e01b0316631b2ce7f360e11b1790526139ed565b50805460ff1916815561329f6131a6565b6001600160a01b0316826001600160a01b0316146133175760405162461bcd60e51b815260206004820152602f60248201527f45524331393637557067726164653a207570677261646520627265616b73206660448201526e75727468657220757067726164657360881b606482015260840161092b565b61332085613ad8565b5050505050565b806116b757604051630df66e3d60e41b81526001600160e01b03198316600482015233602482015260440161092b565b81611835576040516301cc826960e41b81526001600160e01b03198416600482015260ff8216602482015260440161092b565b6001600160a01b03811660009081526101c260205260409020546334aae7c960e11b906116b790829060ff1615613327565b3360009081526101916020526040812090638081252560e01b90805b848110156136755761019554600090819081906001600160a01b0316632726b506338b8b8881811061341a57634e487b7160e01b600052603260045260246000fd5b6040516001600160e01b031960e087901b1681526001600160a01b039094166004850152602002919091013560248301525060440160a06040518083038186803b15801561346757600080fd5b505afa15801561347b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061349f9190614425565b94505093509350506134da63623cc7e4836001600160401b031611158560036134c891906146bd565b6001600160e01b031989169190612bbe565b61350a6000836001600160401b03161180156134f4575081155b6134ff8660036146bd565b6134c8906001614663565b3360009081526101926020526040812061356f918b8b8881811061353e57634e487b7160e01b600052603260045260246000fd5b9050602002013581526020019081526020016000205460001485600361356491906146bd565b6134c8906002614663565b3360009081526101926020526040812084918b8b888181106135a157634e487b7160e01b600052603260045260246000fd5b9050602002013581526020019081526020016000208190555082856135c69190614663565b600188018054919650600160f81b90910460ff1690601f6135e6836147c5565b91906101000a81548160ff021916908360ff1602179055505088888581811061361f57634e487b7160e01b600052603260045260246000fd5b9050602002013587600501600060018a600101601f9054906101000a900460ff1661364a919061475b565b60ff16815260200190815260200160002081905550505050808061366d906147aa565b9150506133d8565b5060405181815233907fce2872a31020970c0a5aecb43e7199b699f079f2a54624c757b797e950621cb49060200160405180910390a25050505050565b60006302665fad60e41b612c7f816001600160401b0385111584613357565b600054610100900460ff16806136ea575060005460ff16155b6137065760405162461bcd60e51b815260040161092b906145c8565b600054610100900460ff16158015613728576000805461ffff19166101011790555b630a895f0360e11b613745816001600160a01b03891660026128a1565b6137646001600160e01b031982166001600160a01b03881660036128a1565b6137836001600160e01b031982166001600160401b03861660056128a1565b6137a36001600160e01b0319821663ffffffff808616906006906128a116565b6137ac85613b18565b6137b4613bbd565b6137bc613c30565b5061019480546001600160a01b03199081166001600160a01b038b811691909117909255610193805482168a841617905561019680546101958054909316898516179092559188166001600160c01b031990911617600160a01b63ffffffff851602176001600160c01b0316600160c01b6001600160401b03861602179055801561384d576000805461ff00191690555b5050505050505050565b600063809fdd3360e01b612c7f816001600160801b0385111584613357565b60006138cb826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316613c979092919063ffffffff16565b80519091501561183557808060200190518101906138e99190614391565b6118355760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840161092b565b803b6139ac5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b606482015260840161092b565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b0319166001600160a01b0392909216919091179055565b6060823b613a4c5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b606482015260840161092b565b600080846001600160a01b031684604051613a6791906144e1565b600060405180830381855af49150503d8060008114613aa2576040519150601f19603f3d011682016040523d82523d6000602084013e613aa7565b606091505b5091509150613acf828260405180606001604052806027815260200161485c60279139613ca6565b95945050505050565b613ae181613948565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b600054610100900460ff1680613b31575060005460ff16155b613b4d5760405162461bcd60e51b815260040161092b906145c8565b600054610100900460ff16158015613b6f576000805461ffff19166101011790555b63bb6c0dbf60e01b613b8c816001600160a01b03851660006128a1565b50606580546001600160a01b0319166001600160a01b03841617905580156116b7576000805461ff00191690555050565b600054610100900460ff1680613bd6575060005460ff16155b613bf25760405162461bcd60e51b815260040161092b906145c8565b600054610100900460ff16158015613c14576000805461ffff19166101011790555b613c1c613cdf565b80156108bc576000805461ff001916905550565b600054610100900460ff1680613c49575060005460ff16155b613c655760405162461bcd60e51b815260040161092b906145c8565b600054610100900460ff16158015613c87576000805461ffff19166101011790555b613c8f613d4f565b613c1c613db9565b606061319e8484600085613e2f565b60608315613cb5575081613135565b825115613cc55782518084602001fd5b8160405162461bcd60e51b815260040161092b91906144fd565b600054610100900460ff1680613cf8575060005460ff16155b613d145760405162461bcd60e51b815260040161092b906145c8565b600054610100900460ff16158015613d36576000805461ffff19166101011790555b600160c95580156108bc576000805461ff001916905550565b600054610100900460ff1680613d68575060005460ff16155b613d845760405162461bcd60e51b815260040161092b906145c8565b600054610100900460ff16158015613c1c576000805461ffff191661010117905580156108bc576000805461ff001916905550565b600054610100900460ff1680613dd2575060005460ff16155b613dee5760405162461bcd60e51b815260040161092b906145c8565b600054610100900460ff16158015613e10576000805461ffff19166101011790555b61012d805460ff1916905580156108bc576000805461ff001916905550565b606082471015613e905760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840161092b565b843b613ede5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161092b565b600080866001600160a01b03168587604051613efa91906144e1565b60006040518083038185875af1925050503d8060008114613f37576040519150601f19603f3d011682016040523d82523d6000602084013e613f3c565b606091505b5091509150613f4c828286613ca6565b979650505050505050565b8280548282559060005260206000209081019282156140365760005260206000209182015b8281111561403657825482546001600160781b039091166effffffffffffffffffffffffffffff1982168117845584546001600160b81b031990921617600160781b918290046001600160401b0390811690920217808455845467ffffffffffffffff60b81b198216600160b81b9182900490931602918217845584546001600160b81b039091166001600160f81b0390921691909117600160f81b9182900460ff16151590910217825560019283019290910190613f7c565b50614042929150614060565b5090565b50805460008255906000526020600020908101906108bc91905b5b808211156140425760008155600101614061565b60008083601f840112614086578081fd5b5081356001600160401b0381111561409c578182fd5b6020830191508360208260051b85010111156140b757600080fd5b9250929050565b6000602082840312156140cf578081fd5b813561313581614811565b6000602082840312156140eb578081fd5b815161313581614811565b600080600080600080600080610100898b031215614112578384fd5b883561411d81614811565b9750602089013561412d81614811565b9650604089013561413d81614811565b9550606089013561414d81614811565b9450608089013561415d81614846565b935060a089013561416d81614834565b925060c089013561417d81614811565b8092505060e089013590509295985092959890939650565b600080604083850312156141a7578182fd5b82356141b281614811565b915060208301356141c281614826565b809150509250929050565b600080604083850312156141df578182fd5b82356141ea81614811565b915060208301356001600160401b0380821115614205578283fd5b818501915085601f830112614218578283fd5b81358181111561422a5761422a6147fb565b604051601f8201601f19908116603f01168101908382118183101715614252576142526147fb565b8160405282815288602084870101111561426a578586fd5b82602086016020830137856020848301015280955050505050509250929050565b6000806040838503121561429d578182fd5b82356142a881614811565b946020939093013593505050565b600080602083850312156142c8578182fd5b82356001600160401b038111156142dd578283fd5b6142e985828601614075565b90969095509350505050565b600080600060408486031215614309578283fd5b83356001600160401b038082111561431f578485fd5b818601915086601f830112614332578485fd5b813581811115614340578586fd5b8760208260061b8501011115614354578586fd5b6020928301955093505084013561436a81614826565b809150509250925092565b600060208284031215614386578081fd5b813561313581614826565b6000602082840312156143a2578081fd5b815161313581614826565b6000602082840312156143be578081fd5b81516001600160c01b0381168114613135578182fd5b6000602082840312156143e5578081fd5b5035919050565b6000602082840312156143fd578081fd5b5051919050565b60008060408385031215614416578182fd5b50508035926020909101359150565b600080600080600060a0868803121561443c578283fd5b8551945060208601519350604086015161445581614846565b606087015190935061446681614846565b608087015190925061447781614826565b809150509295509295909350565b60008060408385031215614497578182fd5b8235915060208301356141c281614846565b6000602082840312156144ba578081fd5b813561313581614834565b6000602082840312156144d6578081fd5b815161313581614834565b600082516144f381846020870161477e565b9190910192915050565b602081526000825180602084015261451c81604085016020870161477e565b601f01601f19169190910160400192915050565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b6163746976652070726f787960a01b606082015260800190565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b60006001600160801b03808316818516808303821115614638576146386147e5565b01949350505050565b60006001600160f81b03828116848216808303821115614638576146386147e5565b60008219821115614676576146766147e5565b500190565b60006001600160401b03808316818516808303821115614638576146386147e5565b6000826146b857634e487b7160e01b81526012600452602481fd5b500490565b60008160001904831182151516156146d7576146d76147e5565b500290565b60006001600160781b03838116908316818110156146fc576146fc6147e5565b039392505050565b60006001600160f81b03838116908316818110156146fc576146fc6147e5565b600082821015614736576147366147e5565b500390565b60006001600160401b03838116908316818110156146fc576146fc6147e5565b600060ff821660ff841680821015614775576147756147e5565b90039392505050565b60005b83811015614799578181015183820152602001614781565b8381111561204c5750506000910152565b60006000198214156147be576147be6147e5565b5060010190565b600060ff821660ff8114156147dc576147dc6147e5565b60010192915050565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b03811681146108bc57600080fd5b80151581146108bc57600080fd5b63ffffffff811681146108bc57600080fd5b6001600160401b03811681146108bc57600080fdfe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a164736f6c6343000804000a
Deployed Bytecode
0x60806040526004361061023a5760003560e01c806370a082311161012e578063bb3d676a116100ab578063ed91b7de1161006f578063ed91b7de146107ee578063ef0c792414610805578063fa213bd61461084d578063fe575a8714610864578063fff6cae91461089557600080fd5b8063bb3d676a146106d9578063cbdf382c146106f9578063ce11154114610732578063cfd4766314610749578063dc60e2cb146107b557600080fd5b8063a1aab33f116100f2578063a1aab33f14610594578063a4292812146105ce578063a87430ba146105ee578063ae9f245a146106a2578063b1aca504146106b957600080fd5b806370a08231146104da57806374bd128f146104fa578063909767d91461051a578063952e68cf146105545780639e2c8a5b1461057457600080fd5b80633021a560116101bc5780634f1ef286116101805780634f1ef2861461044e57806353961e06146104615780635c975abb146104815780636817031b1461049a5780636955cf92146104ba57600080fd5b80633021a5601461039957806331d7a262146103b95780633659cfe6146103ee5780633b350f901461040e5780634087aeb71461042e57600080fd5b80631965a599116102035780631965a599146102ea5780631bfe80b8146102ff5780631da10d911461031f578063242693d31461034457806329eb5f2c1461035957600080fd5b806251ccba1461023f57806302329a291461026157806305472358146102815780630834ef45146102aa578063114952be146102ca575b600080fd5b34801561024b57600080fd5b5061025f61025a366004614375565b6108aa565b005b34801561026d57600080fd5b5061025f61027c366004614375565b6108bf565b34801561028d57600080fd5b5061029760985481565b6040519081526020015b60405180910390f35b3480156102b657600080fd5b5061025f6102c53660046140be565b6108dd565b3480156102d657600080fd5b5061025f6102e53660046140f6565b6108f6565b3480156102f657600080fd5b5061025f610983565b34801561030b57600080fd5b5061025f61031a3660046142f5565b610996565b34801561032b57600080fd5b50610334600081565b60405190151581526020016102a1565b34801561035057600080fd5b50610297610d68565b34801561036557600080fd5b506101965461038190600160c01b90046001600160401b031681565b6040516001600160401b0390911681526020016102a1565b3480156103a557600080fd5b5061025f6103b43660046143d4565b610df9565b3480156103c557600080fd5b506103d96103d43660046140be565b610ed1565b604080519283526020830191909152016102a1565b3480156103fa57600080fd5b5061025f6104093660046140be565b611303565b34801561041a57600080fd5b5061025f6104293660046140be565b6113c9565b34801561043a57600080fd5b5061025f6104493660046144a9565b6115b2565b61025f61045c3660046141cd565b611601565b34801561046d57600080fd5b5061025f61047c366004614195565b6116bb565b34801561048d57600080fd5b5061012d5460ff16610334565b3480156104a657600080fd5b5061025f6104b53660046140be565b6116d5565b3480156104c657600080fd5b5061025f6104d53660046142b6565b611803565b3480156104e657600080fd5b506102976104f53660046140be565b61183a565b34801561050657600080fd5b5061025f6105153660046143d4565b6118be565b34801561052657600080fd5b506102976105353660046140be565b6001600160a01b03166000908152610191602052604090206004015490565b34801561056057600080fd5b5061025f61056f366004614485565b6118cc565b34801561058057600080fd5b5061025f61058f366004614404565b611c00565b3480156105a057600080fd5b50610196546105b990600160a01b900463ffffffff1681565b60405163ffffffff90911681526020016102a1565b3480156105da57600080fd5b5061025f6105e9366004614375565b611edf565b3480156105fa57600080fd5b506106596106093660046140be565b6101916020526000908152604090208054600182015460028301546003909301546001600160801b0380841694600160801b90940416926001600160f81b03831692600160f81b900460ff169186565b604080516001600160801b0397881681529690951660208701526001600160f81b039093169385019390935260ff166060840152608083019190915260a082015260c0016102a1565b3480156106ae57600080fd5b506102976101985481565b3480156106c557600080fd5b506102976106d436600461428b565b611ef0565b3480156106e557600080fd5b5061025f6106f43660046142b6565b611f60565b34801561070557600080fd5b506101965461071a906001600160a01b031681565b6040516001600160a01b0390911681526020016102a1565b34801561073e57600080fd5b5061029761019a5481565b34801561075557600080fd5b5061076961076436600461428b565b612052565b6040805182516001600160781b031681526020808401516001600160401b03908116918301919091528383015116918101919091526060918201511515918101919091526080016102a1565b3480156107c157600080fd5b506102976107d036600461428b565b61019260209081526000928352604080842090915290825290205481565b3480156107fa57600080fd5b506102976101995481565b34801561081157600080fd5b5061029761082036600461428b565b6001600160a01b039190911660009081526101916020908152604080832093835260059093019052205490565b34801561085957600080fd5b506102976101975481565b34801561087057600080fd5b5061033461087f3660046140be565b6101c26020526000908152604090205460ff1681565b3480156108a157600080fd5b5061025f612114565b6108b2612124565b6108bc3382612150565b50565b6108c76124f6565b80156108d5576108bc61259c565b6108bc612636565b6108e5612124565b6108ed6126b2565b6108bc81612762565b600054610100900460ff168061090f575060005460ff16155b6109345760405162461bcd60e51b815260040161092b906145c8565b60405180910390fd5b600054610100900460ff16158015610956576000805461ffff19166101011790555b610966898989868a8a8a89612819565b8015610978576000805461ff00191690555b505050505050505050565b61098b612124565b61099433612762565b565b61099e612124565b63037fd01760e31b6109b2818460006128a1565b33600081815261019160205260408120916109cc906128d4565b90506109d83382612a4b565b60008060005b87811015610c17576000808a8a84818110610a0957634e487b7160e01b600052603260045260246000fd5b905060400201600001358b8b85818110610a3357634e487b7160e01b600052603260045260246000fd5b90506040020160200135915091506000876004018381548110610a6657634e487b7160e01b600052603260045260246000fd5b60009182526020909120018054909150610aa990600160b81b90046001600160401b03164211610a978660036146bd565b6001600160e01b03198c169190612bbe565b610abf6001600160e01b03198a168360016128a1565b80546001600160781b03811690600160f81b900460ff16610b088c151582151514610aeb8860036146bd565b610af6906001614663565b6001600160e01b03198e169190612bbe565b610b2e6001600160781b038316851115610b238860036146bd565b610af6906002614663565b6000610b3984612bef565b90506000610b50866001600160781b038616614724565b610b87578b6004018781548110610b7757634e487b7160e01b600052603260045260246000fd5b6000918252602082200155610bdb565b610b9086612c60565b85548690600090610bab9084906001600160781b03166146dc565b92506101000a8154816001600160781b0302191690836001600160781b03160217905550610bd885612bef565b90505b610be58183614724565b610bef908b614663565b9950610bfb868a614663565b9850505050505050508080610c0f906147aa565b9150506109de565b50610c2182612c86565b600185018054600090610c3e9084906001600160f81b0316614704565b92506101000a8154816001600160f81b0302191690836001600160f81b03160217905550816101986000828254610c759190614724565b925050819055508061019a6000828254610c8f9190614724565b90915550508515610d0a576065546040516362cf156560e11b815233600482015260248101839052600060448201526001600160a01b039091169063c59e2aca90606401600060405180830381600087803b158015610ced57600080fd5b505af1158015610d01573d6000803e3d6000fd5b50505050610d22565b61019654610d22906001600160a01b03163383612ca5565b60408051828152871515602082015233917f30d438cf38db3f29630029343ab01e801276913697f489030c0613ddc4aadaaf910160405180910390a25050505050505050565b610195546040805163ce11154160e01b815290516000926001600160a01b03169163ce111541916004808301926020929190829003018186803b158015610dae57600080fd5b505afa158015610dc2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610de691906143ec565b61019a54610df49190614663565b905090565b610e01612d08565b610e09612124565b610e116130f3565b6301810d2b60e51b81610e22575050565b610e4d6000610198541180610e3a5750600061019954115b6001600160e01b03198316906000612bbe565b610e696101995461019854610e629190614663565b8390613115565b60986000828254610e7a9190614663565b909155505061019454610e98906001600160a01b031633308561313c565b60405182815233907f55fd0bec59e0b2fdf9406c9890f568c6ec6f92c752012ef7e3ebaee44d4d6cad9060200160405180910390a25050565b600080610eef6318ebd13160e11b6001600160a01b038516836128a1565b610196546001600160a01b03841660009081526101916020526040812060018101549192600160c01b90046001600160401b031691600160f81b810460ff16906001600160f81b03168482156110455760005b83811015611043576000818152600586016020526040808220546101955491516313935a8360e11b81526001600160a01b038e81166004830152602482018390529193929190911690632726b5069060440160a06040518083038186803b158015610fac57600080fd5b505afa158015610fc0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fe49190614425565b5050506001600160a01b038e1660009081526101926020908152604080832087845290915290205490925090508082111561101f5780611021565b815b61102b9086614663565b9450505050808061103b906147aa565b915050610f42565b505b844211801561105657506101985415155b1561128357606554604080516318cbe5db60e11b815290516000926001600160a01b031691633197cbb6916004808301926020929190829003018186803b1580156110a057600080fd5b505afa1580156110b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d891906144c5565b63ffffffff16905060008142116110f8576110f38742614724565b611102565b6111028783614724565b90506000606560009054906101000a90046001600160a01b03166001600160a01b03166396c82e576040518163ffffffff1660e01b815260040160206040518083038186803b15801561115457600080fd5b505afa158015611168573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061118c91906144c5565b63ffffffff16606560009054906101000a90046001600160a01b03166001600160a01b0316634251342f6040518163ffffffff1660e01b815260040160206040518083038186803b1580156111e057600080fd5b505afa1580156111f4573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061121891906143ad565b610196546001600160c01b03919091169061124090600160a01b900463ffffffff16856146bd565b61124a91906146bd565b611254919061469d565b90506101975461126f6101995461019854610e629190614663565b6112799190614663565b985050505061128a565b6101975495505b835460028501546001600160801b03909116906112b49088906112ad8587614663565b9190613174565b6112be9190614663565b84546098546003870154929a50600160801b9091046001600160801b0316916112ec91906112ad8587614663565b6112f69190614663565b9650505050505050915091565b306001600160a01b037f00000000000000000000000034c267694ed0829f777ab830841f6664ff77e1e016141561134c5760405162461bcd60e51b815260040161092b90614530565b7f00000000000000000000000034c267694ed0829f777ab830841f6664ff77e1e06001600160a01b031661137e6131a6565b6001600160a01b0316146113a45760405162461bcd60e51b815260040161092b9061457c565b6113ad816131d4565b604080516000808252602082019092526108bc918391906131dc565b6113d1612124565b33600081815261019160205260408082206001600160a01b038516835290822090929091906113ff906128d4565b905061140b3382612a4b565b6303b350f960e41b611428816001600160a01b03871660006128a1565b600183015461148f906001600160f81b031615801561145357506001840154600160f81b900460ff16155b801561146157506004840154155b801561146f57506002840154155b8015610e3a57506003840154156001600160e01b03198316906000612bbe565b600180850154855491850180546001600160f81b0319166001600160f81b039092169182179055600160801b8083046001600160801b03908116918202931692831786556101975460028701556098546003870155600480880180549394936114fb9289019190613f57565b506001870180546001600160f81b03191690556000808855611521906004890190614046565b60018601548654604080516001600160f81b03878116825290931660208401526001600160801b038581168483015280831660608501528481166080850152600160801b90920490911660a0830152516001600160a01b038a169133917fb0ddca6540feadff203fffcc5cf7f1e9ba1bc3011800d146734f13e4ddfc7b6d9181900360c00190a35050505050505050565b6115ba612d08565b6065546115da90634087aeb760e01b906001600160a01b03163314613327565b610196805463ffffffff909216600160a01b0263ffffffff60a01b19909216919091179055565b306001600160a01b037f00000000000000000000000034c267694ed0829f777ab830841f6664ff77e1e016141561164a5760405162461bcd60e51b815260040161092b90614530565b7f00000000000000000000000034c267694ed0829f777ab830841f6664ff77e1e06001600160a01b031661167c6131a6565b6001600160a01b0316146116a25760405162461bcd60e51b815260040161092b9061457c565b6116ab826131d4565b6116b7828260016131dc565b5050565b6116c3612124565b6116cb6126b2565b6116b78282612150565b60655460408051638da5cb5b60e01b81529051636817031b60e01b926117819233926001600160a01b0390921691638da5cb5b91600480820192602092909190829003018186803b15801561172957600080fd5b505afa15801561173d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061176191906140da565b6001600160e01b03198416916001600160a01b0391909116146000612bbe565b6117a26001600160e01b031982166001600160a01b03841615156000613357565b609780546001600160a01b0319166001600160a01b038416908117909155604080518281526020810192909252839133917faa55cb88c5664f8f0bbaf57c2fb02459d3a8dd15bfc1e4490335358804da3234910160405180910390a2505050565b61180c3361338a565b611814612124565b600061181f336128d4565b905061182b3382612a4b565b61183583836133bc565b505050565b6001600160a01b038116600090815261019160205260408120815b60048201548110156118b75781600401818154811061188457634e487b7160e01b600052603260045260246000fd5b6000918252602090912001546118a3906001600160781b031684614663565b9250806118af816147aa565b915050611855565b5050919050565b6118c66124f6565b61019955565b600260c954141561191f5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640161092b565b600260c95561192c612124565b63952e68cf60e01b611940818460016128a1565b61197f62278d00836001600160401b03161015801561196c57506301e13380836001600160401b031611155b6001600160e01b03198316906002613357565b3360008181526101916020526040812091611999906128d4565b90506119a53382612a4b565b6000846119b6426136b2565b6136b2565b6119c0919061467b565b9050600086620f42406301e13380816119e2426001600160401b038816614724565b6119ec91906146bd565b6119f6919061469d565b611a009190614663565b611a0a91906146bd565b905060008111611a2a57634e487b7160e01b600052600160045260246000fd5b60006040518060800160405280611a408a612c60565b6001600160781b03168152602001611a57426136b2565b6001600160401b0390811682528581166020808401919091526000604093840181905260048a01805460018101825590825290829020855191018054928601519486015160608701511515600160f81b026001600160f81b03918616600160b81b02919091166001600160b81b0396909516600160781b026001600160b81b03199094166001600160781b03909316929092179290921793909316919091179190911790559050611b0782612c86565b600186018054600090611b249084906001600160f81b0316614641565b92506101000a8154816001600160f81b0302191690836001600160f81b03160217905550816101986000828254611b5b9190614663565b925050819055508761019a6000828254611b759190614663565b909155505061019654611b93906001600160a01b031633308b61313c565b6004850154339081907f47ee2438657f63a52980ec1ed6e4424262f81f621308d91694c410db5bfa401b90611bca90600190614724565b60408051918252602082018d90526001600160401b0388169082015260600160405180910390a35050600160c955505050505050565b611c08612124565b639e2c8a5b60e01b611c1c818360006128a1565b3360009081526101916020526040812060048101805491929186908110611c5357634e487b7160e01b600052603260045260246000fd5b60009182526020909120018054909150611c8c90600160b81b90046001600160401b0316426001600160e01b0319861691106000612bbe565b80546001600160781b03811690600160f81b900460ff16611cbc6001600160e01b03198616878410156001613357565b6000611cc7336128d4565b9050611cd33382612a4b565b6000611cde85612bef565b90506000611cf5896001600160781b038716614724565b611d2c57866004018a81548110611d1c57634e487b7160e01b600052603260045260246000fd5b6000918252602082200155611d80565b611d3589612c60565b86548790600090611d509084906001600160781b03166146dc565b92506101000a8154816001600160781b0302191690836001600160781b03160217905550611d7d86612bef565b90505b60018701548190611d9b9084906001600160f81b0316614724565b611da59190614663565b6001880180546001600160f81b0319166001600160f81b0392909216919091179055610198548190611dd8908490614724565b611de29190614663565b610198819055508861019a6000828254611dfc9190614724565b90915550508315611e77576065546040516362cf156560e11b8152336004820152602481018b9052600060448201526001600160a01b039091169063c59e2aca90606401600060405180830381600087803b158015611e5a57600080fd5b505af1158015611e6e573d6000803e3d6000fd5b50505050611e8f565b61019654611e8f906001600160a01b0316338b612ca5565b604080518b8152602081018b905285151581830152905133917f729ab3b283445a8f221b97237248ecc12a89cafc93156a0c77e1174a01ef1c16919081900360600190a250505050505050505050565b611ee7612124565b6108b233612762565b6001600160a01b038216600090815261019160205260408120815b6001820154600160f81b900460ff16811015611f54576000818152600583016020526040902054841415611f42579150611f5a9050565b80611f4c816147aa565b915050611f0b565b50600080fd5b92915050565b611f686124f6565b635d9eb3b560e11b60005b8281101561204c57611fd66000858584818110611fa057634e487b7160e01b600052603260045260246000fd5b9050602002016020810190611fb591906140be565b6001600160e01b03198516916001600160a01b039190911614156000613357565b60016101c26000868685818110611ffd57634e487b7160e01b600052603260045260246000fd5b905060200201602081019061201291906140be565b6001600160a01b031681526020810191909152604001600020805460ff191691151591909117905580612044816147aa565b915050611f73565b50505050565b6040805160808101825260008082526020808301829052828401829052606083018290526001600160a01b03861682526101919052919091206004018054839081106120ae57634e487b7160e01b600052603260045260246000fd5b60009182526020918290206040805160808101825292909101546001600160781b0381168352600160781b81046001600160401b0390811694840194909452600160b81b810490931690820152600160f81b90910460ff16151560608201529392505050565b61211c612124565b610994612d08565b63abb87a6f60e01b6108bc61213c61012d5460ff1690565b6001600160e01b0319831690156000612bbe565b6001600160a01b03821660009081526101916020526040812090612173846128d4565b905061217f8482612a4b565b81546001600160801b031680612196575050505050565b82546fffffffffffffffffffffffffffffffff191683558315612225576065546040516362cf156560e11b81526001600160a01b03878116600483015260248201849052600160448301529091169063c59e2aca90606401600060405180830381600087803b15801561220857600080fd5b505af115801561221c573d6000803e3d6000fd5b505050506124a7565b61019454610196546001600160a01b03908116911614156123ba57600061224f621e8480836146bd565b90506000604051806080016040528061226785612c60565b6001600160781b0316815260200161227e426136b2565b6001600160401b0316815260200161229d6119b16301e1338042614663565b6001600160401b039081168252600160209283018190526004890180549182018155600090815283902084519101805493850151604086015160608701511515600160f81b026001600160f81b03918616600160b81b02919091166001600160b81b0392909516600160781b026001600160b81b03199096166001600160781b0390941693909317949094179390931691909117179055905061233f82612c86565b60018601805460009061235c9084906001600160f81b0316614641565b92506101000a8154816001600160f81b0302191690836001600160f81b031602179055508161019860008282546123939190614663565b925050819055508261019a60008282546123ad9190614663565b909155506124a792505050565b6065546101945460405163091465f760e11b81526001600160a01b0391821660048201526000929190911690631228cbee9060240160206040518083038186803b15801561240757600080fd5b505afa15801561241b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061243f91906140da565b6040516344cc892d60e01b81526001600160a01b03888116600483015260248201859052919250908216906344cc892d90604401600060405180830381600087803b15801561248d57600080fd5b505af11580156124a1573d6000803e3d6000fd5b50505050505b604080518515158152602081018390526001600160a01b0387169133917f7aa2446843f85ab4372b9a9eddbe072a35cd062fb199eaddea2ad3b8d0396fa2910160405180910390a35050505050565b60655460408051638da5cb5b60e01b815290516339e71deb60e01b926108bc926001600160a01b0390911691638da5cb5b91600480820192602092909190829003018186803b15801561254857600080fd5b505afa15801561255c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061258091906140da565b6001600160e01b03198316906001600160a01b03163314613327565b61012d5460ff16156125e35760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015260640161092b565b61012d805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586126193390565b6040516001600160a01b03909116815260200160405180910390a1565b61012d5460ff166126805760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b604482015260640161092b565b61012d805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa33612619565b606554610194546040516329018f6f60e21b81526001600160a01b03918216600482015263250f303f60e01b92600092339291169063a4063dbc9060240160206040518083038186803b15801561270857600080fd5b505afa15801561271c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061274091906140da565b6001600160a01b03161490506116b76001600160e01b03198316826000612bbe565b6001600160a01b03811660009081526101916020526040812090612785836128d4565b90506127918382612a4b565b8154600160801b90046001600160801b0316806127ae5750505050565b82546001600160801b03168355610194546127d3906001600160a01b03168583612ca5565b6040518181526001600160a01b0385169033907fa69db2085ef89718710bae5b78f2032cf155ff99feca17d718e69f8ba375c11e9060200160405180910390a350505050565b600054610100900460ff1680612832575060005460ff16155b61284e5760405162461bcd60e51b815260040161092b906145c8565b600054610100900460ff16158015612870576000805461ffff19166101011790555b61287f898989898989896136d1565b6101c38290558015610978576000805461ff0019169055505050505050505050565b8161183557604051633bd8dd9360e21b81526001600160e01b03198416600482015260ff8216602482015260440161092b565b6001600160a01b0381166000908152610191602052604081206001810154600160f81b900460ff1680156118b75760005b81811015612a43576000818152600584016020526040808220546101955491516313935a8360e11b81526001600160a01b038981166004830152602482018390529193929190911690632726b5069060440160a06040518083038186803b15801561296f57600080fd5b505afa158015612983573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129a79190614425565b5050506001600160a01b0389166000908152610192602090815260408083208784529091529020549092509050808211156129e257806129e4565b815b6129ee9088614663565b965081811115612a2d578115612a045781612a07565b60015b6001600160a01b0389166000908152610192602090815260408083208784529091529020555b5050508080612a3b906147aa565b915050612905565b505050919050565b612a53612d08565b6001600160a01b0382166000908152610191602052604081206001810154909190612a889084906001600160f81b0316614663565b90506000612aa8610197548460020154846131749092919063ffffffff16565b90506000612ac76098548560030154856131749092919063ffffffff16565b9050612ad282613857565b84548590600090612aed9084906001600160801b0316614616565b92506101000a8154816001600160801b0302191690836001600160801b03160217905550612b1a81613857565b84548590601090612b3c908490600160801b90046001600160801b0316614616565b82546001600160801b039182166101009390930a928302919092021990911617905550610197546002850155609854600385015560408051838152602081018390526001600160a01b0388169133917f31eeb6a0d26c29b4c243d704ff4ae6feebcc2e8b123df7ea0bd12083c3083cb8910160405180910390a3505050505050565b8161183557604051631db762fb60e31b81526001600160e01b0319841660048201526024810182905260440161092b565b80546000906001600160781b03811690620f4240906301e13380908290612c2f906001600160401b03600160781b8204811691600160b81b90041661473b565b6001600160401b0316612c4291906146bd565b612c4c919061469d565b612c569190614663565b611f5a91906146bd565b6000631e4e4bad60e01b612c7f816001600160781b0385111584613357565b5090919050565b6000631feb933960e11b612c7f816001600160f81b0385111584613357565b6040516001600160a01b03831660248201526044810182905261183590849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152613876565b60655460408051639f1dc9bd60e01b815290516001600160a01b03909216918291639f1dc9bd916004808301926020929190829003018186803b158015612d4e57600080fd5b505afa158015612d62573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d869190614391565b15612ddf57806001600160a01b031663a83c76646040518163ffffffff1660e01b8152600401600060405180830381600087803b158015612dc657600080fd5b505af1158015612dda573d6000803e3d6000fd5b505050505b6000816001600160a01b0316633197cbb66040518163ffffffff1660e01b815260040160206040518083038186803b158015612e1a57600080fd5b505afa158015612e2e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e5291906144c5565b6101965463ffffffff919091169150600160c01b90046001600160401b03168111612e7b575050565b61019654600160c01b90046001600160401b03164211612e99575050565b61019854158015612eab575061019954155b15612ee457612eb9426136b2565b61019660186101000a8154816001600160401b0302191690836001600160401b031602179055505050565b6000814211612ef35742612ef5565b815b61019654909150600090612f1990600160c01b90046001600160401b031683614724565b90506000846001600160a01b0316634251342f6040518163ffffffff1660e01b815260040160206040518083038186803b158015612f5657600080fd5b505afa158015612f6a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f8e91906143ad565b6001600160c01b031690506000856001600160a01b03166396c82e576040518163ffffffff1660e01b815260040160206040518083038186803b158015612fd457600080fd5b505afa158015612fe8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061300c91906144c5565b6101965463ffffffff91821691600160a01b9091041661302c84866146bd565b61303691906146bd565b613040919061469d565b905061305e61019954610198546130579190614663565b8290613115565b61019760008282546130709190614663565b9091555061307f9050846136b2565b61019680546001600160c01b0316600160c01b6001600160401b0393841681029190911791829055610197546040805191825291909204909216602082015233917f33e6f269701b611439c5bd9eae485d1b2f10d29b632a6f0d5688c93c2d77af1f910160405180910390a2505050505050565b60975463eeea774b60e01b906108bc9082906001600160a01b03163314613327565b60008161312b68056bc75e2d63100000856146bd565b613135919061469d565b9392505050565b6040516001600160a01b038085166024830152831660448201526064810182905261204c9085906323b872dd60e01b90608401612cd1565b600068056bc75e2d6310000061318a8385614724565b61319490866146bd565b61319e919061469d565b949350505050565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b6108bc6124f6565b60006131e66131a6565b90506131f184613948565b6000835111806131fe5750815b1561320f5761320d84846139ed565b505b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143805460ff1661332057805460ff191660011781556040516001600160a01b038316602482015261328e90869060440160408051601f198184030181529190526020810180516001600160e01b0316631b2ce7f360e11b1790526139ed565b50805460ff1916815561329f6131a6565b6001600160a01b0316826001600160a01b0316146133175760405162461bcd60e51b815260206004820152602f60248201527f45524331393637557067726164653a207570677261646520627265616b73206660448201526e75727468657220757067726164657360881b606482015260840161092b565b61332085613ad8565b5050505050565b806116b757604051630df66e3d60e41b81526001600160e01b03198316600482015233602482015260440161092b565b81611835576040516301cc826960e41b81526001600160e01b03198416600482015260ff8216602482015260440161092b565b6001600160a01b03811660009081526101c260205260409020546334aae7c960e11b906116b790829060ff1615613327565b3360009081526101916020526040812090638081252560e01b90805b848110156136755761019554600090819081906001600160a01b0316632726b506338b8b8881811061341a57634e487b7160e01b600052603260045260246000fd5b6040516001600160e01b031960e087901b1681526001600160a01b039094166004850152602002919091013560248301525060440160a06040518083038186803b15801561346757600080fd5b505afa15801561347b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061349f9190614425565b94505093509350506134da63623cc7e4836001600160401b031611158560036134c891906146bd565b6001600160e01b031989169190612bbe565b61350a6000836001600160401b03161180156134f4575081155b6134ff8660036146bd565b6134c8906001614663565b3360009081526101926020526040812061356f918b8b8881811061353e57634e487b7160e01b600052603260045260246000fd5b9050602002013581526020019081526020016000205460001485600361356491906146bd565b6134c8906002614663565b3360009081526101926020526040812084918b8b888181106135a157634e487b7160e01b600052603260045260246000fd5b9050602002013581526020019081526020016000208190555082856135c69190614663565b600188018054919650600160f81b90910460ff1690601f6135e6836147c5565b91906101000a81548160ff021916908360ff1602179055505088888581811061361f57634e487b7160e01b600052603260045260246000fd5b9050602002013587600501600060018a600101601f9054906101000a900460ff1661364a919061475b565b60ff16815260200190815260200160002081905550505050808061366d906147aa565b9150506133d8565b5060405181815233907fce2872a31020970c0a5aecb43e7199b699f079f2a54624c757b797e950621cb49060200160405180910390a25050505050565b60006302665fad60e41b612c7f816001600160401b0385111584613357565b600054610100900460ff16806136ea575060005460ff16155b6137065760405162461bcd60e51b815260040161092b906145c8565b600054610100900460ff16158015613728576000805461ffff19166101011790555b630a895f0360e11b613745816001600160a01b03891660026128a1565b6137646001600160e01b031982166001600160a01b03881660036128a1565b6137836001600160e01b031982166001600160401b03861660056128a1565b6137a36001600160e01b0319821663ffffffff808616906006906128a116565b6137ac85613b18565b6137b4613bbd565b6137bc613c30565b5061019480546001600160a01b03199081166001600160a01b038b811691909117909255610193805482168a841617905561019680546101958054909316898516179092559188166001600160c01b031990911617600160a01b63ffffffff851602176001600160c01b0316600160c01b6001600160401b03861602179055801561384d576000805461ff00191690555b5050505050505050565b600063809fdd3360e01b612c7f816001600160801b0385111584613357565b60006138cb826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316613c979092919063ffffffff16565b80519091501561183557808060200190518101906138e99190614391565b6118355760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840161092b565b803b6139ac5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b606482015260840161092b565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b0319166001600160a01b0392909216919091179055565b6060823b613a4c5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b606482015260840161092b565b600080846001600160a01b031684604051613a6791906144e1565b600060405180830381855af49150503d8060008114613aa2576040519150601f19603f3d011682016040523d82523d6000602084013e613aa7565b606091505b5091509150613acf828260405180606001604052806027815260200161485c60279139613ca6565b95945050505050565b613ae181613948565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b600054610100900460ff1680613b31575060005460ff16155b613b4d5760405162461bcd60e51b815260040161092b906145c8565b600054610100900460ff16158015613b6f576000805461ffff19166101011790555b63bb6c0dbf60e01b613b8c816001600160a01b03851660006128a1565b50606580546001600160a01b0319166001600160a01b03841617905580156116b7576000805461ff00191690555050565b600054610100900460ff1680613bd6575060005460ff16155b613bf25760405162461bcd60e51b815260040161092b906145c8565b600054610100900460ff16158015613c14576000805461ffff19166101011790555b613c1c613cdf565b80156108bc576000805461ff001916905550565b600054610100900460ff1680613c49575060005460ff16155b613c655760405162461bcd60e51b815260040161092b906145c8565b600054610100900460ff16158015613c87576000805461ffff19166101011790555b613c8f613d4f565b613c1c613db9565b606061319e8484600085613e2f565b60608315613cb5575081613135565b825115613cc55782518084602001fd5b8160405162461bcd60e51b815260040161092b91906144fd565b600054610100900460ff1680613cf8575060005460ff16155b613d145760405162461bcd60e51b815260040161092b906145c8565b600054610100900460ff16158015613d36576000805461ffff19166101011790555b600160c95580156108bc576000805461ff001916905550565b600054610100900460ff1680613d68575060005460ff16155b613d845760405162461bcd60e51b815260040161092b906145c8565b600054610100900460ff16158015613c1c576000805461ffff191661010117905580156108bc576000805461ff001916905550565b600054610100900460ff1680613dd2575060005460ff16155b613dee5760405162461bcd60e51b815260040161092b906145c8565b600054610100900460ff16158015613e10576000805461ffff19166101011790555b61012d805460ff1916905580156108bc576000805461ff001916905550565b606082471015613e905760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840161092b565b843b613ede5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161092b565b600080866001600160a01b03168587604051613efa91906144e1565b60006040518083038185875af1925050503d8060008114613f37576040519150601f19603f3d011682016040523d82523d6000602084013e613f3c565b606091505b5091509150613f4c828286613ca6565b979650505050505050565b8280548282559060005260206000209081019282156140365760005260206000209182015b8281111561403657825482546001600160781b039091166effffffffffffffffffffffffffffff1982168117845584546001600160b81b031990921617600160781b918290046001600160401b0390811690920217808455845467ffffffffffffffff60b81b198216600160b81b9182900490931602918217845584546001600160b81b039091166001600160f81b0390921691909117600160f81b9182900460ff16151590910217825560019283019290910190613f7c565b50614042929150614060565b5090565b50805460008255906000526020600020908101906108bc91905b5b808211156140425760008155600101614061565b60008083601f840112614086578081fd5b5081356001600160401b0381111561409c578182fd5b6020830191508360208260051b85010111156140b757600080fd5b9250929050565b6000602082840312156140cf578081fd5b813561313581614811565b6000602082840312156140eb578081fd5b815161313581614811565b600080600080600080600080610100898b031215614112578384fd5b883561411d81614811565b9750602089013561412d81614811565b9650604089013561413d81614811565b9550606089013561414d81614811565b9450608089013561415d81614846565b935060a089013561416d81614834565b925060c089013561417d81614811565b8092505060e089013590509295985092959890939650565b600080604083850312156141a7578182fd5b82356141b281614811565b915060208301356141c281614826565b809150509250929050565b600080604083850312156141df578182fd5b82356141ea81614811565b915060208301356001600160401b0380821115614205578283fd5b818501915085601f830112614218578283fd5b81358181111561422a5761422a6147fb565b604051601f8201601f19908116603f01168101908382118183101715614252576142526147fb565b8160405282815288602084870101111561426a578586fd5b82602086016020830137856020848301015280955050505050509250929050565b6000806040838503121561429d578182fd5b82356142a881614811565b946020939093013593505050565b600080602083850312156142c8578182fd5b82356001600160401b038111156142dd578283fd5b6142e985828601614075565b90969095509350505050565b600080600060408486031215614309578283fd5b83356001600160401b038082111561431f578485fd5b818601915086601f830112614332578485fd5b813581811115614340578586fd5b8760208260061b8501011115614354578586fd5b6020928301955093505084013561436a81614826565b809150509250925092565b600060208284031215614386578081fd5b813561313581614826565b6000602082840312156143a2578081fd5b815161313581614826565b6000602082840312156143be578081fd5b81516001600160c01b0381168114613135578182fd5b6000602082840312156143e5578081fd5b5035919050565b6000602082840312156143fd578081fd5b5051919050565b60008060408385031215614416578182fd5b50508035926020909101359150565b600080600080600060a0868803121561443c578283fd5b8551945060208601519350604086015161445581614846565b606087015190935061446681614846565b608087015190925061447781614826565b809150509295509295909350565b60008060408385031215614497578182fd5b8235915060208301356141c281614846565b6000602082840312156144ba578081fd5b813561313581614834565b6000602082840312156144d6578081fd5b815161313581614834565b600082516144f381846020870161477e565b9190910192915050565b602081526000825180602084015261451c81604085016020870161477e565b601f01601f19169190910160400192915050565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b6163746976652070726f787960a01b606082015260800190565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b60006001600160801b03808316818516808303821115614638576146386147e5565b01949350505050565b60006001600160f81b03828116848216808303821115614638576146386147e5565b60008219821115614676576146766147e5565b500190565b60006001600160401b03808316818516808303821115614638576146386147e5565b6000826146b857634e487b7160e01b81526012600452602481fd5b500490565b60008160001904831182151516156146d7576146d76147e5565b500290565b60006001600160781b03838116908316818110156146fc576146fc6147e5565b039392505050565b60006001600160f81b03838116908316818110156146fc576146fc6147e5565b600082821015614736576147366147e5565b500390565b60006001600160401b03838116908316818110156146fc576146fc6147e5565b600060ff821660ff841680821015614775576147756147e5565b90039392505050565b60005b83811015614799578181015183820152602001614781565b8381111561204c5750506000910152565b60006000198214156147be576147be6147e5565b5060010190565b600060ff821660ff8114156147dc576147dc6147e5565b60010192915050565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b03811681146108bc57600080fd5b80151581146108bc57600080fd5b63ffffffff811681146108bc57600080fd5b6001600160401b03811681146108bc57600080fdfe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a164736f6c6343000804000a
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
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.