Overview
APE Balance
0 APE
APE Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 1 from a total of 1 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
0x60806040 | 4600705 | 14 hrs ago | IN | 0 APE | 0.09863349 |
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
GNSStaking
Compiler Version
v0.8.23+commit.f704f362
Optimization Enabled:
Yes with 800 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity 0.8.23; import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import {OwnableUpgradeable, Ownable2StepUpgradeable} from "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol"; import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "../interfaces/IGNSStaking.sol"; import "../interfaces/IERC20.sol"; import "../libraries/CollateralUtils.sol"; import "../misc/VotingDelegator.sol"; /** * @dev Staking contract for GNS token to earn in multiple reward tokens from fees generated on gTrade. */ contract GNSStaking is Initializable, Ownable2StepUpgradeable, IGNSStaking, VotingDelegator { using SafeERC20 for IERC20; uint48 private constant MAX_UNLOCK_DURATION = 730 days; // 2 years in seconds uint128 private constant MIN_UNLOCK_GNS_AMOUNT = 1e18; uint48 private constant UNSTAKING_COOLDOWN_SECONDS = 100; IERC20 public gns; IERC20 public dai; uint128 public accDaiPerToken; // deprecated (old rewards) uint128 public gnsBalance; mapping(address => Staker) public stakers; // stakers.debtDai is deprecated (old dai rewards) mapping(address => UnlockSchedule[]) private unlockSchedules; // unlockSchedules.debtDai is deprecated (old dai rewards) mapping(address => bool) public unlockManagers; // addresses allowed to create vests for others address[] public rewardTokens; mapping(address => RewardState) public rewardTokenState; mapping(address => mapping(address => RewardInfo)) public userTokenRewards; // user => token => info mapping(address => mapping(address => mapping(uint256 => RewardInfo))) public userTokenUnlockRewards; // user => token => unlock ID => info mapping(address => StakerInfo) public stakerInfos; // user => info /// @custom:oz-upgrades-unsafe-allow constructor constructor() { _disableInitializers(); } /** * @dev Sets `owner` and initializes `dai` and `gns` state variables */ function initialize(address _owner, IERC20 _gns, IERC20 _dai) external initializer { require( address(_owner) != address(0) && address(_gns) != address(0) && address(_dai) != address(0), "WRONG_PARAMS" ); _transferOwnership(_owner); gns = _gns; dai = _dai; } /** * @dev Add `dai` as a reward token (old stakers.debtDai, unlockSchedules.debtDai and accDaiPerToken are deprecacted now) * Necessary to call right after contract is updated because otherwise distributeRewardDai() reverts. */ function initializeV2() external reinitializer(2) { _addRewardToken(address(dai)); } /** * @dev Modifier used for vest creation access control. * Users can create non-revocable vests for themselves only, `owner` and `unlockManagers` can create both types for anyone. */ modifier onlyAuthorizedUnlockManager(address _staker, bool _revocable) { require( (_staker == msg.sender && !_revocable) || msg.sender == owner() || unlockManagers[msg.sender], "NO_AUTH" ); _; } /** * @dev Modifier to reject any `_token` not configured as a reward token */ modifier onlyRewardToken(address _token) { require(isRewardToken(_token), "INVALID_TOKEN"); _; } /** * @dev Modifier to ensure operation is not performed before cooldown period has expired */ modifier notInCooldown() { require( uint48(block.timestamp) > stakerInfos[msg.sender].lastDepositTs + UNSTAKING_COOLDOWN_SECONDS, "IN_COOLDOWN" ); _; } /** * @dev Sets whether `_manager` is `_authorized` to create vests for other users. * * Emits {UnlockManagerUpdated} */ function setUnlockManager(address _manager, bool _authorized) external onlyOwner { unlockManagers[_manager] = _authorized; emit UnlockManagerUpdated(_manager, _authorized); } /** * @dev Adds `_token` as a reward token, configures its precision delta. * * precisionDelta = 10^(18-decimals), eg. USDC 6 decimals => precisionDelta = 1e12 * It is used to scale up from token amounts to 1e18 normalized accRewardPerGns/debtToken * and to scale down from accRewardPerGns/debtToken back to 'real' pending token amounts. * * Emits {RewardTokenAdded} */ function _addRewardToken(address _token) private { require(_token != address(0), "ZERO_ADDRESS"); require(!isRewardToken(_token), "DUPLICATE"); rewardTokens.push(_token); uint128 precisionDelta = CollateralUtils.getCollateralConfig(_token).precisionDelta; rewardTokenState[_token].precisionDelta = precisionDelta; emit RewardTokenAdded(_token, rewardTokens.length - 1, precisionDelta); } /** * @dev Forwards call to {_addRewardToken}. Only callable by `owner`. */ function addRewardToken(address _token) external onlyOwner { _addRewardToken(_token); } /** * @dev Attempts to set the delegatee of `_token` to `_delegatee`. `_token` must be a valid reward token. */ function setDelegatee(address _token, address _delegatee) external onlyRewardToken(_token) onlyOwner { require(_delegatee != address(0), "ADDRESS_0"); _tryDelegate(_token, _delegatee); } /** * @dev Returns the current debt (1e18 precision) for a token given `_stakedGns` and `_accRewardPerGns` */ function _currentDebtToken(uint128 _stakedGns, uint128 _accRewardPerGns) private pure returns (uint128) { return uint128((uint256(_stakedGns) * _accRewardPerGns) / 1e18); } /** * @dev Returns the amount of pending token rewards (precision depends on token) given `_currDebtToken`, `_lastDebtToken` and `_precisionDelta` */ function _pendingTokens( uint128 _currDebtToken, uint128 _lastDebtToken, uint128 _precisionDelta ) private pure returns (uint128) { return (_currDebtToken - _lastDebtToken) / _precisionDelta; } /** * @dev Returns the amount of pending token rewards (precision depends on token) given `_stakedGns`, `_lastDebtToken` and `_rewardState` for a token */ function _pendingTokens( uint128 _stakedGns, uint128 _lastDebtToken, RewardState memory _rewardState ) private pure returns (uint128) { return _pendingTokens( _currentDebtToken(_stakedGns, _rewardState.accRewardPerGns), _lastDebtToken, _rewardState.precisionDelta ); } /** * @dev returns pending old dai (1e18 precision) given `_currDebtDai` and `_lastDebtDai` * @custom:deprecated to be removed in version after v7 */ function _pendingDaiPure(uint128 _currDebtDai, uint128 _lastDebtDai) private pure returns (uint128) { return _pendingTokens(_currDebtDai, _lastDebtDai, 1); } /** * @dev returns pending old dai (1e18 precision) given `_stakedGns` amount and `_lastDebtDai` * @custom:deprecated to be removed in version after v7 */ function _pendingDai(uint128 _stakedGns, uint128 _lastDebtDai) private view returns (uint128) { return _pendingDaiPure(_currentDebtToken(_stakedGns, accDaiPerToken), _lastDebtDai); } /** * @dev returns pending old dai (1e18 precision) given `_schedule` * @custom:deprecated to be removed in version after v7 */ function _pendingDai(UnlockSchedule memory _schedule) private view returns (uint128) { return _pendingDaiPure( _currentDebtToken(_scheduleStakedGns(_schedule.totalGns, _schedule.claimedGns), accDaiPerToken), _schedule.debtDai ); } /** * @dev returns staked gns (1e18 precision) given `_totalGns` and `_claimedGns` */ function _scheduleStakedGns(uint128 _totalGns, uint128 _claimedGns) private pure returns (uint128) { return _totalGns - _claimedGns; } /** * @dev Returns the unlocked GNS tokens amount of `_schedule` at `_timestamp`. * Includes already claimed GNS tokens. */ function unlockedGns(UnlockSchedule memory _schedule, uint48 _timestamp) public pure returns (uint128) { // if vest has ended return totalGns if (_timestamp >= _schedule.start + _schedule.duration) return _schedule.totalGns; // if unlock hasn't started or it's a cliff unlock return 0 if (_timestamp < _schedule.start || _schedule.unlockType == UnlockType.CLIFF) return 0; return uint128((uint256(_schedule.totalGns) * (_timestamp - _schedule.start)) / _schedule.duration); } /** * @dev Returns the releasable GNS tokens amount (1e18 precision) of `_schedule` at `_timestamp`. * Doesn't include already claimed GNS tokens. */ function releasableGns(UnlockSchedule memory _schedule, uint48 _timestamp) public pure returns (uint128) { return unlockedGns(_schedule, _timestamp) - _schedule.claimedGns; } /** * @dev Returns the owner of the contract. */ function owner() public view override(IGNSStaking, OwnableUpgradeable) returns (address) { return super.owner(); } /** * @dev Returns whether `_token` is a listed reward token. */ function isRewardToken(address _token) public view returns (bool) { return rewardTokenState[_token].precisionDelta > 0; } /** * @dev Harvests `msg.sender`'s `_token` pending rewards for non-vested GNS. * * Handles updating `stake.debtToken` with new debt given `_stakedGns`. * Transfers pending `_token` rewards to `msg.sender`. * * Emits {RewardHarvested} */ function _harvestToken(address _token, uint128 _stakedGns) private returns (uint128 pendingTokens) { RewardInfo storage userInfo = userTokenRewards[msg.sender][_token]; RewardState memory rewardState = rewardTokenState[_token]; uint128 newDebtToken = _currentDebtToken(_stakedGns, rewardState.accRewardPerGns); pendingTokens = _pendingTokens(newDebtToken, userInfo.debtToken, rewardState.precisionDelta); userInfo.debtToken = newDebtToken; IERC20(_token).safeTransfer(msg.sender, uint256(pendingTokens)); emit RewardHarvested(msg.sender, _token, pendingTokens); } /** * @dev Harvest pending `_token` rewards of `_staker` for vests `_ids`. * `_isOldDai` allows to differentiate between the old dai rewards before v7 and the new ones. * * Emits {RewardHarvestedFromUnlock} */ function _harvestFromUnlock( address _staker, address _token, uint256[] memory _ids, bool _isOldDai ) private returns (uint128 pendingTokens) { require(_staker != address(0), "USER_EMPTY"); if (_ids.length == 0) return 0; uint128 precisionDelta; // only used when _isOldDai == false uint128 accRewardPerGns; /// @custom:deprecated to be removed in version after v7 (only keep else part) if (_isOldDai) { accRewardPerGns = accDaiPerToken; } else { RewardState memory rewardState = rewardTokenState[_token]; precisionDelta = rewardState.precisionDelta; accRewardPerGns = rewardState.accRewardPerGns; } for (uint256 i; i < _ids.length; ) { uint256 unlockId = _ids[i]; UnlockSchedule storage schedule = unlockSchedules[_staker][unlockId]; uint128 newDebtToken = _currentDebtToken( _scheduleStakedGns(schedule.totalGns, schedule.claimedGns), accRewardPerGns ); /// @custom:deprecated to be removed in version after v7 (only keep else part) if (_isOldDai) { pendingTokens += _pendingDaiPure(newDebtToken, schedule.debtDai); schedule.debtDai = newDebtToken; } else { RewardInfo storage unlockInfo = userTokenUnlockRewards[_staker][_token][unlockId]; pendingTokens += _pendingTokens(newDebtToken, unlockInfo.debtToken, precisionDelta); unlockInfo.debtToken = newDebtToken; } unchecked { ++i; } } IERC20(_token).safeTransfer(_staker, uint256(pendingTokens)); emit RewardHarvestedFromUnlock(_staker, _token, _isOldDai, _ids, pendingTokens); } /** * @dev Harvests the `_staker`'s vests `_ids` pending rewards for '_token' */ function _harvestTokenFromUnlock(address _staker, address _token, uint256[] memory _ids) private returns (uint128) { return _harvestFromUnlock(_staker, _token, _ids, false); } /** * @dev Harvests the `_staker`'s vests `_ids` pending rewards for all supported reward tokens */ function _harvestTokensFromUnlock(address _staker, address[] memory _rewardTokens, uint256[] memory _ids) private { for (uint256 i; i < _rewardTokens.length; ) { _harvestTokenFromUnlock(_staker, _rewardTokens[i], _ids); unchecked { ++i; } } } /** * @dev Harvests the `_staker`'s vests `_ids` old dai pending rewards */ function _harvestDaiFromUnlock(address _staker, uint256[] memory _ids) private { _harvestFromUnlock(_staker, address(dai), _ids, true); } /** * @dev Loops through all `rewardTokens` and syncs `debtToken`. * Used when staking or unstaking gns and only after claiming pending rewards. * If called before harvesting, all pending rewards will be lost. */ function _syncRewardTokensDebt(address _staker, uint128 _stakedGns) private { uint256 len = rewardTokens.length; for (uint256 i; i < len; ) { address rewardToken = rewardTokens[i]; userTokenRewards[_staker][rewardToken].debtToken = _currentDebtToken( _stakedGns, rewardTokenState[rewardToken].accRewardPerGns ); unchecked { ++i; } } } /** * @dev Loops through all `_rewardTokens` and syncs `debtToken`. * Used when creating a vest or when claiming unlocked GNS from a vest, after claiming pending rewards. * If called before harvesting, all pending rewards will be lost. */ function _syncUnlockRewardTokensDebt( address _staker, address[] memory _rewardTokens, uint256 _unlockId, uint128 _stakedGns ) private { for (uint256 i; i < _rewardTokens.length; ) { address rewardToken = _rewardTokens[i]; userTokenUnlockRewards[_staker][rewardToken][_unlockId].debtToken = _currentDebtToken( _stakedGns, rewardTokenState[rewardToken].accRewardPerGns ); unchecked { ++i; } } } /** * @dev Harvests old dai and all supported tokens pending rewards for vests `_ids` of `_staker`. * * Then calculates each vest's releasable `amountGns` given `_timestamp`, increases their 'claimedGns' by this amount, * and syncs old `debtDai` and all supported tokens debts. * * Finally transfers the total claimable GNS of all vests to `_staker`. * * Emits {GnsClaimed} */ function _claimUnlockedGns(address _staker, uint256[] memory _ids, uint48 _timestamp) private { uint128 claimedGns; address[] memory rewardTokensArray = rewardTokens; _harvestDaiFromUnlock(_staker, _ids); _harvestTokensFromUnlock(_staker, rewardTokensArray, _ids); for (uint256 i; i < _ids.length; ) { uint256 unlockId = _ids[i]; UnlockSchedule storage schedule = unlockSchedules[_staker][unlockId]; // get gns amount being claimed for current vest uint128 amountGns = releasableGns(schedule, _timestamp); // make sure new vest total claimed amount is not more than total gns for vest uint128 scheduleNewClaimedGns = schedule.claimedGns + amountGns; uint128 scheduleTotalGns = schedule.totalGns; assert(scheduleNewClaimedGns <= scheduleTotalGns); // update vest claimed gns schedule.claimedGns = scheduleNewClaimedGns; // sync debts for all tokens uint128 newStakedGns = _scheduleStakedGns(scheduleTotalGns, scheduleNewClaimedGns); schedule.debtDai = _currentDebtToken(newStakedGns, accDaiPerToken); /// @custom:deprecated to be removed in version after v7 _syncUnlockRewardTokensDebt(_staker, rewardTokensArray, unlockId, newStakedGns); claimedGns += amountGns; unchecked { ++i; } } gnsBalance -= claimedGns; gns.safeTransfer(_staker, uint256(claimedGns)); emit GnsClaimed(_staker, _ids, claimedGns); } /** * @dev Transfers `_amountToken` of `_token` (valid reward token) from caller to this contract and updates `accRewardPerGns`. * * @dev Note: `accRewardPerGns` is normalized to 1e18 for all reward tokens (even those with less than 18 decimals) * * Emits {RewardDistributed} */ function distributeReward(address _token, uint256 _amountToken) external override onlyRewardToken(_token) { require(gnsBalance > 0, "NO_GNS_STAKED"); IERC20(_token).safeTransferFrom(msg.sender, address(this), _amountToken); RewardState storage rewardState = rewardTokenState[_token]; rewardState.accRewardPerGns += uint128((_amountToken * rewardState.precisionDelta * 1e18) / gnsBalance); emit RewardDistributed(_token, _amountToken); } /** * @dev Harvests the caller's regular pending `_token` rewards. `_token` must be a valid reward token. */ function harvestToken(address _token) public onlyRewardToken(_token) returns (uint128) { return _harvestToken(_token, stakers[msg.sender].stakedGns); } /** * @dev Harvests the caller's pending `_token` rewards for vests `_ids`. `_token` must be a valid reward token. */ function harvestTokenFromUnlock( address _token, uint[] calldata _ids ) public onlyRewardToken(_token) returns (uint128) { return _harvestTokenFromUnlock(msg.sender, _token, _ids); } /** * @dev Harvests the caller's regular pending `_token` rewards and pending rewards for vests `_ids`. */ function harvestTokenAll(address _token, uint[] calldata _ids) public returns (uint128) { return harvestToken(_token) + harvestTokenFromUnlock(_token, _ids); } /** * @dev Harvests the caller's regular pending rewards for all supported reward tokens. */ function harvestTokens() public { uint128 stakedGns = stakers[msg.sender].stakedGns; uint256 len = rewardTokens.length; for (uint256 i; i < len; ) { _harvestToken(rewardTokens[i], stakedGns); unchecked { ++i; } } } /** * @dev Harvests the caller's pending rewards of vests `_ids` for all supported reward tokens. */ function harvestTokensFromUnlock(uint[] calldata _ids) public { _harvestTokensFromUnlock(msg.sender, rewardTokens, _ids); } /** * @dev Harvests the caller's regular pending rewards and pending rewards of vests `_ids` for all supported reward tokens. */ function harvestTokensAll(uint[] calldata _ids) public { harvestTokens(); harvestTokensFromUnlock(_ids); } /** * @dev Harvests the caller's GNS pending rewards and then stakes them */ function compoundGnsRewards(uint[] calldata _ids) external { stakeGns(harvestTokenAll(address(gns), _ids)); } /** * @dev Harvests caller's old regular dai rewards. * @custom:deprecated to be removed in version after v7 * * Emits {DaiHarvested} */ function harvestDai() public { Staker storage staker = stakers[msg.sender]; uint128 newDebtDai = _currentDebtToken(staker.stakedGns, accDaiPerToken); uint128 pendingDai = _pendingDaiPure(newDebtDai, staker.debtDai); staker.debtDai = newDebtDai; dai.safeTransfer(msg.sender, uint256(pendingDai)); emit DaiHarvested(msg.sender, pendingDai); } /** * @dev Harvests caller's old dai rewards for vests `_ids`. * @custom:deprecated to be removed in version after v7 */ function harvestDaiFromUnlock(uint256[] calldata _ids) public { _harvestDaiFromUnlock(msg.sender, _ids); } /** * @dev Harvests caller's old regular dai rewards and old dai rewards of vests `_ids`. * @custom:deprecated to be removed in version after v7 */ function harvestDaiAll(uint256[] calldata _ids) public { harvestDai(); harvestDaiFromUnlock(_ids); } /** * @dev Harvests the caller's regular pending rewards and pending rewards for vests `_ids` for all supported reward tokens (+ old DAI rewards). * @custom:deprecated to be removed in version after v7, can just use {harvestTokensAll} */ function harvestAll(uint[] calldata _ids) external { harvestTokensAll(_ids); harvestDaiAll(_ids); } /** * @dev Stakes non-vested `_amountGns` from caller. * * Emits {GnsStaked} */ function stakeGns(uint128 _amountGns) public { require(_amountGns > 0, "AMOUNT_ZERO"); gns.safeTransferFrom(msg.sender, address(this), uint256(_amountGns)); harvestDai(); harvestTokens(); Staker storage staker = stakers[msg.sender]; uint128 newStakedGns = staker.stakedGns + _amountGns; staker.stakedGns = newStakedGns; /// @custom:deprecated to be removed in version after v7 staker.debtDai = _currentDebtToken(newStakedGns, accDaiPerToken); // Update `.debtToken` for all reward tokens using newStakedGns _syncRewardTokensDebt(msg.sender, newStakedGns); gnsBalance += _amountGns; // Update lastDeposit stakerInfos[msg.sender].lastDepositTs = uint48(block.timestamp); emit GnsStaked(msg.sender, _amountGns); } /** * @dev Unstakes non-vested `_amountGns` from caller. * * Emits {GnsUnstaked} */ function unstakeGns(uint128 _amountGns) external notInCooldown { require(_amountGns > 0, "AMOUNT_ZERO"); harvestDai(); harvestTokens(); Staker storage staker = stakers[msg.sender]; uint128 newStakedGns = staker.stakedGns - _amountGns; // reverts if _amountGns > staker.stakedGns (underflow) staker.stakedGns = newStakedGns; /// @custom:deprecated to be removed in version after v7 staker.debtDai = _currentDebtToken(newStakedGns, accDaiPerToken); // Update `.debtToken` for all reward tokens with current newStakedGns _syncRewardTokensDebt(msg.sender, newStakedGns); gnsBalance -= _amountGns; gns.safeTransfer(msg.sender, uint256(_amountGns)); emit GnsUnstaked(msg.sender, _amountGns); } /** * @dev Claims caller's unlocked GNS from vests `_ids`. */ function claimUnlockedGns(uint256[] memory _ids) external { _claimUnlockedGns(msg.sender, _ids, uint48(block.timestamp)); } /** * @dev Creates vest for `_staker` given `_schedule` input parameters. * Restricted with onlyAuthorizedUnlockManager access control. * * Emits {UnlockScheduled} */ function createUnlockSchedule( UnlockScheduleInput calldata _schedule, address _staker ) external override onlyAuthorizedUnlockManager(_staker, _schedule.revocable) { uint48 timestamp = uint48(block.timestamp); require(_schedule.start < timestamp + MAX_UNLOCK_DURATION, "TOO_FAR_IN_FUTURE"); require( _schedule.duration >= UNSTAKING_COOLDOWN_SECONDS && _schedule.duration <= MAX_UNLOCK_DURATION, "INCORRECT_DURATION" ); require(_schedule.totalGns >= MIN_UNLOCK_GNS_AMOUNT, "INCORRECT_AMOUNT"); require(_staker != address(0), "ADDRESS_0"); uint128 totalGns = _schedule.totalGns; // Requester has to pay the gns amount gns.safeTransferFrom(msg.sender, address(this), uint256(totalGns)); UnlockSchedule memory schedule = UnlockSchedule({ totalGns: totalGns, claimedGns: 0, debtDai: _currentDebtToken(totalGns, accDaiPerToken), /// @custom:deprecated to be removed in version after v7 start: _schedule.start >= timestamp ? _schedule.start : timestamp, // accept time in the future duration: _schedule.duration, unlockType: _schedule.unlockType, revocable: _schedule.revocable, __placeholder: 0 }); unlockSchedules[_staker].push(schedule); gnsBalance += totalGns; uint256 unlockId = unlockSchedules[_staker].length - 1; // Set `.debtToken` for all available rewardTokens _syncUnlockRewardTokensDebt(_staker, rewardTokens, unlockId, totalGns); emit UnlockScheduled(_staker, unlockId, schedule); } /** * @dev Revokes vest `_id` for `_staker`. Sends the unlocked GNS to `_staker` and sends the remaining locked GNS to `owner`. * Only callable by `owner`. * * Emits {UnlockScheduleRevoked} */ function revokeUnlockSchedule(address _staker, uint256 _id) external onlyOwner { UnlockSchedule storage schedule = unlockSchedules[_staker][_id]; require(schedule.revocable, "NOT_REVOCABLE"); uint256[] memory ids = new uint256[](1); ids[0] = _id; // claims unlocked gns and harvests pending rewards _claimUnlockedGns(_staker, ids, uint48(block.timestamp)); // store remaining gns staked before resetting schedule uint128 lockedAmountGns = _scheduleStakedGns(schedule.totalGns, schedule.claimedGns); // resets vest so no more claims or harvests are possible schedule.totalGns = schedule.claimedGns; schedule.duration = 0; schedule.start = 0; schedule.debtDai = 0; /// @custom:deprecated to be removed in version after v7 // reset all other reward tokens `debtToken` to 0 (by passing _stakedGns = 0) _syncUnlockRewardTokensDebt(_staker, rewardTokens, _id, 0); gnsBalance -= lockedAmountGns; gns.safeTransfer(owner(), uint256(lockedAmountGns)); emit UnlockScheduleRevoked(_staker, _id); } /** * @dev Returns the pending `_token` rewards (precision depends on token) for `_staker`. */ function pendingRewardToken(address _staker, address _token) public view returns (uint128) { if (!isRewardToken(_token)) return 0; return _pendingTokens( stakers[_staker].stakedGns, userTokenRewards[_staker][_token].debtToken, rewardTokenState[_token] ); } /** * @dev Returns an array of `_staker`'s pending rewards (precision depends on token) for all supported tokens. */ function pendingRewardTokens(address _staker) external view returns (uint128[] memory pendingTokens) { uint256 len = rewardTokens.length; pendingTokens = new uint128[](len); for (uint256 i; i < len; ++i) { pendingTokens[i] = pendingRewardToken(_staker, rewardTokens[i]); } return pendingTokens; } /** * @dev Returns an array of `_staker`'s pending rewards (precision depends on token) from vests `_ids` for all supported tokens. */ function pendingRewardTokensFromUnlocks( address _staker, uint256[] calldata _ids ) external view returns (uint128[] memory pendingTokens) { address[] memory rewardTokensArray = rewardTokens; pendingTokens = new uint128[](rewardTokensArray.length); for (uint256 i; i < _ids.length; ++i) { UnlockSchedule storage schedule = unlockSchedules[_staker][_ids[i]]; uint128 stakedGns = _scheduleStakedGns(schedule.totalGns, schedule.claimedGns); for (uint256 j; j < rewardTokensArray.length; ++j) { address rewardToken = rewardTokensArray[j]; pendingTokens[j] += _pendingTokens( stakedGns, userTokenUnlockRewards[_staker][rewardToken][_ids[i]].debtToken, rewardTokenState[rewardToken] ); } } } /** * @dev Returns `_staker`'s pending old dai rewards (1e18 precision). * @custom:deprecated to be removed in version after v7 */ function pendingRewardDai(address _staker) external view returns (uint128) { Staker memory staker = stakers[_staker]; return _pendingDai(staker.stakedGns, staker.debtDai); } /** * @dev Returns `_staker`'s pending old dai rewards (1e18 precision) from vests `_ids`. * @custom:deprecated to be removed in version after v7 */ function pendingRewardDaiFromUnlocks( address _staker, uint256[] calldata _ids ) external view returns (uint128 pending) { for (uint256 i; i < _ids.length; ++i) { pending += _pendingDai(unlockSchedules[_staker][_ids[i]]); } } /** * @dev Returns `_staker's` total non-vested and vested GNS staked (1e18 precision) */ function totalGnsStaked(address _staker) external view returns (uint128) { uint128 totalGns = stakers[_staker].stakedGns; UnlockSchedule[] memory stakerUnlocks = unlockSchedules[_staker]; for (uint256 i; i < stakerUnlocks.length; ++i) { UnlockSchedule memory schedule = stakerUnlocks[i]; totalGns += _scheduleStakedGns(schedule.totalGns, schedule.claimedGns); } return totalGns; } /** * @dev Returns all `_staker's` vests. */ function getUnlockSchedules(address _staker) external view returns (UnlockSchedule[] memory) { return unlockSchedules[_staker]; } /** * @dev Returns `_staker's` vest at `_index'` */ function getUnlockSchedules(address _staker, uint256 _index) external view returns (UnlockSchedule memory) { return unlockSchedules[_staker][_index]; } /** * @dev Returns the address of all supported reward tokens */ function getRewardTokens() external view returns (address[] memory) { return rewardTokens; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol) pragma solidity ^0.8.0; import "./OwnableUpgradeable.sol"; import {Initializable} from "../proxy/utils/Initializable.sol"; /** * @dev Contract module which provides access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership} and {acceptOwnership}. * * This module is used through inheritance. It will make available all functions * from parent (Ownable). */ abstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable { address private _pendingOwner; event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner); function __Ownable2Step_init() internal onlyInitializing { __Ownable_init_unchained(); } function __Ownable2Step_init_unchained() internal onlyInitializing { } /** * @dev Returns the address of the pending owner. */ function pendingOwner() public view virtual returns (address) { return _pendingOwner; } /** * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual override onlyOwner { _pendingOwner = newOwner; emit OwnershipTransferStarted(owner(), newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner. * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual override { delete _pendingOwner; super._transferOwnership(newOwner); } /** * @dev The new owner accepts the ownership transfer. */ function acceptOwnership() public virtual { address sender = _msgSender(); require(pendingOwner() == sender, "Ownable2Step: caller is not the new owner"); _transferOwnership(sender); } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/ContextUpgradeable.sol"; import {Initializable} from "../proxy/utils/Initializable.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ function __Ownable_init() internal onlyInitializing { __Ownable_init_unchained(); } function __Ownable_init_unchained() internal onlyInitializing { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.2; import "../../utils/AddressUpgradeable.sol"; /** * @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 proxied contracts do not make use of 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. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ```solidity * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * 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. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. * @custom:oz-retyped-from bool */ uint8 private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint8 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. * * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a * constructor. * * Emits an {Initialized} event. */ modifier initializer() { bool isTopLevelCall = !_initializing; require( (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1), "Initializable: contract is already initialized" ); _initialized = 1; if (isTopLevelCall) { _initializing = true; } _; if (isTopLevelCall) { _initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * A reinitializer may be used after the original initialization step. This is essential to configure modules that * are added through upgrades and that require initialization. * * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer` * cannot be nested. If one is invoked in the context of another, execution will revert. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. * * WARNING: setting the version to 255 will prevent any future reinitialization. * * Emits an {Initialized} event. */ modifier reinitializer(uint8 version) { require(!_initializing && _initialized < version, "Initializable: contract is already initialized"); _initialized = version; _initializing = true; _; _initializing = false; emit Initialized(version); } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { require(_initializing, "Initializable: contract is not initializing"); _; } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. * * Emits an {Initialized} event the first time it is successfully executed. */ function _disableInitializers() internal virtual { require(!_initializing, "Initializable: contract is initializing"); if (_initialized != type(uint8).max) { _initialized = type(uint8).max; emit Initialized(type(uint8).max); } } /** * @dev Returns the highest version that has been initialized. See {reinitializer}. */ function _getInitializedVersion() internal view returns (uint8) { return _initialized; } /** * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}. */ function _isInitializing() internal view returns (bool) { return _initializing; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @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 * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol) pragma solidity ^0.8.0; import {Initializable} from "../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 onlyInitializing { } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; /** * @dev Interface for the optional metadata functions from the ERC20 standard. * * _Available since v4.1._ */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.4) (token/ERC20/extensions/IERC20Permit.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. * * ==== Security Considerations * * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be * considered as an intention to spend the allowance in any specific way. The second is that because permits have * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be * generally recommended is: * * ```solidity * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public { * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {} * doThing(..., value); * } * * function doThing(..., uint256 value) public { * token.safeTransferFrom(msg.sender, address(this), value); * ... * } * ``` * * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also * {SafeERC20-safeTransferFrom}). * * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so * contracts should have entry points that don't rely on permit. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. * * CAUTION: See Security Considerations above. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 amount) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; import "../extensions/IERC20Permit.sol"; import "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; /** * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } /** * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful. */ function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove(IERC20 token, address spender, uint256 value) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } /** * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 oldAllowance = token.allowance(address(this), spender); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value)); } /** * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value)); } } /** * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval * to be set to zero before setting it to a non-zero value, such as USDT. */ function forceApprove(IERC20 token, address spender, uint256 value) internal { bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value); if (!_callOptionalReturnBool(token, approvalCall)) { _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0)); _callOptionalReturn(token, approvalCall); } } /** * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`. * Revert on invalid signature. */ function safePermit( IERC20Permit token, address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) internal { uint256 nonceBefore = token.nonces(owner); token.permit(owner, spender, value, deadline, v, r, s); uint256 nonceAfter = token.nonces(owner); require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). * * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead. */ function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false // and not revert is the subcall reverts. (bool success, bytes memory returndata) = address(token).call(data); return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.23; import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; /** * @dev Interface for ERC20 tokens */ interface IERC20 is IERC20Metadata { function burn(address, uint256) external; function mint(address, uint256) external; function hasRole(bytes32, address) external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.23; /** * @dev Interface for GNSStaking contract */ interface IGNSStaking { struct Staker { uint128 stakedGns; // 1e18 uint128 debtDai; // 1e18 } struct StakerInfo { uint48 lastDepositTs; uint208 __placeholder; } struct RewardState { uint128 accRewardPerGns; // 1e18 uint128 precisionDelta; } struct RewardInfo { uint128 debtToken; // 1e18 uint128 __placeholder; } struct UnlockSchedule { uint128 totalGns; // 1e18 uint128 claimedGns; // 1e18 uint128 debtDai; // 1e18 uint48 start; // block.timestamp (seconds) uint48 duration; // in seconds bool revocable; UnlockType unlockType; uint16 __placeholder; } struct UnlockScheduleInput { uint128 totalGns; // 1e18 uint48 start; // block.timestamp (seconds) uint48 duration; // in seconds bool revocable; UnlockType unlockType; } enum UnlockType { LINEAR, CLIFF } function owner() external view returns (address); function distributeReward(address _rewardToken, uint256 _amountToken) external; function createUnlockSchedule(UnlockScheduleInput calldata _schedule, address _staker) external; event UnlockManagerUpdated(address indexed manager, bool authorized); event DaiHarvested(address indexed staker, uint128 amountDai); event RewardHarvested(address indexed staker, address indexed token, uint128 amountToken); event RewardHarvestedFromUnlock( address indexed staker, address indexed token, bool isOldDai, uint256[] ids, uint128 amountToken ); event RewardDistributed(address indexed token, uint256 amount); event GnsStaked(address indexed staker, uint128 amountGns); event GnsUnstaked(address indexed staker, uint128 amountGns); event GnsClaimed(address indexed staker, uint256[] ids, uint128 amountGns); event UnlockScheduled(address indexed staker, uint256 indexed index, UnlockSchedule schedule); event UnlockScheduleRevoked(address indexed staker, uint256 indexed index); event RewardTokenAdded(address token, uint256 index, uint128 precisionDelta); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.23; import "../interfaces/IERC20.sol"; /** * @dev Collaterals decimal precision internal library */ library CollateralUtils { struct CollateralConfig { uint128 precision; uint128 precisionDelta; } /** * @dev Calculates `precision` (10^decimals) and `precisionDelta` (precision difference * between 18 decimals and `token` decimals) of a given IERC20 `token` * * Notice: not compatible with tokens with more than 18 decimals * * @param _token collateral token address */ function getCollateralConfig(address _token) internal view returns (CollateralConfig memory _meta) { uint256 _decimals = uint256(IERC20(_token).decimals()); _meta.precision = uint128(10 ** _decimals); _meta.precisionDelta = uint128(10 ** (18 - _decimals)); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.23; /** * * @dev Abstract contract that handles delegating governance votes of an asset when possible. * Compatible with any token that extends OpenZeppelin ERC20Votes/ERC20VotesUpgradeable or implements `delegate(address)` */ abstract contract VotingDelegator { event Delegated(address indexed asset, address indexed delegatee, bool success); /** * @dev Calls `delegate(address)` on `_asset`. Does not revert if function is not supported by `_asset`. * * Emits {Delegated} with `_asset`, `_delegatee` and `success` flag */ function _tryDelegate(address _asset, address _delegatee) internal { (bool success, ) = _asset.call(abi.encodeWithSignature("delegate(address)", _delegatee)); emit Delegated(_asset, _delegatee, success); } }
{ "optimizer": { "enabled": true, "runs": 800 }, "evmVersion": "paris", "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"staker","type":"address"},{"indexed":false,"internalType":"uint128","name":"amountDai","type":"uint128"}],"name":"DaiHarvested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":true,"internalType":"address","name":"delegatee","type":"address"},{"indexed":false,"internalType":"bool","name":"success","type":"bool"}],"name":"Delegated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"staker","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"indexed":false,"internalType":"uint128","name":"amountGns","type":"uint128"}],"name":"GnsClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"staker","type":"address"},{"indexed":false,"internalType":"uint128","name":"amountGns","type":"uint128"}],"name":"GnsStaked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"staker","type":"address"},{"indexed":false,"internalType":"uint128","name":"amountGns","type":"uint128"}],"name":"GnsUnstaked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RewardDistributed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"staker","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint128","name":"amountToken","type":"uint128"}],"name":"RewardHarvested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"staker","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"bool","name":"isOldDai","type":"bool"},{"indexed":false,"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"indexed":false,"internalType":"uint128","name":"amountToken","type":"uint128"}],"name":"RewardHarvestedFromUnlock","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"index","type":"uint256"},{"indexed":false,"internalType":"uint128","name":"precisionDelta","type":"uint128"}],"name":"RewardTokenAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"manager","type":"address"},{"indexed":false,"internalType":"bool","name":"authorized","type":"bool"}],"name":"UnlockManagerUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"staker","type":"address"},{"indexed":true,"internalType":"uint256","name":"index","type":"uint256"}],"name":"UnlockScheduleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"staker","type":"address"},{"indexed":true,"internalType":"uint256","name":"index","type":"uint256"},{"components":[{"internalType":"uint128","name":"totalGns","type":"uint128"},{"internalType":"uint128","name":"claimedGns","type":"uint128"},{"internalType":"uint128","name":"debtDai","type":"uint128"},{"internalType":"uint48","name":"start","type":"uint48"},{"internalType":"uint48","name":"duration","type":"uint48"},{"internalType":"bool","name":"revocable","type":"bool"},{"internalType":"enum IGNSStaking.UnlockType","name":"unlockType","type":"uint8"},{"internalType":"uint16","name":"__placeholder","type":"uint16"}],"indexed":false,"internalType":"struct IGNSStaking.UnlockSchedule","name":"schedule","type":"tuple"}],"name":"UnlockScheduled","type":"event"},{"inputs":[],"name":"accDaiPerToken","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"addRewardToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_ids","type":"uint256[]"}],"name":"claimUnlockedGns","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_ids","type":"uint256[]"}],"name":"compoundGnsRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint128","name":"totalGns","type":"uint128"},{"internalType":"uint48","name":"start","type":"uint48"},{"internalType":"uint48","name":"duration","type":"uint48"},{"internalType":"bool","name":"revocable","type":"bool"},{"internalType":"enum IGNSStaking.UnlockType","name":"unlockType","type":"uint8"}],"internalType":"struct IGNSStaking.UnlockScheduleInput","name":"_schedule","type":"tuple"},{"internalType":"address","name":"_staker","type":"address"}],"name":"createUnlockSchedule","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"dai","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amountToken","type":"uint256"}],"name":"distributeReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getRewardTokens","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_staker","type":"address"},{"internalType":"uint256","name":"_index","type":"uint256"}],"name":"getUnlockSchedules","outputs":[{"components":[{"internalType":"uint128","name":"totalGns","type":"uint128"},{"internalType":"uint128","name":"claimedGns","type":"uint128"},{"internalType":"uint128","name":"debtDai","type":"uint128"},{"internalType":"uint48","name":"start","type":"uint48"},{"internalType":"uint48","name":"duration","type":"uint48"},{"internalType":"bool","name":"revocable","type":"bool"},{"internalType":"enum IGNSStaking.UnlockType","name":"unlockType","type":"uint8"},{"internalType":"uint16","name":"__placeholder","type":"uint16"}],"internalType":"struct IGNSStaking.UnlockSchedule","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_staker","type":"address"}],"name":"getUnlockSchedules","outputs":[{"components":[{"internalType":"uint128","name":"totalGns","type":"uint128"},{"internalType":"uint128","name":"claimedGns","type":"uint128"},{"internalType":"uint128","name":"debtDai","type":"uint128"},{"internalType":"uint48","name":"start","type":"uint48"},{"internalType":"uint48","name":"duration","type":"uint48"},{"internalType":"bool","name":"revocable","type":"bool"},{"internalType":"enum IGNSStaking.UnlockType","name":"unlockType","type":"uint8"},{"internalType":"uint16","name":"__placeholder","type":"uint16"}],"internalType":"struct IGNSStaking.UnlockSchedule[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"gns","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"gnsBalance","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_ids","type":"uint256[]"}],"name":"harvestAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"harvestDai","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_ids","type":"uint256[]"}],"name":"harvestDaiAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_ids","type":"uint256[]"}],"name":"harvestDaiFromUnlock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"harvestToken","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256[]","name":"_ids","type":"uint256[]"}],"name":"harvestTokenAll","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256[]","name":"_ids","type":"uint256[]"}],"name":"harvestTokenFromUnlock","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"harvestTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_ids","type":"uint256[]"}],"name":"harvestTokensAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_ids","type":"uint256[]"}],"name":"harvestTokensFromUnlock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"contract IERC20","name":"_gns","type":"address"},{"internalType":"contract IERC20","name":"_dai","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"initializeV2","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"isRewardToken","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_staker","type":"address"}],"name":"pendingRewardDai","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_staker","type":"address"},{"internalType":"uint256[]","name":"_ids","type":"uint256[]"}],"name":"pendingRewardDaiFromUnlocks","outputs":[{"internalType":"uint128","name":"pending","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_staker","type":"address"},{"internalType":"address","name":"_token","type":"address"}],"name":"pendingRewardToken","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_staker","type":"address"}],"name":"pendingRewardTokens","outputs":[{"internalType":"uint128[]","name":"pendingTokens","type":"uint128[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_staker","type":"address"},{"internalType":"uint256[]","name":"_ids","type":"uint256[]"}],"name":"pendingRewardTokensFromUnlocks","outputs":[{"internalType":"uint128[]","name":"pendingTokens","type":"uint128[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint128","name":"totalGns","type":"uint128"},{"internalType":"uint128","name":"claimedGns","type":"uint128"},{"internalType":"uint128","name":"debtDai","type":"uint128"},{"internalType":"uint48","name":"start","type":"uint48"},{"internalType":"uint48","name":"duration","type":"uint48"},{"internalType":"bool","name":"revocable","type":"bool"},{"internalType":"enum IGNSStaking.UnlockType","name":"unlockType","type":"uint8"},{"internalType":"uint16","name":"__placeholder","type":"uint16"}],"internalType":"struct IGNSStaking.UnlockSchedule","name":"_schedule","type":"tuple"},{"internalType":"uint48","name":"_timestamp","type":"uint48"}],"name":"releasableGns","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_staker","type":"address"},{"internalType":"uint256","name":"_id","type":"uint256"}],"name":"revokeUnlockSchedule","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"rewardTokenState","outputs":[{"internalType":"uint128","name":"accRewardPerGns","type":"uint128"},{"internalType":"uint128","name":"precisionDelta","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"rewardTokens","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_delegatee","type":"address"}],"name":"setDelegatee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_manager","type":"address"},{"internalType":"bool","name":"_authorized","type":"bool"}],"name":"setUnlockManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint128","name":"_amountGns","type":"uint128"}],"name":"stakeGns","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"stakerInfos","outputs":[{"internalType":"uint48","name":"lastDepositTs","type":"uint48"},{"internalType":"uint208","name":"__placeholder","type":"uint208"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"stakers","outputs":[{"internalType":"uint128","name":"stakedGns","type":"uint128"},{"internalType":"uint128","name":"debtDai","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_staker","type":"address"}],"name":"totalGnsStaked","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"unlockManagers","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint128","name":"totalGns","type":"uint128"},{"internalType":"uint128","name":"claimedGns","type":"uint128"},{"internalType":"uint128","name":"debtDai","type":"uint128"},{"internalType":"uint48","name":"start","type":"uint48"},{"internalType":"uint48","name":"duration","type":"uint48"},{"internalType":"bool","name":"revocable","type":"bool"},{"internalType":"enum IGNSStaking.UnlockType","name":"unlockType","type":"uint8"},{"internalType":"uint16","name":"__placeholder","type":"uint16"}],"internalType":"struct IGNSStaking.UnlockSchedule","name":"_schedule","type":"tuple"},{"internalType":"uint48","name":"_timestamp","type":"uint48"}],"name":"unlockedGns","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint128","name":"_amountGns","type":"uint128"}],"name":"unstakeGns","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"userTokenRewards","outputs":[{"internalType":"uint128","name":"debtToken","type":"uint128"},{"internalType":"uint128","name":"__placeholder","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"userTokenUnlockRewards","outputs":[{"internalType":"uint128","name":"debtToken","type":"uint128"},{"internalType":"uint128","name":"__placeholder","type":"uint128"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
60806040523480156200001157600080fd5b506200001c62000022565b620000e3565b600054610100900460ff16156200008f5760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff90811614620000e1576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b6144c280620000f36000396000f3fe608060405234801561001057600080fd5b50600436106103365760003560e01c806379ba5097116101b2578063c4f59f9b116100f9578063e4c924aa116100a2578063f2fde38b1161007c578063f2fde38b1461084a578063f4b9fa751461085d578063f8b74d5a14610870578063fc7d01481461088357600080fd5b8063e4c924aa146107d5578063e860930a146107e8578063f2a1bba41461080b57600080fd5b8063dacf00f8116100d3578063dacf00f81461079e578063dad5d0be146107b1578063e30c3978146107c457600080fd5b8063c4f59f9b14610763578063ce1c77df14610778578063d784f1881461078b57600080fd5b806396c95c1a1161015b578063b5fd73f811610135578063b5fd73f8146106c0578063c0c53b8b1461070b578063c17713711461071e57600080fd5b806396c95c1a1461067a578063aeaf58131461069a578063b2e1dbc9146106ad57600080fd5b8063850e27111161018c578063850e27111461061e5780638da5cb5b1461063e5780639168ae721461064657600080fd5b806379ba5097146105d85780637bb7bed1146105e0578063810232921461060b57600080fd5b806337f2225e116102815780636023eb7f1161022a578063715018a611610204578063715018a614610521578063777bdadc1461052957806377c6b1671461053c57806378ce3d89146105c557600080fd5b80636023eb7f146104e157806368787b51146104f45780636f60bc981461050e57600080fd5b8063514e1a541161025b578063514e1a54146104be5780635cd8a76b146104d15780635f371739146104d957600080fd5b806337f2225e14610485578063439cffaf146104985780634689e8d2146104ab57600080fd5b80632aabff15116102e357806331a12529116102bd57806331a125291461040b57806332939f7d1461045f5780633620151b1461047257600080fd5b80632aabff15146103d25780632abbe3ea146103e55780632f527ac1146103f857600080fd5b80631c03e6cc116103145780631c03e6cc146103a25780631ec8bb8c146103b75780632a981b5b146103ca57600080fd5b80630408f96d1461033b57806308e22f6c146103645780630bb18dc11461038f575b600080fd5b61034e610349366004613a5a565b610896565b60405161035b9190613b3b565b60405180910390f35b610377610372366004613c1c565b6109d2565b6040516001600160801b03909116815260200161035b565b61037761039d366004613ce8565b6109f4565b6103b56103b0366004613ce8565b610a84565b005b6103b56103c5366004613a5a565b610a98565b6103b5610c54565b6103b56103e0366004613d51565b610cbb565b6103b56103f3366004613d93565b610cd3565b610377610406366004613c1c565b610e6d565b61043f610419366004613ce8565b609e602052600090815260409020546001600160801b0380821691600160801b90041682565b604080516001600160801b0393841681529290911660208301520161035b565b6103b561046d366004613d51565b610f29565b609954610377906001600160801b031681565b610377610493366004613ce8565b610f3b565b6103776104a6366004613dae565b610f88565b6103b56104b9366004613e03565b610fb0565b6103b56104cc366004613d51565b611017565b6103b5611029565b6103b561111b565b6103b56104ef366004613e3c565b6111dc565b60995461037790600160801b90046001600160801b031681565b6103b561051c366004613ee2565b6111e7565b6103b56112a2565b6103b5610537366004613d51565b6112b6565b61058c61054a366004613ce8565b60a16020526000908152604090205465ffffffffffff8116906601000000000000900479ffffffffffffffffffffffffffffffffffffffffffffffffffff1682565b6040805165ffffffffffff909316835279ffffffffffffffffffffffffffffffffffffffffffffffffffff90911660208301520161035b565b6103b56105d3366004613f10565b61134e565b6103b5611971565b6105f36105ee366004613f44565b6119fc565b6040516001600160a01b03909116815260200161035b565b610377610619366004613dae565b611a26565b61063161062c366004613ce8565b611b64565b60405161035b9190613f5d565b6105f3611c24565b61043f610654366004613ce8565b609a602052600090815260409020546001600160801b0380821691600160801b90041682565b61068d610688366004613ce8565b611c3d565b60405161035b9190613faa565b6103776106a8366004613ee2565b611d60565b6103b56106bb366004613d51565b611e04565b6106fb6106ce366004613ce8565b6001600160a01b03166000908152609e6020526040902054600160801b90046001600160801b0316151590565b604051901515815260200161035b565b6103b5610719366004613fed565b611e41565b61043f61072c366004614038565b60a06020908152600093845260408085208252928452828420905282529020546001600160801b0380821691600160801b90041682565b61076b612006565b60405161035b9190614079565b610377610786366004613dae565b612068565b6103b5610799366004613d93565b612116565b6103776107ac366004613ce8565b612302565b6103b56107bf366004613d51565b61248b565b6065546001600160a01b03166105f3565b6106316107e3366004613dae565b6124a6565b6106fb6107f6366004613ce8565b609c6020526000908152604090205460ff1681565b61043f610819366004613ee2565b609f6020908152600092835260408084209091529082529020546001600160801b0380821691600160801b90041682565b6103b5610858366004613ce8565b6126ee565b6098546105f3906001600160a01b031681565b6097546105f3906001600160a01b031681565b6103b5610891366004613a5a565b612754565b604080516101008101825260008082526020808301829052828401829052606083018290526080830182905260a0830182905260c0830182905260e083018290526001600160a01b0386168252609b9052919091208054839081106108fd576108fd6140ba565b60009182526020918290206040805161010081018252600290930290910180546001600160801b038082168552600160801b918290048116958501959095526001808301549586169385019390935265ffffffffffff90850481166060850152600160b01b850416608084015260ff600160e01b85048116151560a08501529293909260c0850192600160e81b909204169081111561099e5761099e613a86565b60018111156109af576109af613a86565b815260019190910154600160f01b900461ffff1660209091015290505b92915050565b600082602001516109e38484610e6d565b6109ed91906140e6565b9392505050565b6001600160a01b0381166000908152609e60205260408120548290600160801b90046001600160801b0316610a605760405162461bcd60e51b815260206004820152600d60248201526c24a72b20a624a22faa27a5a2a760991b60448201526064015b60405180910390fd5b336000908152609a60205260409020546109ed9084906001600160801b03166129c4565b610a8c612acc565b610a9581612b2b565b50565b6001600160a01b0382166000908152609e60205260409020548290600160801b90046001600160801b0316610aff5760405162461bcd60e51b815260206004820152600d60248201526c24a72b20a624a22faa27a5a2a760991b6044820152606401610a57565b609954600160801b90046001600160801b0316610b5e5760405162461bcd60e51b815260206004820152600d60248201527f4e4f5f474e535f5354414b4544000000000000000000000000000000000000006044820152606401610a57565b610b736001600160a01b038416333085612ced565b6001600160a01b0383166000908152609e6020526040902060995481546001600160801b03600160801b92839004811692610bb09204168561410d565b610bc290670de0b6b3a764000061410d565b610bcc919061413a565b81548290600090610be79084906001600160801b031661414e565b92506101000a8154816001600160801b0302191690836001600160801b03160217905550836001600160a01b03167fe34918ff1c7084970068b53fd71ad6d8b04e9f15d3886cbf006443e6cdc52ea684604051610c4691815260200190565b60405180910390a250505050565b336000908152609a6020526040812054609d546001600160801b03909116915b81811015610cb657610cad609d8281548110610c9257610c926140ba565b6000918252602090912001546001600160a01b0316846129c4565b50600101610c74565b505050565b610cc58282611017565b610ccf8282610f29565b5050565b6000816001600160801b031611610d1a5760405162461bcd60e51b815260206004820152600b60248201526a414d4f554e545f5a45524f60a81b6044820152606401610a57565b609754610d3b906001600160a01b031633306001600160801b038516612ced565b610d4361111b565b610d4b610c54565b336000908152609a602052604081208054909190610d739084906001600160801b031661414e565b82546001600160801b0319166001600160801b03828116919091178455609954919250610da291839116612d85565b82546001600160801b03918216600160801b029116178255610dc43382612da6565b82609960108282829054906101000a90046001600160801b0316610de8919061414e565b82546101009290920a6001600160801b0381810219909316918316021790915533600081815260a16020908152604091829020805465ffffffffffff19164265ffffffffffff16179055905192871683529092507f69b9aace4ec5d9b020dc8f26b1af9e31665e291e86de8db7bf2e03dd76a151ea91015b60405180910390a2505050565b600082608001518360600151610e83919061416e565b65ffffffffffff168265ffffffffffff1610610ea1575081516109cc565b826060015165ffffffffffff168265ffffffffffff161080610ed8575060018360c001516001811115610ed657610ed6613a86565b145b15610ee5575060006109cc565b826080015165ffffffffffff16836060015183610f02919061418d565b8451610f1f9165ffffffffffff16906001600160801b031661410d565b6109ed919061413a565b610f3161111b565b610ccf8282611e04565b6001600160a01b0381166000908152609a602090815260408083208151808301909252546001600160801b03808216808452600160801b9092041692820183905290916109ed9190612e53565b6000610f95848484612068565b610f9e856109f4565b610fa8919061414e565b949350505050565b610fb8612acc565b6001600160a01b0382166000818152609c6020908152604091829020805460ff191685151590811790915591519182527f37d059510662ed4f7c846b2b307b12cae9efc251486cb247fba0b9d7021e5b3f910160405180910390a25050565b61101f610c54565b610ccf82826112b6565b600054600290610100900460ff1615801561104b575060005460ff8083169116105b6110ae5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610a57565b6000805461ffff191660ff8316176101001790556098546110d7906001600160a01b0316612b2b565b6000805461ff001916905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150565b336000908152609a602052604081208054609954919291611148916001600160801b039081169116612d85565b825490915060009061116b908390600160801b90046001600160801b0316612e73565b83546001600160801b03908116600160801b858316021785556098549192506111a1916001600160a01b03169033908416612e81565b6040516001600160801b038216815233907ff5c4762b09bad9ee274417cb38a318d436e5840ab30be2c2900f8f0e69b317fc90602001610e60565b610a95338242612eb1565b6001600160a01b0382166000908152609e60205260409020548290600160801b90046001600160801b031661124e5760405162461bcd60e51b815260206004820152600d60248201526c24a72b20a624a22faa27a5a2a760991b6044820152606401610a57565b611256612acc565b6001600160a01b0382166112985760405162461bcd60e51b81526020600482015260096024820152680414444524553535f360bc1b6044820152606401610a57565b610cb683836131d9565b6112aa612acc565b6112b460006132da565b565b610ccf33609d80548060200260200160405190810160405280929190818152602001828054801561131057602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116112f2575b50505050508484808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152506132f392505050565b8061135f60808401606085016141ac565b6001600160a01b03821633148015611375575080155b806113985750611383611c24565b6001600160a01b0316336001600160a01b0316145b806113b25750336000908152609c602052604090205460ff165b6113fe5760405162461bcd60e51b815260206004820152600760248201527f4e4f5f41555448000000000000000000000000000000000000000000000000006044820152606401610a57565b4261140d6303c267008261416e565b65ffffffffffff1661142560408701602088016141c9565b65ffffffffffff161061147a5760405162461bcd60e51b815260206004820152601160248201527f544f4f5f4641525f494e5f4655545552450000000000000000000000000000006044820152606401610a57565b606461148c60608701604088016141c9565b65ffffffffffff16101580156114bd57506303c267006114b260608701604088016141c9565b65ffffffffffff1611155b6115095760405162461bcd60e51b815260206004820152601260248201527f494e434f52524543545f4455524154494f4e00000000000000000000000000006044820152606401610a57565b670de0b6b3a764000061151f6020870187613d93565b6001600160801b031610156115765760405162461bcd60e51b815260206004820152601060248201527f494e434f52524543545f414d4f554e54000000000000000000000000000000006044820152606401610a57565b6001600160a01b0384166115b85760405162461bcd60e51b81526020600482015260096024820152680414444524553535f360bc1b6044820152606401610a57565b60006115c76020870187613d93565b6097549091506115eb906001600160a01b031633306001600160801b038516612ced565b60408051610100810182526001600160801b038084168252600060208301819052609954909383019161162091869116612d85565b6001600160801b031681526020018465ffffffffffff1689602001602081019061164a91906141c9565b65ffffffffffff16101561165e578461166e565b61166e60408a0160208b016141c9565b65ffffffffffff16815260200161168b60608a0160408b016141c9565b65ffffffffffff1681526020016116a860808a0160608b016141ac565b151581526020016116bf60a08a0160808b016141e4565b60018111156116d0576116d0613a86565b8152600060209182018190526001600160a01b0389168152609b82526040808220805460018181018355918452928490208551948601516001600160801b03908116600160801b9081029682169690961760029095029091019384559185015183820180546060880151608089015160a08a01511515600160e01b027fffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffff65ffffffffffff928316600160b01b02167fffffff00000000000000ffffffffffffffffffffffffffffffffffffffffffff929093169099027fffffffffffffffffffff0000000000000000000000000000000000000000000090931694909616939093171793909316179390931780825560c0850151949550859492937fffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90911690600160e81b90849081111561182757611827613a86565b021790555060e082015181600101601e6101000a81548161ffff021916908361ffff160217905550505081609960108282829054906101000a90046001600160801b0316611875919061414e565b82546001600160801b039182166101009390930a9283029190920219909116179055506001600160a01b0386166000908152609b60205260408120546118bd906001906141ff565b905061192587609d80548060200260200160405190810160405280929190818152602001828054801561191957602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116118fb575b5050505050838661332c565b80876001600160a01b03167fd858b6b4541385008baaa764f65f7ca9b7e0cdcf25fa214b9c3b1c8de97f3faa8460405161195f9190613b3b565b60405180910390a35050505050505050565b60655433906001600160a01b031681146119f35760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f74207468652060448201527f6e6577206f776e657200000000000000000000000000000000000000000000006064820152608401610a57565b610a95816132da565b609d8181548110611a0c57600080fd5b6000918252602090912001546001600160a01b0316905081565b6000805b82811015611b5c576001600160a01b0385166000908152609b60205260409020611b4890858584818110611a6057611a606140ba565b9050602002013581548110611a7757611a776140ba565b60009182526020918290206040805161010081018252600290930290910180546001600160801b038082168552600160801b918290048116958501959095526001808301549586169385019390935265ffffffffffff90850481166060850152600160b01b850416608084015260ff600160e01b85048116151560a08501529293909260c0850192600160e81b9092041690811115611b1857611b18613a86565b6001811115611b2957611b29613a86565b815260019190910154600160f01b900461ffff166020909101526133e6565b611b52908361414e565b9150600101611a2a565b509392505050565b609d546060908067ffffffffffffffff811115611b8357611b83613b4a565b604051908082528060200260200182016040528015611bac578160200160208202803683370190505b50915060005b81811015611c1d57611beb84609d8381548110611bd157611bd16140ba565b6000918252602090912001546001600160a01b0316611d60565b838281518110611bfd57611bfd6140ba565b6001600160801b0390921660209283029190910190910152600101611bb2565b5050919050565b6000611c386033546001600160a01b031690565b905090565b6001600160a01b0381166000908152609b60209081526040808320805482518185028101850190935280835260609492939192909184015b82821015611d5557600084815260209081902060408051610100810182526002860290920180546001600160801b038082168552600160801b918290048116958501959095526001808301549586169385019390935265ffffffffffff90850481166060850152600160b01b850416608084015260ff600160e01b85048116151560a08501529293909260c0850192600160e81b9092041690811115611d1d57611d1d613a86565b6001811115611d2e57611d2e613a86565b8152600191820154600160f01b900461ffff16602091820152918352929092019101611c75565b505050509050919050565b6001600160a01b0381166000908152609e6020526040812054600160801b90046001600160801b0316611d95575060006109cc565b6001600160a01b038084166000908152609a6020908152604080832054609f8352818420948716845293825280832054609e8352928190208151808301909252546001600160801b038181168352600160801b9091048116928201929092526109ed938216929091169061341b565b610ccf3383838080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061343992505050565b600054610100900460ff1615808015611e615750600054600160ff909116105b80611e7b5750303b158015611e7b575060005460ff166001145b611ede5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610a57565b6000805460ff191660011790558015611f01576000805461ff0019166101001790555b6001600160a01b03841615801590611f2157506001600160a01b03831615155b8015611f3557506001600160a01b03821615155b611f815760405162461bcd60e51b815260206004820152600c60248201527f57524f4e475f504152414d5300000000000000000000000000000000000000006044820152606401610a57565b611f8a846132da565b609780546001600160a01b038086166001600160a01b03199283161790925560988054928516929091169190911790558015612000576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b6060609d80548060200260200160405190810160405280929190818152602001828054801561205e57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311612040575b5050505050905090565b6001600160a01b0383166000908152609e60205260408120548490600160801b90046001600160801b03166120cf5760405162461bcd60e51b815260206004820152600d60248201526c24a72b20a624a22faa27a5a2a760991b6044820152606401610a57565b61210d338686868080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061345392505050565b95945050505050565b33600090815260a1602052604090205461213a9060649065ffffffffffff1661416e565b65ffffffffffff164265ffffffffffff16116121985760405162461bcd60e51b815260206004820152600b60248201527f494e5f434f4f4c444f574e0000000000000000000000000000000000000000006044820152606401610a57565b6000816001600160801b0316116121df5760405162461bcd60e51b815260206004820152600b60248201526a414d4f554e545f5a45524f60a81b6044820152606401610a57565b6121e761111b565b6121ef610c54565b336000908152609a6020526040812080549091906122179084906001600160801b03166140e6565b82546001600160801b0319166001600160801b0382811691909117845560995491925061224691839116612d85565b82546001600160801b03918216600160801b0291161782556122683382612da6565b82609960108282829054906101000a90046001600160801b031661228c91906140e6565b82546101009290920a6001600160801b038181021990931691831602179091556097546122c792506001600160a01b03169033908616612e81565b6040516001600160801b038416815233907f8e8e48230f251ae906ddcb489028403d8c74fba7bd69b48ef909509dbeca58f190602001610e60565b6001600160a01b0381166000908152609a6020908152604080832054609b835281842080548351818602810186019094528084526001600160801b039092169385939290849084015b8282101561242b57600084815260209081902060408051610100810182526002860290920180546001600160801b038082168552600160801b918290048116958501959095526001808301549586169385019390935265ffffffffffff90850481166060850152600160b01b850416608084015260ff600160e01b85048116151560a08501529293909260c0850192600160e81b90920416908111156123f3576123f3613a86565b600181111561240457612404613a86565b8152600191820154600160f01b900461ffff1660209182015291835292909201910161234b565b50505050905060005b8151811015612482576000828281518110612451576124516140ba565b6020026020010151905061246d81600001518260200151613462565b612477908561414e565b935050600101612434565b50909392505050565b609754610ccf906103f3906001600160a01b03168484610f88565b60606000609d80548060200260200160405190810160405280929190818152602001828054801561250057602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116124e2575b50505050509050805167ffffffffffffffff81111561252157612521613b4a565b60405190808252806020026020018201604052801561254a578160200160208202803683370190505b50915060005b838110156126e5576001600160a01b0386166000908152609b60205260408120868684818110612582576125826140ba565b9050602002013581548110612599576125996140ba565b60009182526020822060029091020180549092506125ca906001600160801b0380821691600160801b900416613462565b905060005b84518110156126d75760008582815181106125ec576125ec6140ba565b6020908102919091018101516001600160a01b03808d16600090815260a084526040808220928416825291909352822090925061269c918591908c8c8a818110612638576126386140ba565b602090810292909201358352508181019290925260409081016000908120546001600160a01b0387168252609e8452908290208251808401909352546001600160801b038181168452600160801b909104811693830193909352919091169061341b565b8783815181106126ae576126ae6140ba565b602002602001018181516126c2919061414e565b6001600160801b0316905250506001016125cf565b505050806001019050612550565b50509392505050565b6126f6612acc565b606580546001600160a01b0319166001600160a01b03831690811790915561271c611c24565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b61275c612acc565b6001600160a01b0382166000908152609b60205260408120805483908110612786576127866140ba565b9060005260206000209060020201905080600101601c9054906101000a900460ff166127f45760405162461bcd60e51b815260206004820152600d60248201527f4e4f545f5245564f4341424c45000000000000000000000000000000000000006044820152606401610a57565b60408051600180825281830190925260009160208083019080368337019050509050828160008151811061282a5761282a6140ba565b602002602001018181525050612841848242612eb1565b8154600090612863906001600160801b0380821691600160801b900416613462565b8354600160801b81046001600160801b03166001600160801b03199091161784556001840180547fffffffff00000000000000000000000000000000000000000000000000000000169055609d8054604080516020808402820181019092528281529394506129189389939092909183018282801561290b57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116128ed575b505050505086600061332c565b80609960108282829054906101000a90046001600160801b031661293c91906140e6565b92506101000a8154816001600160801b0302191690836001600160801b0316021790555061298761296b611c24565b6097546001600160a01b0316906001600160801b038416612e81565b60405184906001600160a01b038716907fec3458853f0bb76e34bb0ac49646241e29b9d541e9b111c74803383b1878f4db90600090a35050505050565b336000908152609f602090815260408083206001600160a01b03861684528252808320609e83528184208251808401909352546001600160801b03808216808552600160801b9092041693830193909352918390612a23908690612d85565b83546020840151919250612a429183916001600160801b03169061346e565b83546001600160801b0319166001600160801b03838116919091178555909450612a7a906001600160a01b0388169033908716612e81565b6040516001600160801b03851681526001600160a01b0387169033907f5b9fe24dad005f849fabd507136947dd5046b5b0c3eba33bb090ae1ca84aa6e39060200160405180910390a350505092915050565b33612ad5611c24565b6001600160a01b0316146112b45760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a57565b6001600160a01b038116612b815760405162461bcd60e51b815260206004820152600c60248201527f5a45524f5f4144445245535300000000000000000000000000000000000000006044820152606401610a57565b6001600160a01b0381166000908152609e6020526040902054600160801b90046001600160801b031615612bf75760405162461bcd60e51b815260206004820152600960248201527f4455504c494341544500000000000000000000000000000000000000000000006044820152606401610a57565b609d805460018101825560009182527fd26e832454299e9fabb89e0e5fffdc046d4e14431bc1bf607ffb2e8a1ddecf7b0180546001600160a01b0319166001600160a01b038416179055612c4a82613485565b6020908101516001600160a01b0384166000908152609e909252604090912080546001600160801b03808416600160801b029116179055609d549091507f4f570e8a8e9e89b002df3832af59fff510da91949ffd9e4b1a02e61dd5da3201908390612cb7906001906141ff565b604080516001600160a01b03909316835260208301919091526001600160801b0384169082015260600160405180910390a15050565b6040516001600160a01b03808516602483015283166044820152606481018290526120009085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152613542565b6000670de0b6b3a7640000610f1f6001600160801b0380851690861661410d565b609d5460005b81811015612000576000609d8281548110612dc957612dc96140ba565b60009182526020808320909101546001600160a01b0316808352609e909152604090912054909150612e059085906001600160801b0316612d85565b6001600160a01b038681166000908152609f602090815260408083209590931682529390935290912080546001600160801b0319166001600160801b03909216919091179055600101612dac565b6099546000906109ed90612e719085906001600160801b0316612d85565b835b60006109ed8383600161346e565b6040516001600160a01b038316602482015260448101829052610cb690849063a9059cbb60e01b90606401612d21565b600080609d805480602002602001604051908101604052809291908181526020018280548015612f0a57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311612eec575b50505050509050612f1b8585613439565b612f268582866132f3565b60005b845181101561312f576000858281518110612f4657612f466140ba565b602002602001015190506000609b6000896001600160a01b03166001600160a01b031681526020019081526020016000208281548110612f8857612f886140ba565b600091825260208083206040805161010081018252600290940290910180546001600160801b038082168652600160801b918290048116948601949094526001808301549485169386019390935265ffffffffffff90840481166060860152600160b01b840416608085015260ff600160e01b84048116151560a08601529095506130619392869260c0850192600160e81b9092049091169081111561303057613030613a86565b600181111561304157613041613a86565b815260019190910154600160f01b900461ffff16602090910152886109d2565b8254909150600090613084908390600160801b90046001600160801b031661414e565b83549091506001600160801b039081169082168110156130a6576130a6614212565b83546001600160801b03808416600160801b02911617845560006130ca8284613462565b6099549091506130e49082906001600160801b0316612d85565b6001860180546001600160801b0319166001600160801b03929092169190911790556131128c89888461332c565b61311c848a61414e565b9850866001019650505050505050612f29565b5081609960108282829054906101000a90046001600160801b031661315491906140e6565b82546101009290920a6001600160801b0381810219909316918316021790915560975461318f92506001600160a01b03169087908516612e81565b846001600160a01b03167f88b681940a5361aa8a87ba4cca9d420b08e7d6df1f6691d2621e2c803f1f585485846040516131ca929190614264565b60405180910390a25050505050565b6040516001600160a01b0382811660248301526000919084169060440160408051601f198184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166317066a5760e21b1790525161324091906142b3565b6000604051808303816000865af19150503d806000811461327d576040519150601f19603f3d011682016040523d82523d6000602084013e613282565b606091505b50509050816001600160a01b0316836001600160a01b03167fb1247c60c1f535e393496ecb92a45670b346b057bf9e382c99cb0dca11ee8abc836040516132cd911515815260200190565b60405180910390a3505050565b606580546001600160a01b0319169055610a958161362a565b60005b82518110156120005761332384848381518110613315576133156140ba565b602002602001015184613453565b506001016132f6565b60005b83518110156133df57600084828151811061334c5761334c6140ba565b6020908102919091018101516001600160a01b0381166000908152609e9092526040909120549091506133899084906001600160801b0316612d85565b6001600160a01b03878116600090815260a06020908152604080832095909316825293845281812087825290935290912080546001600160801b0319166001600160801b0390921691909117905560010161332f565b5050505050565b60006109cc61341161340084600001518560200151613462565b6099546001600160801b0316612d85565b8360400151612e73565b6000610fa861342e858460000151612d85565b84846020015161346e565b609854610cb69083906001600160a01b031683600161367c565b6000610fa8848484600061367c565b60006109ed82846140e6565b60008161347b84866140e6565b610fa891906142cf565b60408051808201909152600080825260208201526000826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156134d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134fd91906142f5565b60ff16905061350d81600a6143fc565b6001600160801b031682526135238160126141ff565b61352e90600a6143fc565b6001600160801b0316602083015250919050565b6000613597826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166139229092919063ffffffff16565b90508051600014806135b85750808060200190518101906135b89190614408565b610cb65760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610a57565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60006001600160a01b0385166136d45760405162461bcd60e51b815260206004820152600a60248201527f555345525f454d505459000000000000000000000000000000000000000000006044820152606401610a57565b82516000036136e557506000610fa8565b600080831561370057506099546001600160801b0316613746565b50506001600160a01b0384166000908152609e60209081526040918290208251808401909352546001600160801b03808216808552600160801b90920416929091018290525b60005b85518110156138ab576000868281518110613766576137666140ba565b602002602001015190506000609b60008b6001600160a01b03166001600160a01b0316815260200190815260200160002082815481106137a8576137a86140ba565b60009182526020822060029091020180549092506137e3906137dd906001600160801b0380821691600160801b900416613462565b86612d85565b905087156138325760018201546138049082906001600160801b0316612e73565b61380e908861414e565b6001830180546001600160801b0319166001600160801b038416179055965061389d565b6001600160a01b03808c16600090815260a060209081526040808320938e16835292815282822086835290522080546138769083906001600160801b03168961346e565b613880908961414e565b81546001600160801b0319166001600160801b0384161790915596505b836001019350505050613749565b506138c96001600160a01b038716886001600160801b038616612e81565b856001600160a01b0316876001600160a01b03167f7cb388073abaf9b2dca10d8718dcb227463afe5ef4eb02a81eb0066ae26860d586888760405161391093929190614425565b60405180910390a35050949350505050565b6060610fa8848460008585600080866001600160a01b0316858760405161394991906142b3565b60006040518083038185875af1925050503d8060008114613986576040519150601f19603f3d011682016040523d82523d6000602084013e61398b565b606091505b509150915061399c878383876139a7565b979650505050505050565b60608315613a16578251600003613a0f576001600160a01b0385163b613a0f5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610a57565b5081610fa8565b610fa88383815115613a2b5781518083602001fd5b8060405162461bcd60e51b8152600401610a579190614459565b6001600160a01b0381168114610a9557600080fd5b60008060408385031215613a6d57600080fd5b8235613a7881613a45565b946020939093013593505050565b634e487b7160e01b600052602160045260246000fd5b60028110613aba57634e487b7160e01b600052602160045260246000fd5b9052565b6001600160801b0380825116835280602083015116602084015280604083015116604084015250606081015165ffffffffffff8082166060850152806080840151166080850152505060a0810151151560a083015260c0810151613b2560c0840182613a9c565b5060e0810151610cb660e084018261ffff169052565b61010081016109cc8284613abe565b634e487b7160e01b600052604160045260246000fd5b604051610100810167ffffffffffffffff81118282101715613b8457613b84613b4a565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715613bb357613bb3613b4a565b604052919050565b80356001600160801b0381168114613bd257600080fd5b919050565b803565ffffffffffff81168114613bd257600080fd5b8015158114610a9557600080fd5b803560028110613bd257600080fd5b803561ffff81168114613bd257600080fd5b600080828403610120811215613c3157600080fd5b61010080821215613c4157600080fd5b613c49613b60565b9150613c5485613bbb565b8252613c6260208601613bbb565b6020830152613c7360408601613bbb565b6040830152613c8460608601613bd7565b6060830152613c9560808601613bd7565b608083015260a0850135613ca881613bed565b60a0830152613cb960c08601613bfb565b60c0830152613cca60e08601613c0a565b60e0830152819350613cdd818601613bd7565b925050509250929050565b600060208284031215613cfa57600080fd5b81356109ed81613a45565b60008083601f840112613d1757600080fd5b50813567ffffffffffffffff811115613d2f57600080fd5b6020830191508360208260051b8501011115613d4a57600080fd5b9250929050565b60008060208385031215613d6457600080fd5b823567ffffffffffffffff811115613d7b57600080fd5b613d8785828601613d05565b90969095509350505050565b600060208284031215613da557600080fd5b6109ed82613bbb565b600080600060408486031215613dc357600080fd5b8335613dce81613a45565b9250602084013567ffffffffffffffff811115613dea57600080fd5b613df686828701613d05565b9497909650939450505050565b60008060408385031215613e1657600080fd5b8235613e2181613a45565b91506020830135613e3181613bed565b809150509250929050565b60006020808385031215613e4f57600080fd5b823567ffffffffffffffff80821115613e6757600080fd5b818501915085601f830112613e7b57600080fd5b813581811115613e8d57613e8d613b4a565b8060051b9150613e9e848301613b8a565b8181529183018401918481019088841115613eb857600080fd5b938501935b83851015613ed657843582529385019390850190613ebd565b98975050505050505050565b60008060408385031215613ef557600080fd5b8235613f0081613a45565b91506020830135613e3181613a45565b60008082840360c0811215613f2457600080fd5b60a0811215613f3257600080fd5b5082915060a0830135613e3181613a45565b600060208284031215613f5657600080fd5b5035919050565b6020808252825182820181905260009190848201906040850190845b81811015613f9e5783516001600160801b031683529284019291840191600101613f79565b50909695505050505050565b6020808252825182820181905260009190848201906040850190845b81811015613f9e57613fd9838551613abe565b928401926101009290920191600101613fc6565b60008060006060848603121561400257600080fd5b833561400d81613a45565b9250602084013561401d81613a45565b9150604084013561402d81613a45565b809150509250925092565b60008060006060848603121561404d57600080fd5b833561405881613a45565b9250602084013561406881613a45565b929592945050506040919091013590565b6020808252825182820181905260009190848201906040850190845b81811015613f9e5783516001600160a01b031683529284019291840191600101614095565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b6001600160801b03828116828216039080821115614106576141066140d0565b5092915050565b80820281158282048414176109cc576109cc6140d0565b634e487b7160e01b600052601260045260246000fd5b60008261414957614149614124565b500490565b6001600160801b03818116838216019080821115614106576141066140d0565b65ffffffffffff818116838216019080821115614106576141066140d0565b65ffffffffffff828116828216039080821115614106576141066140d0565b6000602082840312156141be57600080fd5b81356109ed81613bed565b6000602082840312156141db57600080fd5b6109ed82613bd7565b6000602082840312156141f657600080fd5b6109ed82613bfb565b818103818111156109cc576109cc6140d0565b634e487b7160e01b600052600160045260246000fd5b60008151808452602080850194506020840160005b838110156142595781518752958201959082019060010161423d565b509495945050505050565b6040815260006142776040830185614228565b90506001600160801b03831660208301529392505050565b60005b838110156142aa578181015183820152602001614292565b50506000910152565b600082516142c581846020870161428f565b9190910192915050565b60006001600160801b03808416806142e9576142e9614124565b92169190910492915050565b60006020828403121561430757600080fd5b815160ff811681146109ed57600080fd5b600181815b80851115614353578160001904821115614339576143396140d0565b8085161561434657918102915b93841c939080029061431d565b509250929050565b60008261436a575060016109cc565b81614377575060006109cc565b816001811461438d5760028114614397576143b3565b60019150506109cc565b60ff8411156143a8576143a86140d0565b50506001821b6109cc565b5060208310610133831016604e8410600b84101617156143d6575081810a6109cc565b6143e08383614318565b80600019048211156143f4576143f46140d0565b029392505050565b60006109ed838361435b565b60006020828403121561441a57600080fd5b81516109ed81613bed565b83151581526060602082015260006144406060830185614228565b90506001600160801b0383166040830152949350505050565b602081526000825180602084015261447881604085016020870161428f565b601f01601f1916919091016040019291505056fea2646970667358221220de5cc1a183d5d407c85ae2d8e05542b603fdec82824cadb310a24c7bcfe9555664736f6c63430008170033
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106103365760003560e01c806379ba5097116101b2578063c4f59f9b116100f9578063e4c924aa116100a2578063f2fde38b1161007c578063f2fde38b1461084a578063f4b9fa751461085d578063f8b74d5a14610870578063fc7d01481461088357600080fd5b8063e4c924aa146107d5578063e860930a146107e8578063f2a1bba41461080b57600080fd5b8063dacf00f8116100d3578063dacf00f81461079e578063dad5d0be146107b1578063e30c3978146107c457600080fd5b8063c4f59f9b14610763578063ce1c77df14610778578063d784f1881461078b57600080fd5b806396c95c1a1161015b578063b5fd73f811610135578063b5fd73f8146106c0578063c0c53b8b1461070b578063c17713711461071e57600080fd5b806396c95c1a1461067a578063aeaf58131461069a578063b2e1dbc9146106ad57600080fd5b8063850e27111161018c578063850e27111461061e5780638da5cb5b1461063e5780639168ae721461064657600080fd5b806379ba5097146105d85780637bb7bed1146105e0578063810232921461060b57600080fd5b806337f2225e116102815780636023eb7f1161022a578063715018a611610204578063715018a614610521578063777bdadc1461052957806377c6b1671461053c57806378ce3d89146105c557600080fd5b80636023eb7f146104e157806368787b51146104f45780636f60bc981461050e57600080fd5b8063514e1a541161025b578063514e1a54146104be5780635cd8a76b146104d15780635f371739146104d957600080fd5b806337f2225e14610485578063439cffaf146104985780634689e8d2146104ab57600080fd5b80632aabff15116102e357806331a12529116102bd57806331a125291461040b57806332939f7d1461045f5780633620151b1461047257600080fd5b80632aabff15146103d25780632abbe3ea146103e55780632f527ac1146103f857600080fd5b80631c03e6cc116103145780631c03e6cc146103a25780631ec8bb8c146103b75780632a981b5b146103ca57600080fd5b80630408f96d1461033b57806308e22f6c146103645780630bb18dc11461038f575b600080fd5b61034e610349366004613a5a565b610896565b60405161035b9190613b3b565b60405180910390f35b610377610372366004613c1c565b6109d2565b6040516001600160801b03909116815260200161035b565b61037761039d366004613ce8565b6109f4565b6103b56103b0366004613ce8565b610a84565b005b6103b56103c5366004613a5a565b610a98565b6103b5610c54565b6103b56103e0366004613d51565b610cbb565b6103b56103f3366004613d93565b610cd3565b610377610406366004613c1c565b610e6d565b61043f610419366004613ce8565b609e602052600090815260409020546001600160801b0380821691600160801b90041682565b604080516001600160801b0393841681529290911660208301520161035b565b6103b561046d366004613d51565b610f29565b609954610377906001600160801b031681565b610377610493366004613ce8565b610f3b565b6103776104a6366004613dae565b610f88565b6103b56104b9366004613e03565b610fb0565b6103b56104cc366004613d51565b611017565b6103b5611029565b6103b561111b565b6103b56104ef366004613e3c565b6111dc565b60995461037790600160801b90046001600160801b031681565b6103b561051c366004613ee2565b6111e7565b6103b56112a2565b6103b5610537366004613d51565b6112b6565b61058c61054a366004613ce8565b60a16020526000908152604090205465ffffffffffff8116906601000000000000900479ffffffffffffffffffffffffffffffffffffffffffffffffffff1682565b6040805165ffffffffffff909316835279ffffffffffffffffffffffffffffffffffffffffffffffffffff90911660208301520161035b565b6103b56105d3366004613f10565b61134e565b6103b5611971565b6105f36105ee366004613f44565b6119fc565b6040516001600160a01b03909116815260200161035b565b610377610619366004613dae565b611a26565b61063161062c366004613ce8565b611b64565b60405161035b9190613f5d565b6105f3611c24565b61043f610654366004613ce8565b609a602052600090815260409020546001600160801b0380821691600160801b90041682565b61068d610688366004613ce8565b611c3d565b60405161035b9190613faa565b6103776106a8366004613ee2565b611d60565b6103b56106bb366004613d51565b611e04565b6106fb6106ce366004613ce8565b6001600160a01b03166000908152609e6020526040902054600160801b90046001600160801b0316151590565b604051901515815260200161035b565b6103b5610719366004613fed565b611e41565b61043f61072c366004614038565b60a06020908152600093845260408085208252928452828420905282529020546001600160801b0380821691600160801b90041682565b61076b612006565b60405161035b9190614079565b610377610786366004613dae565b612068565b6103b5610799366004613d93565b612116565b6103776107ac366004613ce8565b612302565b6103b56107bf366004613d51565b61248b565b6065546001600160a01b03166105f3565b6106316107e3366004613dae565b6124a6565b6106fb6107f6366004613ce8565b609c6020526000908152604090205460ff1681565b61043f610819366004613ee2565b609f6020908152600092835260408084209091529082529020546001600160801b0380821691600160801b90041682565b6103b5610858366004613ce8565b6126ee565b6098546105f3906001600160a01b031681565b6097546105f3906001600160a01b031681565b6103b5610891366004613a5a565b612754565b604080516101008101825260008082526020808301829052828401829052606083018290526080830182905260a0830182905260c0830182905260e083018290526001600160a01b0386168252609b9052919091208054839081106108fd576108fd6140ba565b60009182526020918290206040805161010081018252600290930290910180546001600160801b038082168552600160801b918290048116958501959095526001808301549586169385019390935265ffffffffffff90850481166060850152600160b01b850416608084015260ff600160e01b85048116151560a08501529293909260c0850192600160e81b909204169081111561099e5761099e613a86565b60018111156109af576109af613a86565b815260019190910154600160f01b900461ffff1660209091015290505b92915050565b600082602001516109e38484610e6d565b6109ed91906140e6565b9392505050565b6001600160a01b0381166000908152609e60205260408120548290600160801b90046001600160801b0316610a605760405162461bcd60e51b815260206004820152600d60248201526c24a72b20a624a22faa27a5a2a760991b60448201526064015b60405180910390fd5b336000908152609a60205260409020546109ed9084906001600160801b03166129c4565b610a8c612acc565b610a9581612b2b565b50565b6001600160a01b0382166000908152609e60205260409020548290600160801b90046001600160801b0316610aff5760405162461bcd60e51b815260206004820152600d60248201526c24a72b20a624a22faa27a5a2a760991b6044820152606401610a57565b609954600160801b90046001600160801b0316610b5e5760405162461bcd60e51b815260206004820152600d60248201527f4e4f5f474e535f5354414b4544000000000000000000000000000000000000006044820152606401610a57565b610b736001600160a01b038416333085612ced565b6001600160a01b0383166000908152609e6020526040902060995481546001600160801b03600160801b92839004811692610bb09204168561410d565b610bc290670de0b6b3a764000061410d565b610bcc919061413a565b81548290600090610be79084906001600160801b031661414e565b92506101000a8154816001600160801b0302191690836001600160801b03160217905550836001600160a01b03167fe34918ff1c7084970068b53fd71ad6d8b04e9f15d3886cbf006443e6cdc52ea684604051610c4691815260200190565b60405180910390a250505050565b336000908152609a6020526040812054609d546001600160801b03909116915b81811015610cb657610cad609d8281548110610c9257610c926140ba565b6000918252602090912001546001600160a01b0316846129c4565b50600101610c74565b505050565b610cc58282611017565b610ccf8282610f29565b5050565b6000816001600160801b031611610d1a5760405162461bcd60e51b815260206004820152600b60248201526a414d4f554e545f5a45524f60a81b6044820152606401610a57565b609754610d3b906001600160a01b031633306001600160801b038516612ced565b610d4361111b565b610d4b610c54565b336000908152609a602052604081208054909190610d739084906001600160801b031661414e565b82546001600160801b0319166001600160801b03828116919091178455609954919250610da291839116612d85565b82546001600160801b03918216600160801b029116178255610dc43382612da6565b82609960108282829054906101000a90046001600160801b0316610de8919061414e565b82546101009290920a6001600160801b0381810219909316918316021790915533600081815260a16020908152604091829020805465ffffffffffff19164265ffffffffffff16179055905192871683529092507f69b9aace4ec5d9b020dc8f26b1af9e31665e291e86de8db7bf2e03dd76a151ea91015b60405180910390a2505050565b600082608001518360600151610e83919061416e565b65ffffffffffff168265ffffffffffff1610610ea1575081516109cc565b826060015165ffffffffffff168265ffffffffffff161080610ed8575060018360c001516001811115610ed657610ed6613a86565b145b15610ee5575060006109cc565b826080015165ffffffffffff16836060015183610f02919061418d565b8451610f1f9165ffffffffffff16906001600160801b031661410d565b6109ed919061413a565b610f3161111b565b610ccf8282611e04565b6001600160a01b0381166000908152609a602090815260408083208151808301909252546001600160801b03808216808452600160801b9092041692820183905290916109ed9190612e53565b6000610f95848484612068565b610f9e856109f4565b610fa8919061414e565b949350505050565b610fb8612acc565b6001600160a01b0382166000818152609c6020908152604091829020805460ff191685151590811790915591519182527f37d059510662ed4f7c846b2b307b12cae9efc251486cb247fba0b9d7021e5b3f910160405180910390a25050565b61101f610c54565b610ccf82826112b6565b600054600290610100900460ff1615801561104b575060005460ff8083169116105b6110ae5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610a57565b6000805461ffff191660ff8316176101001790556098546110d7906001600160a01b0316612b2b565b6000805461ff001916905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150565b336000908152609a602052604081208054609954919291611148916001600160801b039081169116612d85565b825490915060009061116b908390600160801b90046001600160801b0316612e73565b83546001600160801b03908116600160801b858316021785556098549192506111a1916001600160a01b03169033908416612e81565b6040516001600160801b038216815233907ff5c4762b09bad9ee274417cb38a318d436e5840ab30be2c2900f8f0e69b317fc90602001610e60565b610a95338242612eb1565b6001600160a01b0382166000908152609e60205260409020548290600160801b90046001600160801b031661124e5760405162461bcd60e51b815260206004820152600d60248201526c24a72b20a624a22faa27a5a2a760991b6044820152606401610a57565b611256612acc565b6001600160a01b0382166112985760405162461bcd60e51b81526020600482015260096024820152680414444524553535f360bc1b6044820152606401610a57565b610cb683836131d9565b6112aa612acc565b6112b460006132da565b565b610ccf33609d80548060200260200160405190810160405280929190818152602001828054801561131057602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116112f2575b50505050508484808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152506132f392505050565b8061135f60808401606085016141ac565b6001600160a01b03821633148015611375575080155b806113985750611383611c24565b6001600160a01b0316336001600160a01b0316145b806113b25750336000908152609c602052604090205460ff165b6113fe5760405162461bcd60e51b815260206004820152600760248201527f4e4f5f41555448000000000000000000000000000000000000000000000000006044820152606401610a57565b4261140d6303c267008261416e565b65ffffffffffff1661142560408701602088016141c9565b65ffffffffffff161061147a5760405162461bcd60e51b815260206004820152601160248201527f544f4f5f4641525f494e5f4655545552450000000000000000000000000000006044820152606401610a57565b606461148c60608701604088016141c9565b65ffffffffffff16101580156114bd57506303c267006114b260608701604088016141c9565b65ffffffffffff1611155b6115095760405162461bcd60e51b815260206004820152601260248201527f494e434f52524543545f4455524154494f4e00000000000000000000000000006044820152606401610a57565b670de0b6b3a764000061151f6020870187613d93565b6001600160801b031610156115765760405162461bcd60e51b815260206004820152601060248201527f494e434f52524543545f414d4f554e54000000000000000000000000000000006044820152606401610a57565b6001600160a01b0384166115b85760405162461bcd60e51b81526020600482015260096024820152680414444524553535f360bc1b6044820152606401610a57565b60006115c76020870187613d93565b6097549091506115eb906001600160a01b031633306001600160801b038516612ced565b60408051610100810182526001600160801b038084168252600060208301819052609954909383019161162091869116612d85565b6001600160801b031681526020018465ffffffffffff1689602001602081019061164a91906141c9565b65ffffffffffff16101561165e578461166e565b61166e60408a0160208b016141c9565b65ffffffffffff16815260200161168b60608a0160408b016141c9565b65ffffffffffff1681526020016116a860808a0160608b016141ac565b151581526020016116bf60a08a0160808b016141e4565b60018111156116d0576116d0613a86565b8152600060209182018190526001600160a01b0389168152609b82526040808220805460018181018355918452928490208551948601516001600160801b03908116600160801b9081029682169690961760029095029091019384559185015183820180546060880151608089015160a08a01511515600160e01b027fffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffff65ffffffffffff928316600160b01b02167fffffff00000000000000ffffffffffffffffffffffffffffffffffffffffffff929093169099027fffffffffffffffffffff0000000000000000000000000000000000000000000090931694909616939093171793909316179390931780825560c0850151949550859492937fffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90911690600160e81b90849081111561182757611827613a86565b021790555060e082015181600101601e6101000a81548161ffff021916908361ffff160217905550505081609960108282829054906101000a90046001600160801b0316611875919061414e565b82546001600160801b039182166101009390930a9283029190920219909116179055506001600160a01b0386166000908152609b60205260408120546118bd906001906141ff565b905061192587609d80548060200260200160405190810160405280929190818152602001828054801561191957602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116118fb575b5050505050838661332c565b80876001600160a01b03167fd858b6b4541385008baaa764f65f7ca9b7e0cdcf25fa214b9c3b1c8de97f3faa8460405161195f9190613b3b565b60405180910390a35050505050505050565b60655433906001600160a01b031681146119f35760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f74207468652060448201527f6e6577206f776e657200000000000000000000000000000000000000000000006064820152608401610a57565b610a95816132da565b609d8181548110611a0c57600080fd5b6000918252602090912001546001600160a01b0316905081565b6000805b82811015611b5c576001600160a01b0385166000908152609b60205260409020611b4890858584818110611a6057611a606140ba565b9050602002013581548110611a7757611a776140ba565b60009182526020918290206040805161010081018252600290930290910180546001600160801b038082168552600160801b918290048116958501959095526001808301549586169385019390935265ffffffffffff90850481166060850152600160b01b850416608084015260ff600160e01b85048116151560a08501529293909260c0850192600160e81b9092041690811115611b1857611b18613a86565b6001811115611b2957611b29613a86565b815260019190910154600160f01b900461ffff166020909101526133e6565b611b52908361414e565b9150600101611a2a565b509392505050565b609d546060908067ffffffffffffffff811115611b8357611b83613b4a565b604051908082528060200260200182016040528015611bac578160200160208202803683370190505b50915060005b81811015611c1d57611beb84609d8381548110611bd157611bd16140ba565b6000918252602090912001546001600160a01b0316611d60565b838281518110611bfd57611bfd6140ba565b6001600160801b0390921660209283029190910190910152600101611bb2565b5050919050565b6000611c386033546001600160a01b031690565b905090565b6001600160a01b0381166000908152609b60209081526040808320805482518185028101850190935280835260609492939192909184015b82821015611d5557600084815260209081902060408051610100810182526002860290920180546001600160801b038082168552600160801b918290048116958501959095526001808301549586169385019390935265ffffffffffff90850481166060850152600160b01b850416608084015260ff600160e01b85048116151560a08501529293909260c0850192600160e81b9092041690811115611d1d57611d1d613a86565b6001811115611d2e57611d2e613a86565b8152600191820154600160f01b900461ffff16602091820152918352929092019101611c75565b505050509050919050565b6001600160a01b0381166000908152609e6020526040812054600160801b90046001600160801b0316611d95575060006109cc565b6001600160a01b038084166000908152609a6020908152604080832054609f8352818420948716845293825280832054609e8352928190208151808301909252546001600160801b038181168352600160801b9091048116928201929092526109ed938216929091169061341b565b610ccf3383838080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061343992505050565b600054610100900460ff1615808015611e615750600054600160ff909116105b80611e7b5750303b158015611e7b575060005460ff166001145b611ede5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610a57565b6000805460ff191660011790558015611f01576000805461ff0019166101001790555b6001600160a01b03841615801590611f2157506001600160a01b03831615155b8015611f3557506001600160a01b03821615155b611f815760405162461bcd60e51b815260206004820152600c60248201527f57524f4e475f504152414d5300000000000000000000000000000000000000006044820152606401610a57565b611f8a846132da565b609780546001600160a01b038086166001600160a01b03199283161790925560988054928516929091169190911790558015612000576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b6060609d80548060200260200160405190810160405280929190818152602001828054801561205e57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311612040575b5050505050905090565b6001600160a01b0383166000908152609e60205260408120548490600160801b90046001600160801b03166120cf5760405162461bcd60e51b815260206004820152600d60248201526c24a72b20a624a22faa27a5a2a760991b6044820152606401610a57565b61210d338686868080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061345392505050565b95945050505050565b33600090815260a1602052604090205461213a9060649065ffffffffffff1661416e565b65ffffffffffff164265ffffffffffff16116121985760405162461bcd60e51b815260206004820152600b60248201527f494e5f434f4f4c444f574e0000000000000000000000000000000000000000006044820152606401610a57565b6000816001600160801b0316116121df5760405162461bcd60e51b815260206004820152600b60248201526a414d4f554e545f5a45524f60a81b6044820152606401610a57565b6121e761111b565b6121ef610c54565b336000908152609a6020526040812080549091906122179084906001600160801b03166140e6565b82546001600160801b0319166001600160801b0382811691909117845560995491925061224691839116612d85565b82546001600160801b03918216600160801b0291161782556122683382612da6565b82609960108282829054906101000a90046001600160801b031661228c91906140e6565b82546101009290920a6001600160801b038181021990931691831602179091556097546122c792506001600160a01b03169033908616612e81565b6040516001600160801b038416815233907f8e8e48230f251ae906ddcb489028403d8c74fba7bd69b48ef909509dbeca58f190602001610e60565b6001600160a01b0381166000908152609a6020908152604080832054609b835281842080548351818602810186019094528084526001600160801b039092169385939290849084015b8282101561242b57600084815260209081902060408051610100810182526002860290920180546001600160801b038082168552600160801b918290048116958501959095526001808301549586169385019390935265ffffffffffff90850481166060850152600160b01b850416608084015260ff600160e01b85048116151560a08501529293909260c0850192600160e81b90920416908111156123f3576123f3613a86565b600181111561240457612404613a86565b8152600191820154600160f01b900461ffff1660209182015291835292909201910161234b565b50505050905060005b8151811015612482576000828281518110612451576124516140ba565b6020026020010151905061246d81600001518260200151613462565b612477908561414e565b935050600101612434565b50909392505050565b609754610ccf906103f3906001600160a01b03168484610f88565b60606000609d80548060200260200160405190810160405280929190818152602001828054801561250057602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116124e2575b50505050509050805167ffffffffffffffff81111561252157612521613b4a565b60405190808252806020026020018201604052801561254a578160200160208202803683370190505b50915060005b838110156126e5576001600160a01b0386166000908152609b60205260408120868684818110612582576125826140ba565b9050602002013581548110612599576125996140ba565b60009182526020822060029091020180549092506125ca906001600160801b0380821691600160801b900416613462565b905060005b84518110156126d75760008582815181106125ec576125ec6140ba565b6020908102919091018101516001600160a01b03808d16600090815260a084526040808220928416825291909352822090925061269c918591908c8c8a818110612638576126386140ba565b602090810292909201358352508181019290925260409081016000908120546001600160a01b0387168252609e8452908290208251808401909352546001600160801b038181168452600160801b909104811693830193909352919091169061341b565b8783815181106126ae576126ae6140ba565b602002602001018181516126c2919061414e565b6001600160801b0316905250506001016125cf565b505050806001019050612550565b50509392505050565b6126f6612acc565b606580546001600160a01b0319166001600160a01b03831690811790915561271c611c24565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b61275c612acc565b6001600160a01b0382166000908152609b60205260408120805483908110612786576127866140ba565b9060005260206000209060020201905080600101601c9054906101000a900460ff166127f45760405162461bcd60e51b815260206004820152600d60248201527f4e4f545f5245564f4341424c45000000000000000000000000000000000000006044820152606401610a57565b60408051600180825281830190925260009160208083019080368337019050509050828160008151811061282a5761282a6140ba565b602002602001018181525050612841848242612eb1565b8154600090612863906001600160801b0380821691600160801b900416613462565b8354600160801b81046001600160801b03166001600160801b03199091161784556001840180547fffffffff00000000000000000000000000000000000000000000000000000000169055609d8054604080516020808402820181019092528281529394506129189389939092909183018282801561290b57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116128ed575b505050505086600061332c565b80609960108282829054906101000a90046001600160801b031661293c91906140e6565b92506101000a8154816001600160801b0302191690836001600160801b0316021790555061298761296b611c24565b6097546001600160a01b0316906001600160801b038416612e81565b60405184906001600160a01b038716907fec3458853f0bb76e34bb0ac49646241e29b9d541e9b111c74803383b1878f4db90600090a35050505050565b336000908152609f602090815260408083206001600160a01b03861684528252808320609e83528184208251808401909352546001600160801b03808216808552600160801b9092041693830193909352918390612a23908690612d85565b83546020840151919250612a429183916001600160801b03169061346e565b83546001600160801b0319166001600160801b03838116919091178555909450612a7a906001600160a01b0388169033908716612e81565b6040516001600160801b03851681526001600160a01b0387169033907f5b9fe24dad005f849fabd507136947dd5046b5b0c3eba33bb090ae1ca84aa6e39060200160405180910390a350505092915050565b33612ad5611c24565b6001600160a01b0316146112b45760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a57565b6001600160a01b038116612b815760405162461bcd60e51b815260206004820152600c60248201527f5a45524f5f4144445245535300000000000000000000000000000000000000006044820152606401610a57565b6001600160a01b0381166000908152609e6020526040902054600160801b90046001600160801b031615612bf75760405162461bcd60e51b815260206004820152600960248201527f4455504c494341544500000000000000000000000000000000000000000000006044820152606401610a57565b609d805460018101825560009182527fd26e832454299e9fabb89e0e5fffdc046d4e14431bc1bf607ffb2e8a1ddecf7b0180546001600160a01b0319166001600160a01b038416179055612c4a82613485565b6020908101516001600160a01b0384166000908152609e909252604090912080546001600160801b03808416600160801b029116179055609d549091507f4f570e8a8e9e89b002df3832af59fff510da91949ffd9e4b1a02e61dd5da3201908390612cb7906001906141ff565b604080516001600160a01b03909316835260208301919091526001600160801b0384169082015260600160405180910390a15050565b6040516001600160a01b03808516602483015283166044820152606481018290526120009085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152613542565b6000670de0b6b3a7640000610f1f6001600160801b0380851690861661410d565b609d5460005b81811015612000576000609d8281548110612dc957612dc96140ba565b60009182526020808320909101546001600160a01b0316808352609e909152604090912054909150612e059085906001600160801b0316612d85565b6001600160a01b038681166000908152609f602090815260408083209590931682529390935290912080546001600160801b0319166001600160801b03909216919091179055600101612dac565b6099546000906109ed90612e719085906001600160801b0316612d85565b835b60006109ed8383600161346e565b6040516001600160a01b038316602482015260448101829052610cb690849063a9059cbb60e01b90606401612d21565b600080609d805480602002602001604051908101604052809291908181526020018280548015612f0a57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311612eec575b50505050509050612f1b8585613439565b612f268582866132f3565b60005b845181101561312f576000858281518110612f4657612f466140ba565b602002602001015190506000609b6000896001600160a01b03166001600160a01b031681526020019081526020016000208281548110612f8857612f886140ba565b600091825260208083206040805161010081018252600290940290910180546001600160801b038082168652600160801b918290048116948601949094526001808301549485169386019390935265ffffffffffff90840481166060860152600160b01b840416608085015260ff600160e01b84048116151560a08601529095506130619392869260c0850192600160e81b9092049091169081111561303057613030613a86565b600181111561304157613041613a86565b815260019190910154600160f01b900461ffff16602090910152886109d2565b8254909150600090613084908390600160801b90046001600160801b031661414e565b83549091506001600160801b039081169082168110156130a6576130a6614212565b83546001600160801b03808416600160801b02911617845560006130ca8284613462565b6099549091506130e49082906001600160801b0316612d85565b6001860180546001600160801b0319166001600160801b03929092169190911790556131128c89888461332c565b61311c848a61414e565b9850866001019650505050505050612f29565b5081609960108282829054906101000a90046001600160801b031661315491906140e6565b82546101009290920a6001600160801b0381810219909316918316021790915560975461318f92506001600160a01b03169087908516612e81565b846001600160a01b03167f88b681940a5361aa8a87ba4cca9d420b08e7d6df1f6691d2621e2c803f1f585485846040516131ca929190614264565b60405180910390a25050505050565b6040516001600160a01b0382811660248301526000919084169060440160408051601f198184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166317066a5760e21b1790525161324091906142b3565b6000604051808303816000865af19150503d806000811461327d576040519150601f19603f3d011682016040523d82523d6000602084013e613282565b606091505b50509050816001600160a01b0316836001600160a01b03167fb1247c60c1f535e393496ecb92a45670b346b057bf9e382c99cb0dca11ee8abc836040516132cd911515815260200190565b60405180910390a3505050565b606580546001600160a01b0319169055610a958161362a565b60005b82518110156120005761332384848381518110613315576133156140ba565b602002602001015184613453565b506001016132f6565b60005b83518110156133df57600084828151811061334c5761334c6140ba565b6020908102919091018101516001600160a01b0381166000908152609e9092526040909120549091506133899084906001600160801b0316612d85565b6001600160a01b03878116600090815260a06020908152604080832095909316825293845281812087825290935290912080546001600160801b0319166001600160801b0390921691909117905560010161332f565b5050505050565b60006109cc61341161340084600001518560200151613462565b6099546001600160801b0316612d85565b8360400151612e73565b6000610fa861342e858460000151612d85565b84846020015161346e565b609854610cb69083906001600160a01b031683600161367c565b6000610fa8848484600061367c565b60006109ed82846140e6565b60008161347b84866140e6565b610fa891906142cf565b60408051808201909152600080825260208201526000826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156134d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134fd91906142f5565b60ff16905061350d81600a6143fc565b6001600160801b031682526135238160126141ff565b61352e90600a6143fc565b6001600160801b0316602083015250919050565b6000613597826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166139229092919063ffffffff16565b90508051600014806135b85750808060200190518101906135b89190614408565b610cb65760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610a57565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60006001600160a01b0385166136d45760405162461bcd60e51b815260206004820152600a60248201527f555345525f454d505459000000000000000000000000000000000000000000006044820152606401610a57565b82516000036136e557506000610fa8565b600080831561370057506099546001600160801b0316613746565b50506001600160a01b0384166000908152609e60209081526040918290208251808401909352546001600160801b03808216808552600160801b90920416929091018290525b60005b85518110156138ab576000868281518110613766576137666140ba565b602002602001015190506000609b60008b6001600160a01b03166001600160a01b0316815260200190815260200160002082815481106137a8576137a86140ba565b60009182526020822060029091020180549092506137e3906137dd906001600160801b0380821691600160801b900416613462565b86612d85565b905087156138325760018201546138049082906001600160801b0316612e73565b61380e908861414e565b6001830180546001600160801b0319166001600160801b038416179055965061389d565b6001600160a01b03808c16600090815260a060209081526040808320938e16835292815282822086835290522080546138769083906001600160801b03168961346e565b613880908961414e565b81546001600160801b0319166001600160801b0384161790915596505b836001019350505050613749565b506138c96001600160a01b038716886001600160801b038616612e81565b856001600160a01b0316876001600160a01b03167f7cb388073abaf9b2dca10d8718dcb227463afe5ef4eb02a81eb0066ae26860d586888760405161391093929190614425565b60405180910390a35050949350505050565b6060610fa8848460008585600080866001600160a01b0316858760405161394991906142b3565b60006040518083038185875af1925050503d8060008114613986576040519150601f19603f3d011682016040523d82523d6000602084013e61398b565b606091505b509150915061399c878383876139a7565b979650505050505050565b60608315613a16578251600003613a0f576001600160a01b0385163b613a0f5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610a57565b5081610fa8565b610fa88383815115613a2b5781518083602001fd5b8060405162461bcd60e51b8152600401610a579190614459565b6001600160a01b0381168114610a9557600080fd5b60008060408385031215613a6d57600080fd5b8235613a7881613a45565b946020939093013593505050565b634e487b7160e01b600052602160045260246000fd5b60028110613aba57634e487b7160e01b600052602160045260246000fd5b9052565b6001600160801b0380825116835280602083015116602084015280604083015116604084015250606081015165ffffffffffff8082166060850152806080840151166080850152505060a0810151151560a083015260c0810151613b2560c0840182613a9c565b5060e0810151610cb660e084018261ffff169052565b61010081016109cc8284613abe565b634e487b7160e01b600052604160045260246000fd5b604051610100810167ffffffffffffffff81118282101715613b8457613b84613b4a565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715613bb357613bb3613b4a565b604052919050565b80356001600160801b0381168114613bd257600080fd5b919050565b803565ffffffffffff81168114613bd257600080fd5b8015158114610a9557600080fd5b803560028110613bd257600080fd5b803561ffff81168114613bd257600080fd5b600080828403610120811215613c3157600080fd5b61010080821215613c4157600080fd5b613c49613b60565b9150613c5485613bbb565b8252613c6260208601613bbb565b6020830152613c7360408601613bbb565b6040830152613c8460608601613bd7565b6060830152613c9560808601613bd7565b608083015260a0850135613ca881613bed565b60a0830152613cb960c08601613bfb565b60c0830152613cca60e08601613c0a565b60e0830152819350613cdd818601613bd7565b925050509250929050565b600060208284031215613cfa57600080fd5b81356109ed81613a45565b60008083601f840112613d1757600080fd5b50813567ffffffffffffffff811115613d2f57600080fd5b6020830191508360208260051b8501011115613d4a57600080fd5b9250929050565b60008060208385031215613d6457600080fd5b823567ffffffffffffffff811115613d7b57600080fd5b613d8785828601613d05565b90969095509350505050565b600060208284031215613da557600080fd5b6109ed82613bbb565b600080600060408486031215613dc357600080fd5b8335613dce81613a45565b9250602084013567ffffffffffffffff811115613dea57600080fd5b613df686828701613d05565b9497909650939450505050565b60008060408385031215613e1657600080fd5b8235613e2181613a45565b91506020830135613e3181613bed565b809150509250929050565b60006020808385031215613e4f57600080fd5b823567ffffffffffffffff80821115613e6757600080fd5b818501915085601f830112613e7b57600080fd5b813581811115613e8d57613e8d613b4a565b8060051b9150613e9e848301613b8a565b8181529183018401918481019088841115613eb857600080fd5b938501935b83851015613ed657843582529385019390850190613ebd565b98975050505050505050565b60008060408385031215613ef557600080fd5b8235613f0081613a45565b91506020830135613e3181613a45565b60008082840360c0811215613f2457600080fd5b60a0811215613f3257600080fd5b5082915060a0830135613e3181613a45565b600060208284031215613f5657600080fd5b5035919050565b6020808252825182820181905260009190848201906040850190845b81811015613f9e5783516001600160801b031683529284019291840191600101613f79565b50909695505050505050565b6020808252825182820181905260009190848201906040850190845b81811015613f9e57613fd9838551613abe565b928401926101009290920191600101613fc6565b60008060006060848603121561400257600080fd5b833561400d81613a45565b9250602084013561401d81613a45565b9150604084013561402d81613a45565b809150509250925092565b60008060006060848603121561404d57600080fd5b833561405881613a45565b9250602084013561406881613a45565b929592945050506040919091013590565b6020808252825182820181905260009190848201906040850190845b81811015613f9e5783516001600160a01b031683529284019291840191600101614095565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b6001600160801b03828116828216039080821115614106576141066140d0565b5092915050565b80820281158282048414176109cc576109cc6140d0565b634e487b7160e01b600052601260045260246000fd5b60008261414957614149614124565b500490565b6001600160801b03818116838216019080821115614106576141066140d0565b65ffffffffffff818116838216019080821115614106576141066140d0565b65ffffffffffff828116828216039080821115614106576141066140d0565b6000602082840312156141be57600080fd5b81356109ed81613bed565b6000602082840312156141db57600080fd5b6109ed82613bd7565b6000602082840312156141f657600080fd5b6109ed82613bfb565b818103818111156109cc576109cc6140d0565b634e487b7160e01b600052600160045260246000fd5b60008151808452602080850194506020840160005b838110156142595781518752958201959082019060010161423d565b509495945050505050565b6040815260006142776040830185614228565b90506001600160801b03831660208301529392505050565b60005b838110156142aa578181015183820152602001614292565b50506000910152565b600082516142c581846020870161428f565b9190910192915050565b60006001600160801b03808416806142e9576142e9614124565b92169190910492915050565b60006020828403121561430757600080fd5b815160ff811681146109ed57600080fd5b600181815b80851115614353578160001904821115614339576143396140d0565b8085161561434657918102915b93841c939080029061431d565b509250929050565b60008261436a575060016109cc565b81614377575060006109cc565b816001811461438d5760028114614397576143b3565b60019150506109cc565b60ff8411156143a8576143a86140d0565b50506001821b6109cc565b5060208310610133831016604e8410600b84101617156143d6575081810a6109cc565b6143e08383614318565b80600019048211156143f4576143f46140d0565b029392505050565b60006109ed838361435b565b60006020828403121561441a57600080fd5b81516109ed81613bed565b83151581526060602082015260006144406060830185614228565b90506001600160801b0383166040830152949350505050565b602081526000825180602084015261447881604085016020870161428f565b601f01601f1916919091016040019291505056fea2646970667358221220de5cc1a183d5d407c85ae2d8e05542b603fdec82824cadb310a24c7bcfe9555664736f6c63430008170033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
[ 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.