Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
IdleCDO
Compiler Version
v0.8.10+commit.fc410830
Optimization Enabled:
Yes with 90 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.10;
import '@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol';
import "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol";
import "./interfaces/IIdleCDOStrategy.sol";
import "./interfaces/IERC20Detailed.sol";
import "./interfaces/IIdleCDOTrancheRewards.sol";
import "./interfaces/IStakedAave.sol";
import "./GuardedLaunchUpgradable.sol";
import "./IdleCDOTranche.sol";
import "./IdleCDOStorage.sol";
/// @title A perpetual tranche implementation
/// @author Idle Labs Inc.
/// @notice More info and high level overview in the README
/// @dev The contract is upgradable, to add storage slots, create IdleCDOStorageVX and inherit from IdleCDOStorage, then update the definitaion below
contract IdleCDO is PausableUpgradeable, GuardedLaunchUpgradable, IdleCDOStorage {
using SafeERC20Upgradeable for IERC20Detailed;
// ERROR MESSAGES:
// 0 = is 0
// 1 = already initialized
// 2 = Contract limit reached
// 3 = Tranche withdraw not allowed (Paused or in shutdown)
// 4 = Default, wait shutdown
// 5 = Amount too low
// 6 = Not authorized
// 7 = Amount too high
// 8 = Same block
// Used to prevent initialization of the implementation contract
/// @custom:oz-upgrades-unsafe-allow constructor
constructor() {
token = address(1);
}
// ###################
// Initializer
// ###################
/// @notice can only be called once
/// @dev Initialize the upgradable contract
/// @param _limit contract value limit, can be 0
/// @param _guardedToken underlying token
/// @param _governanceFund address where funds will be sent in case of emergency
/// @param _owner guardian address (can pause, unpause and call emergencyShutdown)
/// @param _rebalancer rebalancer address
/// @param _strategy strategy address
/// @param _trancheAPRSplitRatio trancheAPRSplitRatio value
/// @param _trancheIdealWeightRatio trancheIdealWeightRatio value
/// @param _incentiveTokens array of addresses for incentive tokens
function initialize(
uint256 _limit, address _guardedToken, address _governanceFund, address _owner, // GuardedLaunch args
address _rebalancer,
address _strategy,
uint256 _trancheAPRSplitRatio, // for AA tranches, so eg 10000 means 10% interest to AA and 90% BB
uint256 _trancheIdealWeightRatio, // for AA tranches, so eg 10000 means 10% of tranches are AA and 90% BB
address[] memory _incentiveTokens
) external initializer {
uint256 _idealRange = FULL_ALLOC / 10;
require(token == address(0), '1');
require(_rebalancer != address(0) && _strategy != address(0) && _guardedToken != address(0), "0");
require( _trancheAPRSplitRatio <= FULL_ALLOC, '7');
require(_trancheIdealWeightRatio <= (FULL_ALLOC - _idealRange), '7');
require(_trancheIdealWeightRatio >= _idealRange, '5');
// Initialize contracts
PausableUpgradeable.__Pausable_init();
// check for _governanceFund and _owner != address(0) are inside GuardedLaunchUpgradable
GuardedLaunchUpgradable.__GuardedLaunch_init(_limit, _governanceFund, _owner);
// Deploy Tranches tokens
address _strategyToken = IIdleCDOStrategy(_strategy).strategyToken();
// get strategy token symbol (eg. idleDAI)
string memory _symbol = IERC20Detailed(_strategyToken).symbol();
// create tranche tokens (concat strategy token symbol in the name and symbol of the tranche tokens)
AATranche = address(new IdleCDOTranche(_concat(string("IdleCDO AA Tranche - "), _symbol), _concat(string("AA_"), _symbol)));
BBTranche = address(new IdleCDOTranche(_concat(string("IdleCDO BB Tranche - "), _symbol), _concat(string("BB_"), _symbol)));
// Set CDO params
token = _guardedToken;
strategy = _strategy;
strategyToken = _strategyToken;
rebalancer = _rebalancer;
trancheAPRSplitRatio = _trancheAPRSplitRatio;
trancheIdealWeightRatio = _trancheIdealWeightRatio;
idealRange = _idealRange; // trancheIdealWeightRatio ± 10%
uint256 _oneToken = 10**(IERC20Detailed(_guardedToken).decimals());
oneToken = _oneToken;
uniswapRouterV2 = IUniswapV2Router02(0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D);
weth = address(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2);
incentiveTokens = _incentiveTokens;
priceAA = _oneToken;
priceBB = _oneToken;
unlentPerc = 2000; // 2%
// # blocks, after an harvest, during which harvested rewards gets progressively unlocked
releaseBlocksPeriod = 1500; // about 1/4 of a day
// Set flags
allowAAWithdraw = true;
allowBBWithdraw = true;
revertIfTooLow = true;
// skipDefaultCheck = false is the default value
// Set allowance for strategy
_allowUnlimitedSpend(_guardedToken, _strategy);
_allowUnlimitedSpend(strategyToken, _strategy);
// Save current strategy price
lastStrategyPrice = _strategyPrice();
// Fee params
fee = 10000; // 10% performance fee
feeReceiver = address(0xFb3bD022D5DAcF95eE28a6B07825D4Ff9C5b3814); // treasury multisig
guardian = _owner;
// feeSplit = 0; // default all to feeReceiver as default
// StkAAVE unwrapping is active
isStkAAVEActive = true;
}
// ###############
// Public methods
// ###############
/// @notice pausable
/// @dev msg.sender should approve this contract first to spend `_amount` of `token`
/// @param _amount amount of `token` to deposit
/// @return AA tranche tokens minted
function depositAA(uint256 _amount) external returns (uint256) {
return _deposit(_amount, AATranche);
}
/// @notice pausable in _deposit
/// @dev msg.sender should approve this contract first to spend `_amount` of `token`
/// @param _amount amount of `token` to deposit
/// @return BB tranche tokens minted
function depositBB(uint256 _amount) external returns (uint256) {
return _deposit(_amount, BBTranche);
}
/// @notice pausable in _deposit
/// @param _amount amount of AA tranche tokens to burn
/// @return underlying tokens redeemed
function withdrawAA(uint256 _amount) external returns (uint256) {
require(!paused() || allowAAWithdraw, '3');
return _withdraw(_amount, AATranche);
}
/// @notice pausable
/// @param _amount amount of BB tranche tokens to burn
/// @return underlying tokens redeemed
function withdrawBB(uint256 _amount) external returns (uint256) {
require(!paused() || allowBBWithdraw, '3');
return _withdraw(_amount, BBTranche);
}
// ###############
// Views
// ###############
/// @param _tranche tranche address
/// @return tranche price
function tranchePrice(address _tranche) external view returns (uint256) {
return _tranchePrice(_tranche);
}
/// @notice calculates the current total value locked (in `token` terms)
/// @dev unclaimed rewards (gov tokens) are not counted.
/// NOTE: `unclaimedFees` are not included in the contract value
/// NOTE2: fees that *will* be taken (in the next _updateAccounting call) are counted
function getContractValue() public override view returns (uint256) {
address _strategyToken = strategyToken;
uint256 strategyTokenDecimals = IERC20Detailed(_strategyToken).decimals();
// TVL is the sum of unlent balance in the contract + the balance in lending - the reduction for harvested rewards - unclaimedFees
// the balance in lending is the value of the interest bearing assets (strategyTokens) in this contract
// TVL = (strategyTokens * strategy token price) + unlent balance - lockedRewards - unclaimedFees
return (_contractTokenBalance(_strategyToken) * _strategyPrice() / (10**(strategyTokenDecimals))) +
_contractTokenBalance(token) -
_lockedRewards() -
unclaimedFees;
}
/// @param _tranche tranche address
/// @return apr at ideal ratio (trancheIdealWeightRatio) between AA and BB
function getIdealApr(address _tranche) external view returns (uint256) {
return _getApr(_tranche, trancheIdealWeightRatio);
}
/// @param _tranche tranche address
/// @return actual apr given current ratio between AA and BB tranches
function getApr(address _tranche) external view returns (uint256) {
return _getApr(_tranche, getCurrentAARatio());
}
/// @notice calculates the current AA tranches ratio
/// @dev _virtualBalance is used to have a more accurate/recent value for the AA ratio
/// because it calculates the balance after splitting the accrued interest since the
/// last depositXX/withdrawXX/harvest
/// @return AA tranches ratio (in underlying value) considering all interest
function getCurrentAARatio() public view returns (uint256) {
uint256 AABal = _virtualBalance(AATranche);
uint256 contractVal = AABal + _virtualBalance(BBTranche);
if (contractVal == 0) {
return 0;
}
// Current AA tranche split ratio = AABal * FULL_ALLOC / (AABal + BBBal)
return AABal * FULL_ALLOC / contractVal;
}
/// @notice calculates the current tranches price considering the interest that is yet to be splitted
/// ie the interest generated since the last update of priceAA and priceBB (done on depositXX/withdrawXX/harvest)
/// useful for showing updated gains on frontends
/// @dev this should always be >= of _tranchePrice(_tranche)
/// @param _tranche address of the requested tranche
/// @return _virtualPrice tranche price considering all interest
function virtualPrice(address _tranche) public view returns (uint256 _virtualPrice) {
// get both NAVs, because we need the total NAV anyway
uint256 _lastNAVAA = lastNAVAA;
uint256 _lastNAVBB = lastNAVBB;
(_virtualPrice, ) = _virtualPricesAux(
_tranche,
getContractValue(), // nav
_lastNAVAA + _lastNAVBB, // lastNAV
_tranche == AATranche ? _lastNAVAA : _lastNAVBB, // lastTrancheNAV
trancheAPRSplitRatio
);
}
/// @notice returns an array of tokens used to incentive tranches via IIdleCDOTrancheRewards
/// @return array with addresses of incentiveTokens (can be empty)
function getIncentiveTokens() external view returns (address[] memory) {
return incentiveTokens;
}
// ###############
// Internal
// ###############
/// @notice method used to deposit `token` and mint tranche tokens
/// Ideally users should deposit right after an `harvest` call to maximize profit
/// @dev this contract must be approved to spend at least _amount of `token` before calling this method
/// automatically reverts on lending provider default (_strategyPrice decreased)
/// @param _amount amount of underlyings (`token`) to deposit
/// @param _tranche tranche address
/// @return _minted number of tranche tokens minted
function _deposit(uint256 _amount, address _tranche) internal whenNotPaused returns (uint256 _minted) {
if (_amount == 0) {
return _minted;
}
// check that we are not depositing more than the contract available limit
_guarded(_amount);
// set _lastCallerBlock hash
_updateCallerBlock();
// check if _strategyPrice decreased
_checkDefault();
// interest accrued since last depositXX/withdrawXX/harvest is splitted between AA and BB
// according to trancheAPRSplitRatio. NAVs of AA and BB are updated and tranche
// prices adjusted accordingly
_updateAccounting();
// get underlyings from sender
IERC20Detailed(token).safeTransferFrom(msg.sender, address(this), _amount);
// mint tranche tokens according to the current tranche price
_minted = _mintShares(_amount, msg.sender, _tranche);
}
/// @notice this method is called on depositXX/withdrawXX/harvest and
/// updates the accounting of the contract and effectively splits the yield between the
/// AA and BB tranches
/// @dev this method:
/// - update tranche prices (priceAA and priceBB)
/// - update net asset value for both tranches (lastNAVAA and lastNAVBB)
/// - update fee accounting (unclaimedFees)
function _updateAccounting() internal {
uint256 _lastNAVAA = lastNAVAA;
uint256 _lastNAVBB = lastNAVBB;
uint256 _lastNAV = _lastNAVAA + _lastNAVBB;
uint256 nav = getContractValue();
uint256 _aprSplitRatio = trancheAPRSplitRatio;
// If gain is > 0, then collect some fees in `unclaimedFees`
if (nav > _lastNAV) {
unclaimedFees += (nav - _lastNAV) * fee / FULL_ALLOC;
}
(uint256 _priceAA, uint256 _totalAAGain) = _virtualPricesAux(AATranche, nav, _lastNAV, _lastNAVAA, _aprSplitRatio);
(uint256 _priceBB, uint256 _totalBBGain) = _virtualPricesAux(BBTranche, nav, _lastNAV, _lastNAVBB, _aprSplitRatio);
lastNAVAA += _totalAAGain;
lastNAVBB += _totalBBGain;
priceAA = _priceAA;
priceBB = _priceBB;
}
/// @notice calculates the NAV for a tranche considering the interest that is yet to be splitted
/// @param _tranche address of the requested tranche
/// @return net asset value, in underlying tokens, for _tranche considering all nav
function _virtualBalance(address _tranche) internal view returns (uint256) {
// balance is: tranche supply * virtual tranche price
return IdleCDOTranche(_tranche).totalSupply() * virtualPrice(_tranche) / ONE_TRANCHE_TOKEN;
}
/// @notice calculates the current tranches price considering the interest that is yet to be splitted and the
/// total gain for a specific tranche
/// @param _tranche address of the requested tranche
/// @param _nav current NAV
/// @param _lastNAV last saved NAV
/// @param _lastTrancheNAV last saved tranche NAV
/// @param _trancheAPRSplitRatio APR split ratio for AA tranche
/// @return _virtualPrice tranche price considering all interest
/// @return _totalTrancheGain tranche gain since last update
function _virtualPricesAux(
address _tranche,
uint256 _nav,
uint256 _lastNAV,
uint256 _lastTrancheNAV,
uint256 _trancheAPRSplitRatio
) internal view returns (uint256 _virtualPrice, uint256 _totalTrancheGain) {
// If there is no gain return the current price
if (_nav <= _lastNAV) {
return (_tranchePrice(_tranche), 0);
}
// Check if there are tranche holders
uint256 trancheSupply = IdleCDOTranche(_tranche).totalSupply();
if (_lastNAV == 0 || trancheSupply == 0) {
return (oneToken, 0);
}
// In order to correctly split the interest generated between AA and BB tranche holders
// (according to the trancheAPRSplitRatio) we need to know how much interest we gained
// since the last price update (during a depositXX/withdrawXX/harvest)
// To do that we need to get the current value of the assets in this contract
// and the last saved one (always during a depositXX/withdrawXX/harvest)
// Calculate the total gain
uint256 totalGain = _nav - _lastNAV;
// Remove performance fee
totalGain -= totalGain * fee / FULL_ALLOC;
address _AATranche = AATranche;
bool _isAATranche = _tranche == _AATranche;
// Get the supply of the other tranche and
// if it's 0 then give all gain to the current `_tranche` holders
if (IdleCDOTranche(_isAATranche ? BBTranche : _AATranche).totalSupply() == 0) {
_totalTrancheGain = totalGain;
} else {
// Split the net gain, with precision loss favoring the AA tranche.
uint256 totalBBGain = totalGain * (FULL_ALLOC - _trancheAPRSplitRatio) / FULL_ALLOC;
// The new NAV for the tranche is old NAV + total gain for the tranche
_totalTrancheGain = _isAATranche ? (totalGain - totalBBGain) : totalBBGain;
}
// Split the new NAV (_lastTrancheNAV + _totalTrancheGain) per tranche token
_virtualPrice = (_lastTrancheNAV + _totalTrancheGain) * ONE_TRANCHE_TOKEN / trancheSupply;
}
/// @notice mint tranche tokens and updates tranche last NAV
/// @param _amount, in underlyings, to convert in tranche tokens
/// @param _to receiver address of the newly minted tranche tokens
/// @param _tranche tranche address
/// @return _minted number of tranche tokens minted
function _mintShares(uint256 _amount, address _to, address _tranche) internal returns (uint256 _minted) {
// calculate # of tranche token to mint based on current tranche price: _amount / tranchePrice
_minted = _amount * ONE_TRANCHE_TOKEN / _tranchePrice(_tranche);
IdleCDOTranche(_tranche).mint(_to, _minted);
// update NAV with the _amount of underlyings added
if (_tranche == AATranche) {
lastNAVAA += _amount;
} else {
lastNAVBB += _amount;
}
}
/// @notice convert fees (`unclaimedFees`) in AA tranche tokens
/// Tranche tokens are then automatically staked in the relative IdleCDOTrancheRewards contact if present
/// @dev this will be called only during harvests
function _depositFees() internal {
uint256 _amount = unclaimedFees;
if (_amount > 0) {
address stakingRewards = AAStaking;
bool isStakingRewardsActive = stakingRewards != address(0);
address _feeReceiver = feeReceiver;
address _referral = referral;
uint256 _referralAmount;
if (_referral != address(0)) {
// If the contract has a referral, then we give the referral a share of the fees (in AA tranche tokens)
_referralAmount = _amount * feeSplit / FULL_ALLOC;
_mintShares(_referralAmount, _referral, AATranche);
}
// mint tranches tokens to this contract
uint256 _minted = _mintShares(_amount - _referralAmount,
isStakingRewardsActive ? address(this) : _feeReceiver,
// Mint AA tranche tokens as fees
AATranche
);
// reset unclaimedFees counter
unclaimedFees = 0;
// auto stake fees in staking contract for feeReceiver
if (isStakingRewardsActive) {
IIdleCDOTrancheRewards(stakingRewards).stakeFor(_feeReceiver, _minted);
}
}
}
/// @notice It allows users to burn their tranche token and redeem their principal + interest back
/// @dev automatically reverts on lending provider default (_strategyPrice decreased).
/// @param _amount in tranche tokens
/// @param _tranche tranche address
/// @return toRedeem number of underlyings redeemed
function _withdraw(uint256 _amount, address _tranche) internal nonReentrant returns (uint256 toRedeem) {
// check if a deposit is made in the same block from the same user
_checkSameTx();
// check if _strategyPrice decreased
_checkDefault();
// accrue interest to tranches and updates tranche prices
_updateAccounting();
// redeem all user balance if 0 is passed as _amount
if (_amount == 0) {
_amount = IERC20Detailed(_tranche).balanceOf(msg.sender);
}
require(_amount > 0, '0');
address _token = token;
// get current available unlent balance
uint256 balanceUnderlying = _contractTokenBalance(_token);
// Calculate the amount to redeem
toRedeem = _amount * _tranchePrice(_tranche) / ONE_TRANCHE_TOKEN;
if (toRedeem > balanceUnderlying) {
// if the unlent balance is not enough we try to redeem what's missing directly from the strategy
// and then add it to the current unlent balance
// NOTE: A difference of up to 100 wei due to rounding is tolerated
toRedeem = _liquidate(toRedeem - balanceUnderlying, revertIfTooLow) + balanceUnderlying;
}
// burn tranche token
IdleCDOTranche(_tranche).burn(msg.sender, _amount);
// send underlying to msg.sender
IERC20Detailed(_token).safeTransfer(msg.sender, toRedeem);
// update NAV with the _amount of underlyings removed
if (_tranche == AATranche) {
lastNAVAA -= toRedeem;
} else {
lastNAVBB -= toRedeem;
}
}
/// @dev check if _strategyPrice is decreased since last update and updates last saved strategy price
function _checkDefault() internal {
uint256 currPrice = _strategyPrice();
if (!skipDefaultCheck) {
require(lastStrategyPrice <= currPrice, "4");
}
lastStrategyPrice = currPrice;
}
/// @return strategy price, in underlyings
function _strategyPrice() internal view returns (uint256) {
return IIdleCDOStrategy(strategy).price();
}
/// @dev this should liquidate at least _amount of `token` from the lending provider or revertIfNeeded
/// @param _amount in underlying tokens
/// @param _revertIfNeeded flag whether to revert or not if the redeemed amount is not enough
/// @return _redeemedTokens number of underlyings redeemed
function _liquidate(uint256 _amount, bool _revertIfNeeded) internal returns (uint256 _redeemedTokens) {
_redeemedTokens = IIdleCDOStrategy(strategy).redeemUnderlying(_amount);
if (_revertIfNeeded) {
// keep 100 wei as margin for rounding errors
require(_redeemedTokens + 100 >= _amount, '5');
}
if (_redeemedTokens > _amount) {
_redeemedTokens = _amount;
}
}
/// @notice sends rewards to the tranche rewards staking contracts
/// @dev this method is called only during harvests
function _updateIncentives() internal {
// Read state variables only once to save gas
uint256 _trancheIdealWeightRatio = trancheIdealWeightRatio;
uint256 _trancheAPRSplitRatio = trancheAPRSplitRatio;
uint256 _idealRange = idealRange;
address _BBStaking = BBStaking;
address _AAStaking = AAStaking;
bool _isBBStakingActive = _BBStaking != address(0);
bool _isAAStakingActive = _AAStaking != address(0);
uint256 currAARatio;
if (_isBBStakingActive && _isAAStakingActive) {
currAARatio = getCurrentAARatio();
}
// Check if BB tranches should be rewarded (if AA ratio is too high)
if (_isBBStakingActive && (!_isAAStakingActive || (currAARatio > (_trancheIdealWeightRatio + _idealRange)))) {
// give more rewards to BB holders, ie send some rewards to BB Staking contract
return _depositIncentiveToken(_BBStaking, FULL_ALLOC);
}
// Check if AA tranches should be rewarded (id AA ratio is too low)
if (_isAAStakingActive && (!_isBBStakingActive || (currAARatio < (_trancheIdealWeightRatio - _idealRange)))) {
// give more rewards to AA holders, ie send some rewards to AA Staking contract
return _depositIncentiveToken(_AAStaking, FULL_ALLOC);
}
// Split rewards according to trancheAPRSplitRatio in case the ratio between
// AA and BB is already ideal
if (_isAAStakingActive) {
// NOTE: the order is important here, first there must be the deposit for AA rewards,
// if staking contract for AA is present
_depositIncentiveToken(_AAStaking, _trancheAPRSplitRatio);
}
if (_isBBStakingActive) {
// NOTE: here we should use FULL_ALLOC directly and not (FULL_ALLOC - _trancheAPRSplitRatio)
// because contract balance for incentive tokens is fetched at each _depositIncentiveToken
// and the balance for AA is already transferred
_depositIncentiveToken(_BBStaking, FULL_ALLOC);
}
}
/// @notice sends requested ratio of reward to a specific IdleCDOTrancheRewards contract
/// @param _stakingContract address which will receive incentive Rewards
/// @param _ratio ratio of the incentive token balance to send
function _depositIncentiveToken(address _stakingContract, uint256 _ratio) internal {
address[] memory _incentiveTokens = incentiveTokens;
for (uint256 i = 0; i < _incentiveTokens.length; i++) {
address _incentiveToken = _incentiveTokens[i];
// calculates the requested _ratio of the current contract balance of
// _incentiveToken to be sent to the IdleCDOTrancheRewards contract
uint256 _reward = _contractTokenBalance(_incentiveToken) * _ratio / FULL_ALLOC;
if (_reward > 0) {
// call depositReward to actually let the IdleCDOTrancheRewards get the reward
IIdleCDOTrancheRewards(_stakingContract).depositReward(_incentiveToken, _reward);
}
}
}
/// @notice method used to sell `_rewardToken` for `_token` on uniswap
/// @param _rewardToken address of the token to sell
/// @param _path uniswap path for the trade
/// @param _amount of `_rewardToken` to sell
/// @param _minAmount min amount of `_token` to buy
/// @return _amount of _rewardToken sold
/// @return _amount received for the sell
function _sellReward(address _rewardToken, address[] memory _path, uint256 _amount, uint256 _minAmount)
internal
returns (uint256, uint256) {
// If 0 is passed as sell amount, we get the whole contract balance
if (_amount == 0) {
_amount = _contractTokenBalance(_rewardToken);
}
if (_amount == 0) {
return (0, 0);
}
IUniswapV2Router02 _uniRouter = uniswapRouterV2;
// approve the uniswap router to spend our reward
IERC20Detailed(_rewardToken).safeIncreaseAllowance(address(_uniRouter), _amount);
// do the trade with all `_rewardToken` in this contract
uint256[] memory _amounts = _uniRouter.swapExactTokensForTokens(
_amount,
_minAmount,
_path,
address(this),
block.timestamp + 1
);
// return the amount swapped and the amount received
return (_amounts[0], _amounts[_amounts.length - 1]);
}
/// @notice method used to sell all sellable rewards for `_token` on uniswap
/// @param _strategy IIdleCDOStrategy stategy instance
/// @param _sellAmounts array with amounts of rewards to sell
/// @param _minAmount array with amounts of _token buy for each reward sold. (should have the same length as _sellAmounts)
/// @param _skipReward array of flags for skipping the market sell of specific rewards (should have the same length as _sellAmounts)
/// @return _soldAmounts array with amounts of rewards actually sold
/// @return _swappedAmounts array with amounts of _token actually bought
/// @return _totSold total rewards sold in `_token`
function _sellAllRewards(IIdleCDOStrategy _strategy, uint256[] memory _sellAmounts, uint256[] memory _minAmount, bool[] memory _skipReward)
internal
returns (uint256[] memory _soldAmounts, uint256[] memory _swappedAmounts, uint256 _totSold) {
// Fetch state variables once to save gas
address[] memory _incentiveTokens = incentiveTokens;
// get all rewards addresses
address[] memory _rewards = _strategy.getRewardTokens();
address _rewardToken;
// Prepare path for uniswap trade
address[] memory _path = new address[](3);
// _path[0] will be the reward token to sell
_path[1] = weth;
_path[2] = token;
// Initialize the return array, containing the amounts received after swapping reward tokens
_soldAmounts = new uint256[](_rewards.length);
_swappedAmounts = new uint256[](_rewards.length);
// loop through all reward tokens
for (uint256 i = 0; i < _rewards.length; i++) {
_rewardToken = _rewards[i];
// check if it should be sold or not
if (_skipReward[i] || _includesAddress(_incentiveTokens, _rewardToken)) { continue; }
// do not sell stkAAVE but only AAVE if present
if (_rewardToken == stkAave) {
_rewardToken = AAVE;
}
// set token to sell in the uniswap path
_path[0] = _rewardToken;
// Market sell _rewardToken in this contract for _token
(_soldAmounts[i], _swappedAmounts[i]) = _sellReward(_rewardToken, _path, _sellAmounts[i], _minAmount[i]);
_totSold += _swappedAmounts[i];
}
}
/// @param _tranche tranche address
/// @return last saved tranche price, in underlyings
function _tranchePrice(address _tranche) internal view returns (uint256) {
if (IdleCDOTranche(_tranche).totalSupply() == 0) {
return oneToken;
}
return _tranche == AATranche ? priceAA : priceBB;
}
/// @notice returns the current apr for a tranche based on trancheAPRSplitRatio and the provided AA ratio
/// @dev the apr for a tranche can be higher than the strategy apr
/// @param _tranche tranche token address
/// @param _AATrancheSplitRatio AA split ratio used for calculations
/// @return apr for the specific tranche
function _getApr(address _tranche, uint256 _AATrancheSplitRatio) internal view returns (uint256) {
uint256 stratApr = IIdleCDOStrategy(strategy).getApr();
uint256 _trancheAPRSplitRatio = trancheAPRSplitRatio;
bool isAATranche = _tranche == AATranche;
if (_AATrancheSplitRatio == 0) {
// if there are no AA tranches, apr for AA is 0 (all apr to BB and it will be equal to stratApr)
return isAATranche ? 0 : stratApr;
}
return isAATranche ?
// AA apr is: stratApr * AAaprSplitRatio / AASplitRatio
stratApr * _trancheAPRSplitRatio / _AATrancheSplitRatio :
// BB apr is: stratApr * BBaprSplitRatio / BBSplitRatio -> where
// BBaprSplitRatio is: (FULL_ALLOC - _trancheAPRSplitRatio) and
// BBSplitRatio is: (FULL_ALLOC - _AATrancheSplitRatio)
stratApr * (FULL_ALLOC - _trancheAPRSplitRatio) / (FULL_ALLOC - _AATrancheSplitRatio);
}
/// @return _locked amount of harvested rewards that are still not available to be redeemed
function _lockedRewards() internal view returns (uint256 _locked) {
uint256 _releaseBlocksPeriod = releaseBlocksPeriod;
uint256 _blocksSinceLastHarvest = block.number - latestHarvestBlock;
uint256 _harvestedRewards = harvestedRewards;
// NOTE: _harvestedRewards is never set to 0, but rather to 1 to save some gas
if (_harvestedRewards > 1 && _blocksSinceLastHarvest < _releaseBlocksPeriod) {
// progressively release harvested rewards
_locked = _harvestedRewards * (_releaseBlocksPeriod - _blocksSinceLastHarvest) / _releaseBlocksPeriod;
}
}
/// @notice used to start the cooldown for unstaking stkAAVE and claiming AAVE rewards (for the contract itself)
function _claimStkAave() internal {
if (!isStkAAVEActive) {
return;
}
IStakedAave _stkAave = IStakedAave(stkAave);
uint256 _stakersCooldown = _stkAave.stakersCooldowns(address(this));
// If there is a pending cooldown:
if (_stakersCooldown > 0) {
uint256 _cooldownEnd = _stakersCooldown + _stkAave.COOLDOWN_SECONDS();
// If it is over
if (_cooldownEnd < block.timestamp) {
// If the unstake window is active
if (block.timestamp - _cooldownEnd <= _stkAave.UNSTAKE_WINDOW()) {
// redeem stkAave AND begin new cooldown
_stkAave.redeem(address(this), type(uint256).max);
}
} else {
// If it is not over, do nothing
return;
}
}
// Pull new stkAAVE rewards
IIdleCDOStrategy(strategy).pullStkAAVE();
// If there's no pending cooldown or we just redeem the prev locked rewards,
// then begin a new cooldown
if (_stkAave.balanceOf(address(this)) > 0) {
// start a new cooldown
_stkAave.cooldown();
}
}
// ###################
// Protected
// ###################
/// @notice This method is used to lend user funds in the lending provider through the IIdleCDOStrategy and update tranches incentives.
/// The method:
/// - redeems rewards (if any) from the lending provider
/// - converts the rewards NOT present in the `incentiveTokens` array, in underlyings through uniswap v2
/// - calls _updateAccounting to update the accounting of the system with the new underlyings received
/// - it then convert fees in tranche tokens and stake tranche tokens in the IdleCDOTrancheRewards if any
/// - sends the correct amount of `incentiveTokens` to the each of the IdleCDOTrancheRewards contracts
/// - Finally it deposits the (initial unlent balance + the underlyings get from uniswap - fees) in the
/// lending provider through the IIdleCDOStrategy `deposit` call
/// The method will be called by an external, whitelisted, keeper bot which will call the method sistematically (eg once a day)
/// @dev can be called only by the rebalancer or the owner
/// @param _skipFlags array of flags, [0] = skip reward redemption, [1] = skip incentives update, [2] = skip fee deposit, [3] = skip all
/// @param _skipReward array of flags for skipping the market sell of specific rewards. Length should be equal to the `IIdleCDOStrategy(strategy).getRewardTokens()` array
/// @param _minAmount array of min amounts for uniswap trades. Lenght should be equal to the _skipReward array
/// @param _sellAmounts array of amounts (of reward tokens) to sell on uniswap. Lenght should be equal to the _minAmount array
/// if a sellAmount is 0 the whole contract balance for that token is swapped
/// @param _extraData bytes to be passed to the redeemRewards call
/// @return _res array of arrays with the following elements:
/// [0] _soldAmounts array with amounts of rewards actually sold
/// [1] _swappedAmounts array with amounts of _token actually bought
/// [2] _redeemedRewards array with amounts of rewards redeemed
function harvest(
// _skipFlags[0] _skipRedeem,
// _skipFlags[1] _skipIncentivesUpdate,
// _skipFlags[2] _skipFeeDeposit,
// _skipFlags[3] _skipRedeem && _skipIncentivesUpdate && _skipFeeDeposit,
bool[] calldata _skipFlags,
bool[] calldata _skipReward,
uint256[] calldata _minAmount,
uint256[] calldata _sellAmounts,
bytes calldata _extraData
) external
returns (uint256[][] memory _res) {
_checkOnlyOwnerOrRebalancer();
// initalize the returned array (elements will be [_soldAmounts, _swappedAmounts, _redeemedRewards])
_res = new uint256[][](3);
// Fetch state variable once to save gas
IIdleCDOStrategy _strategy = IIdleCDOStrategy(strategy);
// Check whether to redeem rewards from strategy or not
if (!_skipFlags[3]) {
uint256 _totSold;
if (!_skipFlags[0]) {
// Redeem all rewards associated with the strategy
_res[2] = _strategy.redeemRewards(_extraData);
// Redeem unlocked AAVE if any and start a new cooldown for stkAAVE
_claimStkAave();
// Sell rewards
(_res[0], _res[1], _totSold) = _sellAllRewards(_strategy, _sellAmounts, _minAmount, _skipReward);
}
// update last saved harvest block number
latestHarvestBlock = block.number;
// update harvested rewards value (avoid setting it to 0 to save some gas)
harvestedRewards = _totSold == 0 ? 1 : _totSold;
// split converted rewards if any and update tranche prices
// NOTE: harvested rewards won't be counted directly but released over time
_updateAccounting();
if (!_skipFlags[2]) {
// Get fees in the form of totalSupply diluition
_depositFees();
}
if (!_skipFlags[1]) {
// Update tranche incentives distribution and send rewards to staking contracts
_updateIncentives();
}
}
// Deposit the remaining balance in the lending provider and
// keep some unlent balance for cheap redeems and as reserve of last resort
uint256 underlyingBal = _contractTokenBalance(token);
uint256 idealUnlent = getContractValue() * unlentPerc / FULL_ALLOC;
if (underlyingBal > idealUnlent) {
// Put unlent balance at work in the lending provider
_strategy.deposit(underlyingBal - idealUnlent);
}
}
/// @notice method used to redeem underlyings from the lending provider
/// @dev can be called only by the rebalancer or the owner
/// @param _amount in underlyings to liquidate from lending provider
/// @param _revertIfNeeded flag to revert if amount liquidated is too low
/// @return liquidated amount in underlyings
function liquidate(uint256 _amount, bool _revertIfNeeded) external returns (uint256) {
_checkOnlyOwnerOrRebalancer();
return _liquidate(_amount, _revertIfNeeded);
}
// ###################
// onlyOwner
// ###################
/// @param _allowed flag to allow AA withdraws
function setAllowAAWithdraw(bool _allowed) external {
_checkOnlyOwner();
allowAAWithdraw = _allowed;
}
/// @param _allowed flag to allow BB withdraws
function setAllowBBWithdraw(bool _allowed) external {
_checkOnlyOwner();
allowBBWithdraw = _allowed;
}
/// @param _allowed flag to enable the 'default' check (whether _strategyPrice decreased or not)
function setSkipDefaultCheck(bool _allowed) external {
_checkOnlyOwner();
skipDefaultCheck = _allowed;
}
/// @param _allowed flag to enable the check if redeemed amount during liquidations is enough
function setRevertIfTooLow(bool _allowed) external {
_checkOnlyOwner();
revertIfTooLow = _allowed;
}
/// @notice updates the strategy used (potentially changing the lending protocol used)
/// @dev it's REQUIRED to liquidate / redeem everything from the lending provider before changing strategy
/// if the leding provider of the new strategy is different from the current one
/// it's also REQUIRED to transfer out any incentive tokens accrued if those are changed from the current ones
/// if the lending provider is changed
/// @param _strategy new strategy address
/// @param _incentiveTokens array of incentive tokens addresses
function setStrategy(address _strategy, address[] memory _incentiveTokens) external {
_checkOnlyOwner();
require(_strategy != address(0), '0');
IERC20Detailed _token = IERC20Detailed(token);
// revoke allowance for the current strategy
address _currStrategy = strategy;
_removeAllowance(address(_token), _currStrategy);
_removeAllowance(strategyToken, _currStrategy);
// Updated strategy variables
strategy = _strategy;
// Update incentive tokens
incentiveTokens = _incentiveTokens;
// Update strategyToken
address _newStrategyToken = IIdleCDOStrategy(_strategy).strategyToken();
strategyToken = _newStrategyToken;
// Approve underlyingToken
_allowUnlimitedSpend(address(_token), _strategy);
// Approve the new strategy to transfer strategyToken out from this contract
_allowUnlimitedSpend(_newStrategyToken, _strategy);
// Update last strategy price
lastStrategyPrice = _strategyPrice();
}
/// @param _rebalancer new rebalancer address
function setRebalancer(address _rebalancer) external {
_checkOnlyOwner();
require((rebalancer = _rebalancer) != address(0), '0');
}
/// @param _feeReceiver new fee receiver address
function setFeeReceiver(address _feeReceiver) external {
_checkOnlyOwner();
require((feeReceiver = _feeReceiver) != address(0), '0');
}
/// @notice set new referral address
/// @dev can be called only by the owner
/// @param _referral new referral address (can be address(0))
function setReferral(address _referral) external {
_checkOnlyOwner();
referral = _referral;
}
/// @param _guardian new guardian (pauser) address
function setGuardian(address _guardian) external {
_checkOnlyOwner();
require((guardian = _guardian) != address(0), '0');
}
/// @param _fee new fee
function setFee(uint256 _fee) external {
_checkOnlyOwner();
require((fee = _fee) <= MAX_FEE, '7');
}
/// @notice set fee split between feeReceiver and referral (if any). If referral is not set, fee goes to feeReceiver.
/// @dev can be called only by the owner
/// @param _feeSplit new fee split
function setFeeSplit(uint256 _feeSplit) external {
_checkOnlyOwner();
require((feeSplit = _feeSplit) <= FULL_ALLOC, '8');
}
/// @param _unlentPerc new unlent percentage
function setUnlentPerc(uint256 _unlentPerc) external {
_checkOnlyOwner();
require((unlentPerc = _unlentPerc) <= FULL_ALLOC, '7');
}
/// @param _releaseBlocksPeriod new # of blocks after an harvest during which
/// harvested rewards gets progressively redistriburted to users
function setReleaseBlocksPeriod(uint256 _releaseBlocksPeriod) external {
_checkOnlyOwner();
releaseBlocksPeriod = _releaseBlocksPeriod;
}
/// @param _isStkAAVEActive whether the contract receive stkAAVE or not
function setIsStkAAVEActive(bool _isStkAAVEActive) external {
_checkOnlyOwner();
isStkAAVEActive = _isStkAAVEActive;
}
/// @param _idealRange new ideal range
function setIdealRange(uint256 _idealRange) external {
_checkOnlyOwner();
require((idealRange = _idealRange) <= FULL_ALLOC, '7');
}
/// @param _trancheAPRSplitRatio new apr split ratio
function setTrancheAPRSplitRatio(uint256 _trancheAPRSplitRatio) external {
_checkOnlyOwner();
require((trancheAPRSplitRatio = _trancheAPRSplitRatio) <= FULL_ALLOC, '7');
}
/// @param _trancheIdealWeightRatio new ideal weight ratio (for incentives)
function setTrancheIdealWeightRatio(uint256 _trancheIdealWeightRatio) external {
_checkOnlyOwner();
require((_trancheIdealWeightRatio) >= idealRange, '5');
require((trancheIdealWeightRatio = _trancheIdealWeightRatio) <= (FULL_ALLOC - idealRange), '7');
}
/// @dev it's REQUIRED to transfer out any incentive tokens accrued before
/// @param _incentiveTokens array with new incentive tokens
function setIncentiveTokens(address[] memory _incentiveTokens) external {
_checkOnlyOwner();
incentiveTokens = _incentiveTokens;
}
/// @notice Set tranche Rewards contract addresses (for tranches incentivization)
/// @param _AAStaking IdleCDOTrancheRewards contract address for AA tranches
/// @param _BBStaking IdleCDOTrancheRewards contract address for BB tranches
function setStakingRewards(address _AAStaking, address _BBStaking) external {
_checkOnlyOwner();
// Read state variable once
address _AATranche = AATranche;
address _BBTranche = BBTranche;
address[] memory _incentiveTokens = incentiveTokens;
address _currAAStaking = AAStaking;
address _currBBStaking = BBStaking;
bool _isAAStakingActive = _currAAStaking != address(0);
bool _isBBStakingActive = _currBBStaking != address(0);
address _incentiveToken;
// Remove allowance for incentive tokens for current staking contracts
for (uint256 i = 0; i < _incentiveTokens.length; i++) {
_incentiveToken = _incentiveTokens[i];
if (_isAAStakingActive) {
_removeAllowance(_incentiveToken, _currAAStaking);
}
if (_isBBStakingActive) {
_removeAllowance(_incentiveToken, _currBBStaking);
}
}
// Remove allowace for tranche tokens (used for staking fees)
if (_isAAStakingActive && _AATranche != address(0)) {
_removeAllowance(_AATranche, _currAAStaking);
}
if (_isBBStakingActive && _BBTranche != address(0)) {
_removeAllowance(_BBTranche, _currBBStaking);
}
// Update staking contract addresses
AAStaking = _AAStaking;
BBStaking = _BBStaking;
_isAAStakingActive = _AAStaking != address(0);
_isBBStakingActive = _BBStaking != address(0);
// Increase allowance for incentiveTokens
for (uint256 i = 0; i < _incentiveTokens.length; i++) {
_incentiveToken = _incentiveTokens[i];
// Approve each staking contract to spend each incentiveToken on beahlf of this contract
if (_isAAStakingActive) {
_allowUnlimitedSpend(_incentiveToken, _AAStaking);
}
if (_isBBStakingActive) {
_allowUnlimitedSpend(_incentiveToken, _BBStaking);
}
}
// Increase allowance for tranche tokens (used for staking fees)
if (_isAAStakingActive && _AATranche != address(0)) {
_allowUnlimitedSpend(_AATranche, _AAStaking);
}
if (_isBBStakingActive && _BBTranche != address(0)) {
_allowUnlimitedSpend(_BBTranche, _BBStaking);
}
}
/// @notice pause deposits and redeems for all classes of tranches
/// @dev can be called by both the owner and the guardian
function emergencyShutdown() external {
_checkOnlyOwnerOrGuardian();
// prevent deposits
_pause();
// prevent withdraws
allowAAWithdraw = false;
allowBBWithdraw = false;
// Allow deposits/withdraws (once selectively re-enabled, eg for AA holders)
// without checking for lending protocol default
skipDefaultCheck = true;
revertIfTooLow = true;
}
/// @notice Pauses deposits and redeems
/// @dev can be called by both the owner and the guardian
function pause() external {
_checkOnlyOwnerOrGuardian();
_pause();
}
/// @notice Unpauses deposits and redeems
/// @dev can be called by both the owner and the guardian
function unpause() external {
_checkOnlyOwnerOrGuardian();
_unpause();
}
// ###################
// Helpers
// ###################
/// @dev Check that the msg.sender is the either the owner or the guardian
function _checkOnlyOwnerOrGuardian() internal view {
require(msg.sender == guardian || msg.sender == owner(), "6");
}
/// @dev Check that the msg.sender is the either the owner or the rebalancer
function _checkOnlyOwnerOrRebalancer() internal view {
require(msg.sender == rebalancer || msg.sender == owner(), "6");
}
/// @notice returns the current balance of this contract for a specific token
/// @param _token token address
/// @return balance of `_token` for this contract
function _contractTokenBalance(address _token) internal view returns (uint256) {
return IERC20Detailed(_token).balanceOf(address(this));
}
/// @dev Set allowance for _token to 0 for _spender
/// @param _token token address
/// @param _spender spender address
function _removeAllowance(address _token, address _spender) internal {
IERC20Detailed(_token).safeApprove(_spender, 0);
}
/// @dev Set allowance for _token to unlimited for _spender
/// @param _token token address
/// @param _spender spender address
function _allowUnlimitedSpend(address _token, address _spender) internal {
IERC20Detailed(_token).safeIncreaseAllowance(_spender, type(uint256).max);
}
/// @dev Set last caller and block.number hash. This should be called at the beginning of the first function to protect
function _updateCallerBlock() internal {
_lastCallerBlock = keccak256(abi.encodePacked(tx.origin, block.number));
}
/// @dev Check that the second function is not called in the same tx from the same tx.origin
function _checkSameTx() internal view {
require(keccak256(abi.encodePacked(tx.origin, block.number)) != _lastCallerBlock, "8");
}
/// @dev this method is only used to check whether a token is an incentive tokens or not
/// in the harvest call. The maximum number of element in the array will be a small number (eg at most 3-5)
/// @param _array array of addresses to search for an element
/// @param _val address of an element to find
/// @return flag if the _token is an incentive token or not
function _includesAddress(address[] memory _array, address _val) internal pure returns (bool) {
for (uint256 i = 0; i < _array.length; i++) {
if (_array[i] == _val) {
return true;
}
}
// explicit return to fix linter
return false;
}
/// @notice concat 2 strings in a single one
/// @param a first string
/// @param b second string
/// @return new string with a and b concatenated
function _concat(string memory a, string memory b) internal pure returns (string memory) {
return string(abi.encodePacked(a, b));
}
}pragma solidity >=0.6.2;
import './IUniswapV2Router01.sol';
interface IUniswapV2Router02 is IUniswapV2Router01 {
function removeLiquidityETHSupportingFeeOnTransferTokens(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external returns (uint amountETH);
function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline,
bool approveMax, uint8 v, bytes32 r, bytes32 s
) external returns (uint amountETH);
function swapExactTokensForTokensSupportingFeeOnTransferTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external;
function swapExactETHForTokensSupportingFeeOnTransferTokens(
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external payable;
function swapExactTokensForETHSupportingFeeOnTransferTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../utils/ContextUpgradeable.sol";
import "../proxy/utils/Initializable.sol";
/**
* @dev Contract module which allows children to implement an emergency stop
* mechanism that can be triggered by an authorized account.
*
* This module is used through inheritance. It will make available the
* modifiers `whenNotPaused` and `whenPaused`, which can be applied to
* the functions of your contract. Note that they will not be pausable by
* simply including this module, only once the modifiers are put in place.
*/
abstract contract PausableUpgradeable is Initializable, ContextUpgradeable {
/**
* @dev Emitted when the pause is triggered by `account`.
*/
event Paused(address account);
/**
* @dev Emitted when the pause is lifted by `account`.
*/
event Unpaused(address account);
bool private _paused;
/**
* @dev Initializes the contract in unpaused state.
*/
function __Pausable_init() internal initializer {
__Context_init_unchained();
__Pausable_init_unchained();
}
function __Pausable_init_unchained() internal initializer {
_paused = false;
}
/**
* @dev Returns true if the contract is paused, and false otherwise.
*/
function paused() public view virtual returns (bool) {
return _paused;
}
/**
* @dev Modifier to make a function callable only when the contract is not paused.
*
* Requirements:
*
* - The contract must not be paused.
*/
modifier whenNotPaused() {
require(!paused(), "Pausable: paused");
_;
}
/**
* @dev Modifier to make a function callable only when the contract is paused.
*
* Requirements:
*
* - The contract must be paused.
*/
modifier whenPaused() {
require(paused(), "Pausable: not paused");
_;
}
/**
* @dev Triggers stopped state.
*
* Requirements:
*
* - The contract must not be paused.
*/
function _pause() internal virtual whenNotPaused {
_paused = true;
emit Paused(_msgSender());
}
/**
* @dev Returns to normal state.
*
* Requirements:
*
* - The contract must be paused.
*/
function _unpause() internal virtual whenPaused {
_paused = false;
emit Unpaused(_msgSender());
}
uint256[49] private __gap;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../IERC20Upgradeable.sol";
import "../../../utils/AddressUpgradeable.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20Upgradeable {
using AddressUpgradeable for address;
function safeTransfer(IERC20Upgradeable token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(IERC20Upgradeable token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
/**
* @dev Deprecated. This function has issues similar to the ones found in
* {IERC20-approve}, and its usage is discouraged.
*
* Whenever possible, use {safeIncreaseAllowance} and
* {safeDecreaseAllowance} instead.
*/
function safeApprove(IERC20Upgradeable token, address spender, uint256 value) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
// solhint-disable-next-line max-line-length
require((value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender) + value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
uint256 newAllowance = oldAllowance - value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20Upgradeable token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) { // Return data is optional
// solhint-disable-next-line max-line-length
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.10;
interface IIdleCDOStrategy {
function strategyToken() external view returns(address);
function token() external view returns(address);
function tokenDecimals() external view returns(uint256);
function oneToken() external view returns(uint256);
function redeemRewards(bytes calldata _extraData) external returns(uint256[] memory);
function pullStkAAVE() external returns(uint256);
function price() external view returns(uint256);
function getRewardTokens() external view returns(address[] memory);
function deposit(uint256 _amount) external returns(uint256);
// _amount in `strategyToken`
function redeem(uint256 _amount) external returns(uint256);
// _amount in `token`
function redeemUnderlying(uint256 _amount) external returns(uint256);
function getApr() external view returns(uint256);
}// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.10;
import "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol";
interface IERC20Detailed is IERC20Upgradeable {
function name() external view returns(string memory);
function symbol() external view returns(string memory);
function decimals() external view returns(uint256);
}// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.10;
interface IIdleCDOTrancheRewards {
function stake(uint256 _amount) external;
function stakeFor(address _user, uint256 _amount) external;
function unstake(uint256 _amount) external;
function depositReward(address _reward, uint256 _amount) external;
}// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.10;
interface IStakedAave {
function COOLDOWN_SECONDS() external view returns (uint256);
function UNSTAKE_WINDOW() external view returns (uint256);
function redeem(address to, uint256 amount) external;
function transfer(address to, uint256 amount) external returns (bool);
function cooldown() external;
function balanceOf(address) external view returns (uint256);
function stakersCooldowns(address) external view returns (uint256);
}//SPDX-License-Identifier: Apache 2.0
pragma solidity 0.8.10;
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
/// @notice This abstract contract is used to add an updatable limit on the total value locked
/// that the contract can have. It also have an emergency method that allows the owner to pull
/// funds into predefined recovery address
/// @dev Inherit this contract and add the _guarded method to the child contract
abstract contract GuardedLaunchUpgradable is Initializable, OwnableUpgradeable, ReentrancyGuardUpgradeable {
using SafeERC20Upgradeable for IERC20Upgradeable;
// ERROR MESSAGES:
// 0 = is 0
// 1 = already initialized
// 2 = Contract limit reached
// TVL limit in underlying value
uint256 public limit;
// recovery address
address public governanceRecoveryFund;
/// @param _limit TVL limit. (0 means unlimited)
/// @param _governanceRecoveryFund recovery address
/// @param _owner owner address
function __GuardedLaunch_init(uint256 _limit, address _governanceRecoveryFund, address _owner) internal {
require(_governanceRecoveryFund != address(0), '0');
require(_owner != address(0), '0');
// Initialize inherited contracts
OwnableUpgradeable.__Ownable_init();
ReentrancyGuardUpgradeable.__ReentrancyGuard_init();
// Initialize state variables
limit = _limit;
governanceRecoveryFund = _governanceRecoveryFund;
// Transfer ownership
transferOwnership(_owner);
}
/// @notice this check should be called inside the child contract on deposits to check that the
/// TVL didn't exceed a threshold
/// @param _amount new amount to deposit
function _guarded(uint256 _amount) internal view {
uint256 _limit = limit;
if (_limit == 0) {
return;
}
require(getContractValue() + _amount <= _limit, '2');
}
/// @dev Check that the second function is not called in the same tx from the same tx.origin
function _checkOnlyOwner() internal view {
require(owner() == msg.sender, '6');
}
/// @notice abstract method, should return the TVL in underlyings
function getContractValue() public virtual view returns (uint256);
/// @notice set contract TVL limit
/// @param _limit limit in underlying value, 0 means no limit
function _setLimit(uint256 _limit) external {
_checkOnlyOwner();
limit = _limit;
}
/// @notice Emergency method, tokens gets transferred to the governanceRecoveryFund address
/// @param _token address of the token to transfer
/// @param _value amount to transfer
function transferToken(address _token, uint256 _value) external {
_checkOnlyOwner();
IERC20Upgradeable(_token).safeTransfer(governanceRecoveryFund, _value);
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.10;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
/// @dev ERC20 representing a tranche token
contract IdleCDOTranche is ERC20 {
// allowed minter address
address public minter;
/// @param _name tranche name
/// @param _symbol tranche symbol
constructor(
string memory _name, // eg. IdleDAI
string memory _symbol // eg. IDLEDAI
) ERC20(_name, _symbol) {
// minter is msg.sender which is IdleCDO (in initialize)
minter = msg.sender;
}
/// @param account that should receive the tranche tokens
/// @param amount of tranche tokens to mint
function mint(address account, uint256 amount) external {
require(msg.sender == minter, 'TRANCHE:!AUTH');
_mint(account, amount);
}
/// @param account that should have the tranche tokens burned
/// @param amount of tranche tokens to burn
function burn(address account, uint256 amount) external {
require(msg.sender == minter, 'TRANCHE:!AUTH');
_burn(account, amount);
}
}// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.10;
import '@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol';
contract IdleCDOStorage {
// constant to represent 100%
uint256 public constant FULL_ALLOC = 100000;
// max fee, relative to FULL_ALLOC
uint256 public constant MAX_FEE = 20000;
// one token
uint256 public constant ONE_TRANCHE_TOKEN = 10**18;
// variable used to save the last tx.origin and block.number
bytes32 internal _lastCallerBlock;
// variable used to save the block of the latest harvest
uint256 internal latestHarvestBlock;
// WETH address
address public weth;
// tokens used to incentivize the idle tranche ideal ratio
address[] public incentiveTokens;
// underlying token (eg DAI)
address public token;
// address that can only pause/unpause the contract in case of emergency
address public guardian;
// one `token` (eg for DAI 10**18)
uint256 public oneToken;
// address that can call the 'harvest' method and lend pool assets
address public rebalancer;
// address of the uniswap v2 router
IUniswapV2Router02 internal uniswapRouterV2;
// Flag for allowing AA withdraws
bool public allowAAWithdraw;
// Flag for allowing BB withdraws
bool public allowBBWithdraw;
// Flag for allowing to enable reverting in case the strategy gives back less
// amount than the requested one
bool public revertIfTooLow;
// Flag to enable the `Default Check` (related to the emergency shutdown)
bool public skipDefaultCheck;
// address of the strategy used to lend funds
address public strategy;
// address of the strategy token which represent the position in the lending provider
address public strategyToken;
// address of AA Tranche token contract
address public AATranche;
// address of BB Tranche token contract
address public BBTranche;
// address of AA Staking reward token contract
address public AAStaking;
// address of BB Staking reward token contract
address public BBStaking;
// Apr split ratio for AA tranches
// (relative to FULL_ALLOC so 50% => 50000 => 50% of the interest to tranche AA)
uint256 public trancheAPRSplitRatio; //
// Ideal tranche split ratio in `token` value
// (relative to FULL_ALLOC so 50% => 50000 means 50% of tranches (in value) should be AA)
uint256 public trancheIdealWeightRatio;
// Price for minting AA tranche, in underlyings
uint256 public priceAA;
// Price for minting BB tranche, in underlyings
uint256 public priceBB;
// last saved net asset value (in `token`) for AA tranches
uint256 public lastNAVAA;
// last saved net asset value (in `token`) for BB tranches
uint256 public lastNAVBB;
// last saved lending provider price
uint256 public lastStrategyPrice;
// Keeps track of unclaimed fees for feeReceiver
uint256 public unclaimedFees;
// Keeps an unlent balance both for cheap redeem and as 'insurance of last resort'
uint256 public unlentPerc;
// Fee amount (relative to FULL_ALLOC)
uint256 public fee;
// address of the fee receiver
address public feeReceiver;
// trancheIdealWeightRatio ± idealRanges, used in updateIncentives
uint256 public idealRange;
// period, in blocks, for progressively releasing harvested rewards to users
uint256 public releaseBlocksPeriod;
// amount of rewards sold in the last harvest (in `token`)
uint256 internal harvestedRewards;
// stkAave address
address internal constant stkAave = address(0x4da27a545c0c5B758a6BA100e3a049001de870f5);
// aave address
address internal constant AAVE = address(0x7Fc66500c84A76Ad7e9c93437bFc5Ac33E2DDaE9);
// if the cdo receive stkAAVE
bool internal isStkAAVEActive;
// referral address of the strategy developer
address public referral;
// amount of fee for feeReceiver. Max is FULL_ALLOC
uint256 public feeSplit;
}pragma solidity >=0.6.2;
interface IUniswapV2Router01 {
function factory() external pure returns (address);
function WETH() external pure returns (address);
function addLiquidity(
address tokenA,
address tokenB,
uint amountADesired,
uint amountBDesired,
uint amountAMin,
uint amountBMin,
address to,
uint deadline
) external returns (uint amountA, uint amountB, uint liquidity);
function addLiquidityETH(
address token,
uint amountTokenDesired,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external payable returns (uint amountToken, uint amountETH, uint liquidity);
function removeLiquidity(
address tokenA,
address tokenB,
uint liquidity,
uint amountAMin,
uint amountBMin,
address to,
uint deadline
) external returns (uint amountA, uint amountB);
function removeLiquidityETH(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external returns (uint amountToken, uint amountETH);
function removeLiquidityWithPermit(
address tokenA,
address tokenB,
uint liquidity,
uint amountAMin,
uint amountBMin,
address to,
uint deadline,
bool approveMax, uint8 v, bytes32 r, bytes32 s
) external returns (uint amountA, uint amountB);
function removeLiquidityETHWithPermit(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline,
bool approveMax, uint8 v, bytes32 r, bytes32 s
) external returns (uint amountToken, uint amountETH);
function swapExactTokensForTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external returns (uint[] memory amounts);
function swapTokensForExactTokens(
uint amountOut,
uint amountInMax,
address[] calldata path,
address to,
uint deadline
) external returns (uint[] memory amounts);
function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline)
external
payable
returns (uint[] memory amounts);
function swapTokensForExactETH(uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline)
external
returns (uint[] memory amounts);
function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline)
external
returns (uint[] memory amounts);
function swapETHForExactTokens(uint amountOut, address[] calldata path, address to, uint deadline)
external
payable
returns (uint[] memory amounts);
function quote(uint amountA, uint reserveA, uint reserveB) external pure returns (uint amountB);
function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns (uint amountOut);
function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) external pure returns (uint amountIn);
function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts);
function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../proxy/utils/Initializable.sol";
/*
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract ContextUpgradeable is Initializable {
function __Context_init() internal initializer {
__Context_init_unchained();
}
function __Context_init_unchained() internal initializer {
}
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
return msg.data;
}
uint256[50] private __gap;
}// SPDX-License-Identifier: MIT
// solhint-disable-next-line compiler-version
pragma solidity ^0.8.0;
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 a proxied contract can't have a constructor, it's common to move constructor logic to an
* external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
* function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
*
* TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
* possible by providing the encoded function call as the `_data` argument to {UpgradeableProxy-constructor}.
*
* CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
* that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
*/
abstract contract Initializable {
/**
* @dev Indicates that the contract has been initialized.
*/
bool private _initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool private _initializing;
/**
* @dev Modifier to protect an initializer function from being invoked twice.
*/
modifier initializer() {
require(_initializing || !_initialized, "Initializable: contract is already initialized");
bool isTopLevelCall = !_initializing;
if (isTopLevelCall) {
_initializing = true;
_initialized = true;
}
_;
if (isTopLevelCall) {
_initializing = false;
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev Collection of functions related to the address type
*/
library AddressUpgradeable {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize, which returns 0 for contracts in
// construction, since the code is only stored at the end of the
// constructor execution.
uint256 size;
// solhint-disable-next-line no-inline-assembly
assembly { size := extcodesize(account) }
return size > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
// solhint-disable-next-line avoid-low-level-calls, avoid-call-value
(bool success, ) = recipient.call{ value: amount }("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain`call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = target.call{ value: value }(data);
return _verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = target.staticcall(data);
return _verifyCallResult(success, returndata, errorMessage);
}
function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {
if (success) {
return returndata;
} else {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
// solhint-disable-next-line no-inline-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20Upgradeable {
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address recipient, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../utils/ContextUpgradeable.sol";
import "../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 initializer {
__Context_init_unchained();
__Ownable_init_unchained();
}
function __Ownable_init_unchained() internal initializer {
address msgSender = _msgSender();
_owner = msgSender;
emit OwnershipTransferred(address(0), msgSender);
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
_;
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
emit OwnershipTransferred(_owner, address(0));
_owner = 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");
emit OwnershipTransferred(_owner, newOwner);
_owner = newOwner;
}
uint256[49] private __gap;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../proxy/utils/Initializable.sol";
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*/
abstract contract ReentrancyGuardUpgradeable is Initializable {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
function __ReentrancyGuard_init() internal initializer {
__ReentrancyGuard_init_unchained();
}
function __ReentrancyGuard_init_unchained() internal initializer {
_status = _NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and make it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
// On the first call to nonReentrant, _notEntered will be true
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
// Any calls to nonReentrant after this point will fail
_status = _ENTERED;
_;
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = _NOT_ENTERED;
}
uint256[49] private __gap;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./IERC20.sol";
import "../../utils/Context.sol";
/**
* @dev Implementation of the {IERC20} interface.
*
* This implementation is agnostic to the way tokens are created. This means
* that a supply mechanism has to be added in a derived contract using {_mint}.
* For a generic mechanism see {ERC20PresetMinterPauser}.
*
* TIP: For a detailed writeup see our guide
* https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
* to implement supply mechanisms].
*
* We have followed general OpenZeppelin guidelines: functions revert instead
* of returning `false` on failure. This behavior is nonetheless conventional
* and does not conflict with the expectations of ERC20 applications.
*
* Additionally, an {Approval} event is emitted on calls to {transferFrom}.
* This allows applications to reconstruct the allowance for all accounts just
* by listening to said events. Other implementations of the EIP may not emit
* these events, as it isn't required by the specification.
*
* Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
* functions have been added to mitigate the well-known issues around setting
* allowances. See {IERC20-approve}.
*/
contract ERC20 is Context, IERC20 {
mapping (address => uint256) private _balances;
mapping (address => mapping (address => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
/**
* @dev Sets the values for {name} and {symbol}.
*
* The defaut value of {decimals} is 18. To select a different value for
* {decimals} you should overload it.
*
* All three of these values are immutable: they can only be set once during
* construction.
*/
constructor (string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
/**
* @dev Returns the name of the token.
*/
function name() public view virtual returns (string memory) {
return _name;
}
/**
* @dev Returns the symbol of the token, usually a shorter version of the
* name.
*/
function symbol() public view virtual returns (string memory) {
return _symbol;
}
/**
* @dev Returns the number of decimals used to get its user representation.
* For example, if `decimals` equals `2`, a balance of `505` tokens should
* be displayed to a user as `5,05` (`505 / 10 ** 2`).
*
* Tokens usually opt for a value of 18, imitating the relationship between
* Ether and Wei. This is the value {ERC20} uses, unless this function is
* overloaded;
*
* NOTE: This information is only used for _display_ purposes: it in
* no way affects any of the arithmetic of the contract, including
* {IERC20-balanceOf} and {IERC20-transfer}.
*/
function decimals() public view virtual returns (uint8) {
return 18;
}
/**
* @dev See {IERC20-totalSupply}.
*/
function totalSupply() public view virtual override returns (uint256) {
return _totalSupply;
}
/**
* @dev See {IERC20-balanceOf}.
*/
function balanceOf(address account) public view virtual override returns (uint256) {
return _balances[account];
}
/**
* @dev See {IERC20-transfer}.
*
* Requirements:
*
* - `recipient` cannot be the zero address.
* - the caller must have a balance of at least `amount`.
*/
function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
_transfer(_msgSender(), recipient, amount);
return true;
}
/**
* @dev See {IERC20-allowance}.
*/
function allowance(address owner, address spender) public view virtual override returns (uint256) {
return _allowances[owner][spender];
}
/**
* @dev See {IERC20-approve}.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/
function approve(address spender, uint256 amount) public virtual override returns (bool) {
_approve(_msgSender(), spender, amount);
return true;
}
/**
* @dev See {IERC20-transferFrom}.
*
* Emits an {Approval} event indicating the updated allowance. This is not
* required by the EIP. See the note at the beginning of {ERC20}.
*
* Requirements:
*
* - `sender` and `recipient` cannot be the zero address.
* - `sender` must have a balance of at least `amount`.
* - the caller must have allowance for ``sender``'s tokens of at least
* `amount`.
*/
function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {
_transfer(sender, recipient, amount);
uint256 currentAllowance = _allowances[sender][_msgSender()];
require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance");
_approve(sender, _msgSender(), currentAllowance - amount);
return true;
}
/**
* @dev Atomically increases the allowance granted to `spender` by the caller.
*
* This is an alternative to {approve} that can be used as a mitigation for
* problems described in {IERC20-approve}.
*
* Emits an {Approval} event indicating the updated allowance.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue);
return true;
}
/**
* @dev Atomically decreases the allowance granted to `spender` by the caller.
*
* This is an alternative to {approve} that can be used as a mitigation for
* problems described in {IERC20-approve}.
*
* Emits an {Approval} event indicating the updated allowance.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `spender` must have allowance for the caller of at least
* `subtractedValue`.
*/
function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
uint256 currentAllowance = _allowances[_msgSender()][spender];
require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
_approve(_msgSender(), spender, currentAllowance - subtractedValue);
return true;
}
/**
* @dev Moves tokens `amount` from `sender` to `recipient`.
*
* This is internal function is equivalent to {transfer}, and can be used to
* e.g. implement automatic token fees, slashing mechanisms, etc.
*
* Emits a {Transfer} event.
*
* Requirements:
*
* - `sender` cannot be the zero address.
* - `recipient` cannot be the zero address.
* - `sender` must have a balance of at least `amount`.
*/
function _transfer(address sender, address recipient, uint256 amount) internal virtual {
require(sender != address(0), "ERC20: transfer from the zero address");
require(recipient != address(0), "ERC20: transfer to the zero address");
_beforeTokenTransfer(sender, recipient, amount);
uint256 senderBalance = _balances[sender];
require(senderBalance >= amount, "ERC20: transfer amount exceeds balance");
_balances[sender] = senderBalance - amount;
_balances[recipient] += amount;
emit Transfer(sender, recipient, amount);
}
/** @dev Creates `amount` tokens and assigns them to `account`, increasing
* the total supply.
*
* Emits a {Transfer} event with `from` set to the zero address.
*
* Requirements:
*
* - `to` cannot be the zero address.
*/
function _mint(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: mint to the zero address");
_beforeTokenTransfer(address(0), account, amount);
_totalSupply += amount;
_balances[account] += amount;
emit Transfer(address(0), account, amount);
}
/**
* @dev Destroys `amount` tokens from `account`, reducing the
* total supply.
*
* Emits a {Transfer} event with `to` set to the zero address.
*
* Requirements:
*
* - `account` cannot be the zero address.
* - `account` must have at least `amount` tokens.
*/
function _burn(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: burn from the zero address");
_beforeTokenTransfer(account, address(0), amount);
uint256 accountBalance = _balances[account];
require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
_balances[account] = accountBalance - amount;
_totalSupply -= amount;
emit Transfer(account, address(0), amount);
}
/**
* @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
*
* This internal function is equivalent to `approve`, and can be used to
* e.g. set automatic allowances for certain subsystems, etc.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `owner` cannot be the zero address.
* - `spender` cannot be the zero address.
*/
function _approve(address owner, address spender, uint256 amount) internal virtual {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
/**
* @dev Hook that is called before any transfer of tokens. This includes
* minting and burning.
*
* Calling conditions:
*
* - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
* will be to transferred to `to`.
* - when `from` is zero, `amount` tokens will be minted for `to`.
* - when `to` is zero, `amount` of ``from``'s tokens will be burned.
* - `from` and `to` are never both zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { }
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address recipient, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/*
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
return msg.data;
}
}{
"optimizer": {
"enabled": true,
"runs": 90
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"AAStaking","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"AATranche","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"BBStaking","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"BBTranche","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FULL_ALLOC","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_FEE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ONE_TRANCHE_TOKEN","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_limit","type":"uint256"}],"name":"_setLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"allowAAWithdraw","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"allowBBWithdraw","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"depositAA","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"depositBB","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"emergencyShutdown","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"fee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeReceiver","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeSplit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_tranche","type":"address"}],"name":"getApr","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getContractValue","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentAARatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_tranche","type":"address"}],"name":"getIdealApr","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getIncentiveTokens","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"governanceRecoveryFund","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"guardian","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool[]","name":"_skipFlags","type":"bool[]"},{"internalType":"bool[]","name":"_skipReward","type":"bool[]"},{"internalType":"uint256[]","name":"_minAmount","type":"uint256[]"},{"internalType":"uint256[]","name":"_sellAmounts","type":"uint256[]"},{"internalType":"bytes","name":"_extraData","type":"bytes"}],"name":"harvest","outputs":[{"internalType":"uint256[][]","name":"_res","type":"uint256[][]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"idealRange","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"incentiveTokens","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_limit","type":"uint256"},{"internalType":"address","name":"_guardedToken","type":"address"},{"internalType":"address","name":"_governanceFund","type":"address"},{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_rebalancer","type":"address"},{"internalType":"address","name":"_strategy","type":"address"},{"internalType":"uint256","name":"_trancheAPRSplitRatio","type":"uint256"},{"internalType":"uint256","name":"_trancheIdealWeightRatio","type":"uint256"},{"internalType":"address[]","name":"_incentiveTokens","type":"address[]"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lastNAVAA","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastNAVBB","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastStrategyPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"limit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bool","name":"_revertIfNeeded","type":"bool"}],"name":"liquidate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"oneToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"priceAA","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"priceBB","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rebalancer","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"referral","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"releaseBlocksPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"revertIfTooLow","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"_allowed","type":"bool"}],"name":"setAllowAAWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_allowed","type":"bool"}],"name":"setAllowBBWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_fee","type":"uint256"}],"name":"setFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_feeReceiver","type":"address"}],"name":"setFeeReceiver","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_feeSplit","type":"uint256"}],"name":"setFeeSplit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_guardian","type":"address"}],"name":"setGuardian","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_idealRange","type":"uint256"}],"name":"setIdealRange","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_incentiveTokens","type":"address[]"}],"name":"setIncentiveTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_isStkAAVEActive","type":"bool"}],"name":"setIsStkAAVEActive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_rebalancer","type":"address"}],"name":"setRebalancer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_referral","type":"address"}],"name":"setReferral","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_releaseBlocksPeriod","type":"uint256"}],"name":"setReleaseBlocksPeriod","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_allowed","type":"bool"}],"name":"setRevertIfTooLow","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_allowed","type":"bool"}],"name":"setSkipDefaultCheck","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_AAStaking","type":"address"},{"internalType":"address","name":"_BBStaking","type":"address"}],"name":"setStakingRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_strategy","type":"address"},{"internalType":"address[]","name":"_incentiveTokens","type":"address[]"}],"name":"setStrategy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_trancheAPRSplitRatio","type":"uint256"}],"name":"setTrancheAPRSplitRatio","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_trancheIdealWeightRatio","type":"uint256"}],"name":"setTrancheIdealWeightRatio","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_unlentPerc","type":"uint256"}],"name":"setUnlentPerc","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"skipDefaultCheck","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"strategy","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"strategyToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"trancheAPRSplitRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"trancheIdealWeightRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_tranche","type":"address"}],"name":"tranchePrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"transferToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unclaimedFees","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unlentPerc","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_tranche","type":"address"}],"name":"virtualPrice","outputs":[{"internalType":"uint256","name":"_virtualPrice","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"weth","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdrawAA","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdrawBB","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
608060405234801561001057600080fd5b5060cf80546001600160a01b0319166001179055615fc580620000346000396000f3fe60806040523480156200001157600080fd5b5060043610620004415760003560e01c80638456cb591162000239578063c9aba356116200013f578063e70875ad11620000c2578063e70875ad1462000967578063eb120bf4146200097e578063eb67acb51462000992578063edd636fb14620009a9578063efdcd97414620009b3578063f22ff9f414620009ca578063f2fde38b14620009e1578063fc0c546a14620009f8578063fdf4c0dc1462000a0c578063fe81a0241462000a1657600080fd5b8063c9aba35614620008a2578063cc11580514620008b2578063cd962a0614620008c9578063d5357d8914620008e0578063dc82697c1462000906578063ddca3f431462000910578063dfd5b1c9146200091a578063e07eace61462000925578063e14488e4146200093c578063e3e39368146200095357600080fd5b80639d3ef4b211620001c85780639d3ef4b214620007eb5780639e5914da1462000800578063a219d2181462000817578063a27eccc1146200082e578063a3d0bd481462000838578063a4d66daf146200084f578063a8c62e761462000859578063b3f00674146200086d578063b450dfce1462000881578063bc063e1a146200089857600080fd5b80638456cb5914620007435780638a0dac4a146200074d5780638da5cb5b14620007645780638f5aa090146200076e5780639290d427146200078557806392b29be3146200079c57806394929dc114620007a657806399abe5e814620007bd5780639af6485414620007d457600080fd5b80633f4ba83a116200034b57806362adade511620002ce57806362adade514620006965780636373ea6914620006a057806369fe0e2d14620006aa5780636cfd155314620006c15780636f47d99b14620006d8578063715018a614620006ed578063734d828714620006f7578063747efea114620007015780637692ee0a1462000715578063812e43fa146200072c57600080fd5b80633f4ba83a14620005e05780633fc8cef314620005ea578063400f7d3214620005fe578063408f3a30146200060857806344966ba0146200061f57806344ca67ec1462000633578063452a9320146200064a57806346840590146200065e57806355c7070114620006755780635c975abb146200068a57600080fd5b80631ed4fd9711620003d45780631ed4fd9714620005205780632047782a146200054657806325cdd860146200055057806325f66adf146200055a5780632758db0c146200056457806329811ee5146200057b5780632a3e4dc214620005925780633403c2fc14620005a9578063387af1bd14620005b35780633b28d53714620005c757600080fd5b806301d22ccd1462000446578063085a2b7814620004725780630986950b146200048b5780631072cbea14620004a457806312361ac214620004bb5780631441a5a914620004c557806315c44b8b14620004de57806318dc719514620004f25780631cf7a8ff1462000509575b600080fd5b60d2546200045a906001600160a01b031681565b60405162000469919062004401565b60405180910390f35b6200047c60da5481565b60405190815260200162000469565b620004a26200049c3660046200442b565b62000a20565b005b620004a2620004b536600462004469565b62000c71565b6200047c60dc5481565b60e8546200045a9061010090046001600160a01b031681565b60d9546200045a906001600160a01b031681565b620004a26200050336600462004585565b62000c9b565b620004a26200051a3660046200464a565b6200126e565b60d3546200053590600160b81b900460ff1681565b604051901515815260200162000469565b6200047c60e55481565b6200047c620012a6565b6200047c60db5481565b6200047c6200057536600462004673565b6200131f565b6200047c6200058c3660046200469b565b62001340565b6200045a620005a33660046200464a565b62001357565b620004a262001382565b60ca546200045a906001600160a01b031681565b620005d1620013af565b60405162000469919062004701565b620004a262001413565b60cd546200045a906001600160a01b031681565b6200047c60dd5481565b620004a2620006193660046200464a565b62001429565b60d6546200045a906001600160a01b031681565b620004a2620006443660046200464a565b62001438565b60d0546200045a906001600160a01b031681565b620004a26200066f36600462004716565b620014a0565b60d3546200053590600160a01b900460ff1681565b60335460ff1662000535565b6200047c60de5481565b6200047c60e95481565b620004a2620006bb3660046200464a565b620014c8565b620004a2620006d23660046200469b565b620014fc565b60d3546200053590600160b01b900460ff1681565b620004a262001543565b6200047c60e15481565b60d5546200045a906001600160a01b031681565b620004a26200072636600462004736565b620015b0565b620004a26200073d3660046200464a565b620015cf565b620004a262001604565b620004a26200075e3660046200469b565b62001618565b6200045a6200165f565b620004a26200077f36600462004716565b6200166e565b6200047c620007963660046200469b565b62001696565b6200047c60e25481565b620004a2620007b73660046200464a565b620016ec565b6200047c620007ce3660046200464a565b620016fb565b6200047c620007e53660046200464a565b62001758565b60d3546200053590600160a81b900460ff1681565b620004a2620008113660046200469b565b620017b5565b6200047c620008283660046200469b565b620017e7565b6200047c60d15481565b620004a2620008493660046200464a565b620017f4565b6200047c60c95481565b60d4546200045a906001600160a01b031681565b60e4546200045a906001600160a01b031681565b6200047c620008923660046200464a565b62001829565b6200047c614e2081565b6200047c670de0b6b3a764000081565b620004a2620008c336600462004716565b62001845565b620004a2620008da3660046200464a565b6200186d565b620008f7620008f136600462004800565b620018a2565b60405162000469919062004900565b6200047c62001c7e565b6200047c60e35481565b6200047c620186a081565b620004a26200093636600462004716565b62001d77565b6200047c6200094d3660046200469b565b62001d9f565b60d7546200045a906001600160a01b031681565b6200047c620009783660046200464a565b62001daf565b60d8546200045a906001600160a01b031681565b620004a2620009a336600462004716565b62001dcb565b6200047c60e65481565b620004a2620009c43660046200469b565b62001de8565b620004a2620009db3660046200498e565b62001e2f565b620004a2620009f23660046200469b565b62001f7a565b60cf546200045a906001600160a01b031681565b6200047c60e05481565b6200047c60df5481565b62000a2a62002060565b60d65460d75460ce8054604080516020808402820181019092528281526001600160a01b0395861695909416936000939092909183018282801562000a9957602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831162000a7a575b505060d85460d9549495506001600160a01b039081169416925050508115158115156000805b865181101562000b235786818151811062000ade5762000ade620049e3565b60200260200101519150831562000afb5762000afb828762002094565b821562000b0e5762000b0e828662002094565b8062000b1a8162004a0f565b91505062000abf565b5082801562000b3a57506001600160a01b03881615155b1562000b4c5762000b4c888662002094565b81801562000b6257506001600160a01b03871615155b1562000b745762000b74878562002094565b60d880546001600160a01b03808d166001600160a01b0319928316811790935560d98054918d1691909216811790915590151593501515915060005b865181101562000c145786818151811062000bcf5762000bcf620049e3565b60200260200101519150831562000bec5762000bec828c620020ab565b821562000bff5762000bff828b620020ab565b8062000c0b8162004a0f565b91505062000bb0565b5082801562000c2b57506001600160a01b03881615155b1562000c3d5762000c3d888b620020ab565b81801562000c5357506001600160a01b03871615155b1562000c655762000c65878a620020ab565b50505050505050505050565b62000c7b62002060565b60ca5462000c97906001600160a01b03848116911683620020c3565b5050565b600054610100900460ff168062000cb5575060005460ff16155b62000cdd5760405162461bcd60e51b815260040162000cd49062004a2d565b60405180910390fd5b600054610100900460ff1615801562000d00576000805461ffff19166101011790555b600062000d12600a620186a062004a7b565b60cf549091506001600160a01b03161562000d545760405162461bcd60e51b81526020600482015260016024820152603160f81b604482015260640162000cd4565b6001600160a01b0387161580159062000d7557506001600160a01b03861615155b801562000d8a57506001600160a01b038a1615155b62000da95760405162461bcd60e51b815260040162000cd49062004a9e565b620186a085111562000dcf5760405162461bcd60e51b815260040162000cd49062004ab9565b62000dde81620186a062004ad4565b84111562000e005760405162461bcd60e51b815260040162000cd49062004ab9565b8084101562000e235760405162461bcd60e51b815260040162000cd49062004aee565b62000e2d62002122565b62000e3a8b8a8a620021a7565b6000866001600160a01b031663747efea16040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000e7b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000ea1919062004b09565b90506000816001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000ee4573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000f0e919081019062004b58565b905062000f4960405180604001604052806015815260200174024b23632a1a2279020a0902a3930b731b43290169605d1b8152508262002238565b62000f706040518060400160405280600381526020016241415f60e81b8152508362002238565b60405162000f7e9062004372565b62000f8b92919062004c1b565b604051809103906000f08015801562000fa8573d6000803e3d6000fd5b5060d680546001600160a01b0319166001600160a01b0392909216919091179055604080518082019091526015815274024b23632a1a227902121102a3930b731b43290169605d1b602082015262001001908262002238565b620010286040518060400160405280600381526020016242425f60e81b8152508362002238565b604051620010369062004372565b6200104392919062004c1b565b604051809103906000f08015801562001060573d6000803e3d6000fd5b5060d780546001600160a01b03199081166001600160a01b039384161790915560cf805482168f841690811790915560d4805483168c851617905560d58054831686851617905560d28054909216928c1692909217905560da88905560db87905560e58490556040805163313ce56760e01b815290516000929163313ce5679160048083019260209291908290030181865afa15801562001105573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200112b919062004c4d565b6200113890600a62004d64565b60d181905560d380546001600160a01b0319908116737a250d5630b4cf539739df2c5dacb4c659f2488d1790915560cd805490911673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc217905586519091506200119d9060ce90602089019062004380565b5060dc81905560dd8190556107d060e2556105dc60e65560d3805462ffffff60a01b19166201010160a01b179055620011d78d8a620020ab565b60d554620011ef906001600160a01b03168a620020ab565b620011f962002266565b60e055505061271060e355505060e4805473fb3bd022d5dacf95ee28a6b07825d4ff9c5b38146001600160a01b03199182161790915560d080549091166001600160a01b03891617905560e8805460ff19166001179055801562000c65576000805461ff001916905550505050505050505050565b6200127862002060565b620186a08160e28190551115620012a35760405162461bcd60e51b815260040162000cd49062004ab9565b50565b60d6546000908190620012c2906001600160a01b0316620022dc565b60d754909150600090620012df906001600160a01b0316620022dc565b620012eb908362004d72565b905080620012fc5760009250505090565b806200130c620186a08462004d8d565b62001318919062004a7b565b9250505090565b60006200132b6200236f565b620013378383620023c2565b90505b92915050565b60006200133a8262001351620012a6565b6200247d565b60ce81815481106200136857600080fd5b6000918252602090912001546001600160a01b0316905081565b6200138c62002598565b62001396620025b7565b60d3805463ffffffff60a01b191661010160b01b179055565b606060ce8054806020026020016040519081016040528092919081815260200182805480156200140957602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311620013ea575b5050505050905090565b6200141d62002598565b620014276200262c565b565b6200143362002060565b60c955565b6200144262002060565b60e554811015620014675760405162461bcd60e51b815260040162000cd49062004aee565b60e5546200147990620186a062004ad4565b8160db8190551115620012a35760405162461bcd60e51b815260040162000cd49062004ab9565b620014aa62002060565b60d38054911515600160b81b0260ff60b81b19909216919091179055565b620014d262002060565b614e208160e38190551115620012a35760405162461bcd60e51b815260040162000cd49062004ab9565b6200150662002060565b60d280546001600160a01b0319166001600160a01b038316908117909155620012a35760405162461bcd60e51b815260040162000cd49062004a9e565b336200154e6200165f565b6001600160a01b031614620015775760405162461bcd60e51b815260040162000cd49062004daf565b6065546040516000916001600160a01b03169060008051602062005f70833981519152908390a3606580546001600160a01b0319169055565b620015ba62002060565b805162000c979060ce90602084019062004380565b620015d962002060565b620186a08160e58190551115620012a35760405162461bcd60e51b815260040162000cd49062004ab9565b6200160e62002598565b62001427620025b7565b6200162262002060565b60d080546001600160a01b0319166001600160a01b038316908117909155620012a35760405162461bcd60e51b815260040162000cd49062004a9e565b6065546001600160a01b031690565b6200167862002060565b60d38054911515600160a81b0260ff60a81b19909216919091179055565b60de5460df5460009190620016e384620016af62001c7e565b620016bb848662004d72565b60d6546001600160a01b03898116911614620016d85784620016da565b855b60da54620026a9565b50949350505050565b620016f662002060565b60e655565b60006200170a60335460ff1690565b158062001720575060d354600160a81b900460ff165b6200173f5760405162461bcd60e51b815260040162000cd49062004de4565b60d7546200133a9083906001600160a01b0316620028bb565b60006200176760335460ff1690565b15806200177d575060d354600160a01b900460ff165b6200179c5760405162461bcd60e51b815260040162000cd49062004de4565b60d6546200133a9083906001600160a01b0316620028bb565b620017bf62002060565b60e880546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b60006200133a8262002b31565b620017fe62002060565b620186a08160da8190551115620012a35760405162461bcd60e51b815260040162000cd49062004ab9565b60d6546000906200133a9083906001600160a01b031662002bcc565b6200184f62002060565b60d38054911515600160a01b0260ff60a01b19909216919091179055565b6200187762002060565b620186a08160e98190551115620012a35760405162461bcd60e51b815260040162000cd49062004dff565b6060620018ae6200236f565b6040805160038082526080820190925290816020015b6060815260200190600190039081620018c457505060d4549091506001600160a01b03168b8b6003818110620018fe57620018fe620049e3565b905060200201602081019062001915919062004716565b62001b995760008c8c6000818110620019325762001932620049e3565b905060200201602081019062001949919062004716565b62001afd576040516323b1c78360e21b81526001600160a01b03831690638ec71e0c906200197e908890889060040162004e1a565b6000604051808303816000875af11580156200199e573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620019c8919081019062004e49565b83600281518110620019de57620019de620049e3565b6020026020010181905250620019f362002c57565b62001ab682888880806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f820116905080830192505050505050508b8b80806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f820116905080830192505050505050508e8e8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525062002f9f92505050565b8560008151811062001acc5762001acc620049e3565b602002602001018660018151811062001ae95762001ae9620049e3565b602002602001018295508390528390525050505b4360cc55801562001b0f578062001b12565b60015b60e75562001b1f62003358565b8c8c600281811062001b355762001b35620049e3565b905060200201602081019062001b4c919062004716565b62001b5b5762001b5b6200345d565b8c8c600181811062001b715762001b71620049e3565b905060200201602081019062001b88919062004716565b62001b975762001b9762003581565b505b60cf5460009062001bb3906001600160a01b031662003665565b90506000620186a060e25462001bc862001c7e565b62001bd4919062004d8d565b62001be0919062004a7b565b90508082111562001c6d576001600160a01b03831663b6b55f2562001c06838562004ad4565b6040518263ffffffff1660e01b815260040162001c2591815260200190565b6020604051808303816000875af115801562001c45573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001c6b919062004c4d565b505b5050509a9950505050505050505050565b60d5546040805163313ce56760e01b815290516000926001600160a01b0316918391839163313ce5679160048083019260209291908290030181865afa15801562001ccd573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001cf3919062004c4d565b905060e15462001d02620036da565b60cf5462001d19906001600160a01b031662003665565b62001d2684600a62004d64565b62001d3062002266565b62001d3b8762003665565b62001d47919062004d8d565b62001d53919062004a7b565b62001d5f919062004d72565b62001d6b919062004ad4565b62001318919062004ad4565b62001d8162002060565b60d38054911515600160b01b0260ff60b01b19909216919091179055565b60006200133a8260db546200247d565b60d7546000906200133a9083906001600160a01b031662002bcc565b62001dd562002060565b60e8805460ff1916911515919091179055565b62001df262002060565b60e480546001600160a01b0319166001600160a01b038316908117909155620012a35760405162461bcd60e51b815260040162000cd49062004a9e565b62001e3962002060565b6001600160a01b03821662001e625760405162461bcd60e51b815260040162000cd49062004a9e565b60cf5460d4546001600160a01b03918216911662001e81828262002094565b60d55462001e99906001600160a01b03168262002094565b60d480546001600160a01b0319166001600160a01b038616179055825162001ec99060ce90602086019062004380565b506000846001600160a01b031663747efea16040518163ffffffff1660e01b8152600401602060405180830381865afa15801562001f0b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001f31919062004b09565b60d580546001600160a01b0319166001600160a01b038316179055905062001f5a8386620020ab565b62001f668186620020ab565b62001f7062002266565b60e0555050505050565b3362001f856200165f565b6001600160a01b03161462001fae5760405162461bcd60e51b815260040162000cd49062004daf565b6001600160a01b038116620020155760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840162000cd4565b6065546040516001600160a01b0380841692169060008051602062005f7083398151915290600090a3606580546001600160a01b0319166001600160a01b0392909216919091179055565b336200206b6200165f565b6001600160a01b031614620014275760405162461bcd60e51b815260040162000cd49062004ed7565b62000c976001600160a01b0383168260006200373c565b62000c976001600160a01b0383168260001962003849565b6200211d8363a9059cbb60e01b8484604051602401620020e592919062004ef2565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152620038f7565b505050565b600054610100900460ff16806200213c575060005460ff16155b6200215b5760405162461bcd60e51b815260040162000cd49062004a2d565b600054610100900460ff161580156200217e576000805461ffff19166101011790555b62002188620039d0565b6200219262003a40565b8015620012a3576000805461ff001916905550565b6001600160a01b038216620021d05760405162461bcd60e51b815260040162000cd49062004a9e565b6001600160a01b038116620021f95760405162461bcd60e51b815260040162000cd49062004a9e565b6200220362003abb565b6200220d62003b2b565b60c983905560ca80546001600160a01b0319166001600160a01b0384161790556200211d8162001f7a565b606082826040516020016200224f92919062004f0b565b604051602081830303815290604052905092915050565b60d4546040805163501ad8ff60e11b815290516000926001600160a01b03169163a035b1fe9160048083019260209291908290030181865afa158015620022b1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620022d7919062004c4d565b905090565b6000670de0b6b3a7640000620022f28362001696565b836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562002331573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002357919062004c4d565b62002363919062004d8d565b6200133a919062004a7b565b60d2546001600160a01b0316331480620023a357506200238e6200165f565b6001600160a01b0316336001600160a01b0316145b620014275760405162461bcd60e51b815260040162000cd49062004ed7565b60d45460405163852a12e360e01b8152600481018490526000916001600160a01b03169063852a12e3906024016020604051808303816000875af11580156200240f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002435919062004c4d565b905081156200246d57826200244c82606462004d72565b10156200246d5760405162461bcd60e51b815260040162000cd49062004aee565b828111156200133a575090919050565b60008060d460009054906101000a90046001600160a01b03166001600160a01b031663845bc8046040518163ffffffff1660e01b8152600401602060405180830381865afa158015620024d4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620024fa919062004c4d565b60da5460d654919250906001600160a01b038681169116148462002533578062002525578262002528565b60005b93505050506200133a565b8062002575576200254885620186a062004ad4565b6200255783620186a062004ad4565b62002563908562004d8d565b6200256f919062004a7b565b6200258e565b8462002582838562004d8d565b6200258e919062004a7b565b9695505050505050565b60d0546001600160a01b0316331480620023a357506200238e6200165f565b60335460ff1615620025dd5760405162461bcd60e51b815260040162000cd49062004f3e565b6033805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258620026133390565b60405162002622919062004401565b60405180910390a1565b60335460ff16620026775760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b604482015260640162000cd4565b6033805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa3362002613565b600080848611620026cb57620026bf8762002b31565b600091509150620028b1565b6000876001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200270c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002732919062004c4d565b905085158062002740575080155b156200275557505060d15490506000620028b1565b600062002763878962004ad4565b9050620186a060e3548262002779919062004d8d565b62002785919062004a7b565b62002791908262004ad4565b60d6549091506001600160a01b03908116908a16811480620027b45781620027c1565b60d7546001600160a01b03165b6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620027ff573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002825919062004c4d565b62002833578294506200287c565b6000620186a062002845898262004ad4565b62002851908662004d8d565b6200285d919062004a7b565b9050816200286c578062002878565b62002878818562004ad4565b9550505b83670de0b6b3a764000062002892878b62004d72565b6200289e919062004d8d565b620028aa919062004a7b565b9550505050505b9550959350505050565b600060026097541415620029125760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640162000cd4565b60026097556200292162003b91565b6200292b62003be0565b6200293562003358565b82620029b0576040516370a0823160e01b81526001600160a01b038316906370a08231906200296990339060040162004401565b602060405180830381865afa15801562002987573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620029ad919062004c4d565b92505b60008311620029d35760405162461bcd60e51b815260040162000cd49062004a9e565b60cf546001600160a01b03166000620029ec8262003665565b9050670de0b6b3a764000062002a028562002b31565b62002a0e908762004d8d565b62002a1a919062004a7b565b92508083111562002a58578062002a4962002a36828662004ad4565b60d354600160b01b900460ff16620023c2565b62002a55919062004d72565b92505b604051632770a7eb60e21b81526001600160a01b03851690639dc29fac9062002a88903390899060040162004ef2565b600060405180830381600087803b15801562002aa357600080fd5b505af115801562002ab8573d6000803e3d6000fd5b5062002ad3925050506001600160a01b0383163385620020c3565b60d6546001600160a01b038581169116141562002b0a578260de600082825462002afe919062004ad4565b9091555062002b249050565b8260df600082825462002b1e919062004ad4565b90915550505b5050600160975592915050565b6000816001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562002b72573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002b98919062004c4d565b62002ba557505060d15490565b60d6546001600160a01b0383811691161462002bc45760dd546200133a565b505060dc5490565b600062002bdb60335460ff1690565b1562002bfb5760405162461bcd60e51b815260040162000cd49062004f3e565b8262002c07576200133a565b62002c128362003c3e565b62002c1c62003c97565b62002c2662003be0565b62002c3062003358565b60cf5462002c4a906001600160a01b031633308662003cc9565b6200133783338462003d03565b60e85460ff1662002c6457565b60405163091030c360e01b8152734da27a545c0c5b758a6ba100e3a049001de870f590600090829063091030c39062002ca290309060040162004401565b602060405180830381865afa15801562002cc0573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002ce6919062004c4d565b9050801562002e4d576000826001600160a01b03166372b49d636040518163ffffffff1660e01b8152600401602060405180830381865afa15801562002d30573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002d56919062004c4d565b62002d62908362004d72565b9050428110156200211d57826001600160a01b031663359c4a966040518163ffffffff1660e01b8152600401602060405180830381865afa15801562002dac573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002dd2919062004c4d565b62002dde824262004ad4565b1162002e4b576040516301e9a69560e41b81526001600160a01b03841690631e9a69509062002e169030906000199060040162004ef2565b600060405180830381600087803b15801562002e3157600080fd5b505af115801562002e46573d6000803e3d6000fd5b505050505b505b60d460009054906101000a90046001600160a01b03166001600160a01b031663cdfbe9c56040518163ffffffff1660e01b81526004016020604051808303816000875af115801562002ea3573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002ec9919062004c4d565b506040516370a0823160e01b81526000906001600160a01b038416906370a082319062002efb90309060040162004401565b602060405180830381865afa15801562002f19573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002f3f919062004c4d565b111562000c9757816001600160a01b031663787a08a66040518163ffffffff1660e01b8152600401600060405180830381600087803b15801562002f8257600080fd5b505af115801562002f97573d6000803e3d6000fd5b505050505050565b60608060008060ce80548060200260200160405190810160405280929190818152602001828054801562002ffd57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831162002fde575b505050505090506000886001600160a01b031663c4f59f9b6040518163ffffffff1660e01b8152600401600060405180830381865afa15801562003045573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526200306f919081019062004f68565b60408051600380825260808201909252919250600091829160208201606080368337505060cd5482519293506001600160a01b0316918391506001908110620030bc57620030bc620049e3565b6001600160a01b03928316602091820292909201015260cf54825191169082906002908110620030f057620030f0620049e3565b60200260200101906001600160a01b031690816001600160a01b03168152505082516001600160401b038111156200312c576200312c62004498565b60405190808252806020026020018201604052801562003156578160200160208202803683370190505b50965082516001600160401b0381111562003175576200317562004498565b6040519080825280602002602001820160405280156200319f578160200160208202803683370190505b50955060005b83518110156200334957838181518110620031c457620031c4620049e3565b60200260200101519250888181518110620031e357620031e3620049e3565b602002602001015180620031fe5750620031fe858462003df1565b156200320a5762003334565b6001600160a01b038316734da27a545c0c5b758a6ba100e3a049001de870f514156200324857737fc66500c84a76ad7e9c93437bfc5ac33e2ddae992505b82826000815181106200325f576200325f620049e3565b60200260200101906001600160a01b031690816001600160a01b031681525050620032c583838d84815181106200329a576200329a620049e3565b60200260200101518d8581518110620032b757620032b7620049e3565b602002602001015162003e60565b898381518110620032da57620032da620049e3565b60200260200101898481518110620032f657620032f6620049e3565b60200260200101828152508281525050508681815181106200331c576200331c620049e3565b60200260200101518662003331919062004d72565b95505b80620033408162004a0f565b915050620031a5565b50505050509450945094915050565b60de5460df5460006200336c828462004d72565b905060006200337a62001c7e565b60da5490915082821115620033ce5760e354620186a0906200339d858562004ad4565b620033a9919062004d8d565b620033b5919062004a7b565b60e16000828254620033c8919062004d72565b90915550505b60d6546000908190620033ee906001600160a01b031685878a87620026a9565b60d7549193509150600090819062003413906001600160a01b031687898b89620026a9565b915091508260de60008282546200342b919062004d72565b925050819055508060df600082825462003446919062004d72565b90915550505060dc929092555060dd555050505050565b60e1548015620012a35760d85460e45460e8546001600160a01b03928316928315159281169161010090041660008115620034d257620186a060e95487620034a6919062004d8d565b620034b2919062004a7b565b60d654909150620034d090829084906001600160a01b031662003d03565b505b600062003505620034e4838962004ad4565b86620034f15785620034f3565b305b60d6546001600160a01b031662003d03565b600060e1559050841562003578576040516305dc812160e31b81526001600160a01b03871690632ee409089062003543908790859060040162004ef2565b600060405180830381600087803b1580156200355e57600080fd5b505af115801562003573573d6000803e3d6000fd5b505050505b50505050505050565b60db5460da5460e55460d95460d8546001600160a01b0391821691168115801590821515906000908390620035b35750815b15620035c657620035c3620012a6565b90505b828015620035e75750811580620035e75750620035e4868962004d72565b81115b156200360657620035fc85620186a062003f91565b5050505050505050565b81801562003627575082158062003627575062003624868962004ad4565b81105b156200363c57620035fc84620186a062003f91565b81156200364f576200364f848862003f91565b8215620035fc57620035fc85620186a062003f91565b6040516370a0823160e01b81526000906001600160a01b038316906370a08231906200369690309060040162004401565b602060405180830381865afa158015620036b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200133a919062004c4d565b60e65460cc54600091908290620036f2904362004ad4565b60e7549091506001811180156200370857508282105b156200373657826200371b838262004ad4565b62003727908362004d8d565b62003733919062004a7b565b93505b50505090565b801580620037ba5750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e90604401602060405180830381865afa15801562003792573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620037b8919062004c4d565b155b620038275760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b606482015260840162000cd4565b6200211d8363095ea7b360e01b8484604051602401620020e592919062004ef2565b604051636eb1769f60e11b81523060048201526001600160a01b038381166024830152600091839186169063dd62ed3e90604401602060405180830381865afa1580156200389b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620038c1919062004c4d565b620038cd919062004d72565b9050620038f18463095ea7b360e01b8584604051602401620020e592919062004ef2565b50505050565b60006200394e826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316620040d09092919063ffffffff16565b8051909150156200211d57808060200190518101906200396f919062005001565b6200211d5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840162000cd4565b600054610100900460ff1680620039ea575060005460ff16155b62003a095760405162461bcd60e51b815260040162000cd49062004a2d565b600054610100900460ff1615801562002192576000805461ffff19166101011790558015620012a3576000805461ff001916905550565b600054610100900460ff168062003a5a575060005460ff16155b62003a795760405162461bcd60e51b815260040162000cd49062004a2d565b600054610100900460ff1615801562003a9c576000805461ffff19166101011790555b6033805460ff191690558015620012a3576000805461ff001916905550565b600054610100900460ff168062003ad5575060005460ff16155b62003af45760405162461bcd60e51b815260040162000cd49062004a2d565b600054610100900460ff1615801562003b17576000805461ffff19166101011790555b62003b21620039d0565b62002192620040e9565b600054610100900460ff168062003b45575060005460ff16155b62003b645760405162461bcd60e51b815260040162000cd49062004a2d565b600054610100900460ff1615801562003b87576000805461ffff19166101011790555b620021926200418c565b60cb54324360405160200162003ba992919062005021565b604051602081830303815290604052805190602001201415620014275760405162461bcd60e51b815260040162000cd49062004dff565b600062003bec62002266565b60d354909150600160b81b900460ff1662003c39578060e054111562003c395760405162461bcd60e51b81526020600482015260016024820152600d60fa1b604482015260640162000cd4565b60e055565b60c9548062003c4b575050565b808262003c5762001c7e565b62003c63919062004d72565b111562000c975760405162461bcd60e51b81526020600482015260016024820152601960f91b604482015260640162000cd4565b324360405160200162003cac92919062005021565b60408051601f19818403018152919052805160209091012060cb55565b6040516001600160a01b0380851660248301528316604482015260648101829052620038f19085906323b872dd60e01b90608401620020e5565b600062003d108262002b31565b62003d24670de0b6b3a76400008662004d8d565b62003d30919062004a7b565b6040516340c10f1960e01b81529091506001600160a01b038316906340c10f199062003d63908690859060040162004ef2565b600060405180830381600087803b15801562003d7e57600080fd5b505af115801562003d93573d6000803e3d6000fd5b505060d6546001600160a01b0385811691161415915062003dd09050578360de600082825462003dc4919062004d72565b9091555062003dea9050565b8360df600082825462003de4919062004d72565b90915550505b9392505050565b6000805b835181101562003e5657826001600160a01b031684828151811062003e1e5762003e1e620049e3565b60200260200101516001600160a01b0316141562003e415760019150506200133a565b8062003e4d8162004a0f565b91505062003df5565b5060009392505050565b6000808362003e775762003e748662003665565b93505b8362003e895750600090508062003f88565b60d3546001600160a01b039081169062003ea7908816828762003849565b60006001600160a01b0382166338ed173987878a3062003ec942600162004d72565b6040518663ffffffff1660e01b815260040162003eeb95949392919062005043565b6000604051808303816000875af115801562003f0b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262003f35919081019062004e49565b90508060008151811062003f4d5762003f4d620049e3565b6020026020010151816001835162003f66919062004ad4565b8151811062003f795762003f79620049e3565b60200260200101519350935050505b94509492505050565b600060ce80548060200260200160405190810160405280929190818152602001828054801562003feb57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831162003fcc575b5050505050905060005b8151811015620038f1576000828281518110620040165762004016620049e3565b602002602001015190506000620186a085620040328462003665565b6200403e919062004d8d565b6200404a919062004a7b565b90508015620040b857604051637db4e28f60e01b81526001600160a01b03871690637db4e28f9062004083908590859060040162004ef2565b600060405180830381600087803b1580156200409e57600080fd5b505af1158015620040b3573d6000803e3d6000fd5b505050505b50508080620040c79062004a0f565b91505062003ff5565b6060620040e1848460008562004202565b949350505050565b600054610100900460ff168062004103575060005460ff16155b620041225760405162461bcd60e51b815260040162000cd49062004a2d565b600054610100900460ff1615801562004145576000805461ffff19166101011790555b606580546001600160a01b03191633908117909155604051819060009060008051602062005f70833981519152908290a3508015620012a3576000805461ff001916905550565b600054610100900460ff1680620041a6575060005460ff16155b620041c55760405162461bcd60e51b815260040162000cd49062004a2d565b600054610100900460ff16158015620041e8576000805461ffff19166101011790555b60016097558015620012a3576000805461ff001916905550565b606082471015620042655760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840162000cd4565b843b620042b55760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640162000cd4565b600080866001600160a01b03168587604051620042d3919062005081565b60006040518083038185875af1925050503d806000811462004312576040519150601f19603f3d011682016040523d82523d6000602084013e62004317565b606091505b50915091506200432982828662004334565b979650505050505050565b606083156200434557508162003dea565b825115620043565782518084602001fd5b8160405162461bcd60e51b815260040162000cd491906200509f565b610ebb80620050b583390190565b828054828255906000526020600020908101928215620043d8579160200282015b82811115620043d857825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190620043a1565b50620043e6929150620043ea565b5090565b5b80821115620043e65760008155600101620043eb565b6001600160a01b0391909116815260200190565b6001600160a01b0381168114620012a357600080fd5b600080604083850312156200443f57600080fd5b82356200444c8162004415565b915060208301356200445e8162004415565b809150509250929050565b600080604083850312156200447d57600080fd5b82356200448a8162004415565b946020939093013593505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b0381118282101715620044d957620044d962004498565b604052919050565b60006001600160401b03821115620044fd57620044fd62004498565b5060051b60200190565b600082601f8301126200451957600080fd5b81356020620045326200452c83620044e1565b620044ae565b82815260059290921b840181019181810190868411156200455257600080fd5b8286015b848110156200457a5780356200456c8162004415565b835291830191830162004556565b509695505050505050565b60008060008060008060008060006101208a8c031215620045a557600080fd5b8935985060208a0135620045b98162004415565b975060408a0135620045cb8162004415565b965060608a0135620045dd8162004415565b955060808a0135620045ef8162004415565b945060a08a0135620046018162004415565b935060c08a0135925060e08a013591506101008a01356001600160401b038111156200462c57600080fd5b6200463a8c828d0162004507565b9150509295985092959850929598565b6000602082840312156200465d57600080fd5b5035919050565b8015158114620012a357600080fd5b600080604083850312156200468757600080fd5b8235915060208301356200445e8162004664565b600060208284031215620046ae57600080fd5b813562003dea8162004415565b600081518084526020808501945080840160005b83811015620046f65781516001600160a01b031687529582019590820190600101620046cf565b509495945050505050565b602081526000620013376020830184620046bb565b6000602082840312156200472957600080fd5b813562003dea8162004664565b6000602082840312156200474957600080fd5b81356001600160401b038111156200476057600080fd5b620040e18482850162004507565b60008083601f8401126200478157600080fd5b5081356001600160401b038111156200479957600080fd5b6020830191508360208260051b8501011115620047b557600080fd5b9250929050565b60008083601f840112620047cf57600080fd5b5081356001600160401b03811115620047e757600080fd5b602083019150836020828501011115620047b557600080fd5b60008060008060008060008060008060a08b8d0312156200482057600080fd5b8a356001600160401b03808211156200483857600080fd5b620048468e838f016200476e565b909c509a5060208d01359150808211156200486057600080fd5b6200486e8e838f016200476e565b909a50985060408d01359150808211156200488857600080fd5b620048968e838f016200476e565b909850965060608d0135915080821115620048b057600080fd5b620048be8e838f016200476e565b909650945060808d0135915080821115620048d857600080fd5b50620048e78d828e01620047bc565b915080935050809150509295989b9194979a5092959850565b6000602080830181845280855180835260408601915060408160051b87010192508387016000805b838110156200498057888603603f19018552825180518088529088019088880190845b81811015620049695783518352928a0192918a01916001016200494b565b509097505050938601939186019160010162004928565b509398975050505050505050565b60008060408385031215620049a257600080fd5b8235620049af8162004415565b915060208301356001600160401b03811115620049cb57600080fd5b620049d98582860162004507565b9150509250929050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600060001982141562004a265762004a26620049f9565b5060010190565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b60008262004a9957634e487b7160e01b600052601260045260246000fd5b500490565b6020808252600190820152600360fc1b604082015260600190565b6020808252600190820152603760f81b604082015260600190565b60008282101562004ae95762004ae9620049f9565b500390565b6020808252600190820152603560f81b604082015260600190565b60006020828403121562004b1c57600080fd5b815162003dea8162004415565b60005b8381101562004b4657818101518382015260200162004b2c565b83811115620038f15750506000910152565b60006020828403121562004b6b57600080fd5b81516001600160401b038082111562004b8357600080fd5b818401915084601f83011262004b9857600080fd5b81518181111562004bad5762004bad62004498565b62004bc2601f8201601f1916602001620044ae565b915080825285602082850101111562004bda57600080fd5b620016e381602084016020860162004b29565b6000815180845262004c0781602086016020860162004b29565b601f01601f19169290920160200192915050565b60408152600062004c30604083018562004bed565b828103602084015262004c44818562004bed565b95945050505050565b60006020828403121562004c6057600080fd5b5051919050565b600181815b8085111562004ca857816000190482111562004c8c5762004c8c620049f9565b8085161562004c9a57918102915b93841c939080029062004c6c565b509250929050565b60008262004cc1575060016200133a565b8162004cd0575060006200133a565b816001811462004ce9576002811462004cf45762004d14565b60019150506200133a565b60ff84111562004d085762004d08620049f9565b50506001821b6200133a565b5060208310610133831016604e8410600b841016171562004d39575081810a6200133a565b62004d45838362004c67565b806000190482111562004d5c5762004d5c620049f9565b029392505050565b600062001337838362004cb0565b6000821982111562004d885762004d88620049f9565b500190565b600081600019048311821515161562004daa5762004daa620049f9565b500290565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b6020808252600190820152603360f81b604082015260600190565b6020808252600190820152600760fb1b604082015260600190565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b6000602080838503121562004e5d57600080fd5b82516001600160401b0381111562004e7457600080fd5b8301601f8101851362004e8657600080fd5b805162004e976200452c82620044e1565b81815260059190911b8201830190838101908783111562004eb757600080fd5b928401925b82841015620043295783518252928401929084019062004ebc565b6020808252600190820152601b60f91b604082015260600190565b6001600160a01b03929092168252602082015260400190565b6000835162004f1f81846020880162004b29565b83519083019062004f3581836020880162004b29565b01949350505050565b60208082526010908201526f14185d5cd8589b194e881c185d5cd95960821b604082015260600190565b6000602080838503121562004f7c57600080fd5b82516001600160401b0381111562004f9357600080fd5b8301601f8101851362004fa557600080fd5b805162004fb66200452c82620044e1565b81815260059190911b8201830190838101908783111562004fd657600080fd5b928401925b828410156200432957835162004ff18162004415565b8252928401929084019062004fdb565b6000602082840312156200501457600080fd5b815162003dea8162004664565b60609290921b6bffffffffffffffffffffffff19168252601482015260340190565b85815284602082015260a0604082015260006200506460a0830186620046bb565b6001600160a01b0394909416606083015250608001529392505050565b600082516200509581846020870162004b29565b9190910192915050565b60208152600062001337602083018462004bed56fe60806040523480156200001157600080fd5b5060405162000ebb38038062000ebb8339810160408190526200003491620001f4565b8151829082906200004d90600390602085019062000081565b5080516200006390600490602084019062000081565b5050600580546001600160a01b03191633179055506200029b915050565b8280546200008f906200025e565b90600052602060002090601f016020900481019282620000b35760008555620000fe565b82601f10620000ce57805160ff1916838001178555620000fe565b82800160010185558215620000fe579182015b82811115620000fe578251825591602001919060010190620000e1565b506200010c92915062000110565b5090565b5b808211156200010c576000815560010162000111565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200014f57600080fd5b81516001600160401b03808211156200016c576200016c62000127565b604051601f8301601f19908116603f0116810190828211818310171562000197576200019762000127565b81604052838152602092508683858801011115620001b457600080fd5b600091505b83821015620001d85785820183015181830184015290820190620001b9565b83821115620001ea5760008385830101525b9695505050505050565b600080604083850312156200020857600080fd5b82516001600160401b03808211156200022057600080fd5b6200022e868387016200013d565b935060208501519150808211156200024557600080fd5b5062000254858286016200013d565b9150509250929050565b600181811c908216806200027357607f821691505b602082108114156200029557634e487b7160e01b600052602260045260246000fd5b50919050565b610c1080620002ab6000396000f3fe608060405234801561001057600080fd5b50600436106100ca5760003560e01c806340c10f191161007c57806340c10f191461018257806370a082311461019757806395d89b41146101c05780639dc29fac146101c8578063a457c2d7146101db578063a9059cbb146101ee578063dd62ed3e1461020157600080fd5b806306fdde03146100cf57806307546172146100ed578063095ea7b31461011857806318160ddd1461013b57806323b872dd1461014d578063313ce56714610160578063395093511461016f575b600080fd5b6100d761023a565b6040516100e491906109e7565b60405180910390f35b600554610100906001600160a01b031681565b6040516001600160a01b0390911681526020016100e4565b61012b610126366004610a58565b6102cc565b60405190151581526020016100e4565b6002545b6040519081526020016100e4565b61012b61015b366004610a82565b6102e2565b604051601281526020016100e4565b61012b61017d366004610a58565b610398565b610195610190366004610a58565b6103cf565b005b61013f6101a5366004610abe565b6001600160a01b031660009081526020819052604090205490565b6100d7610407565b6101956101d6366004610a58565b610416565b61012b6101e9366004610a58565b61044a565b61012b6101fc366004610a58565b6104e5565b61013f61020f366004610ae0565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b60606003805461024990610b13565b80601f016020809104026020016040519081016040528092919081815260200182805461027590610b13565b80156102c25780601f10610297576101008083540402835291602001916102c2565b820191906000526020600020905b8154815290600101906020018083116102a557829003601f168201915b5050505050905090565b60006102d93384846104f2565b50600192915050565b60006102ef848484610617565b6001600160a01b0384166000908152600160209081526040808320338452909152902054828110156103795760405162461bcd60e51b815260206004820152602860248201527f45524332303a207472616e7366657220616d6f756e74206578636565647320616044820152676c6c6f77616e636560c01b60648201526084015b60405180910390fd5b61038d85336103888685610b64565b6104f2565b506001949350505050565b3360008181526001602090815260408083206001600160a01b038716845290915281205490916102d9918590610388908690610b7b565b6005546001600160a01b031633146103f95760405162461bcd60e51b815260040161037090610b93565b61040382826107dd565b5050565b60606004805461024990610b13565b6005546001600160a01b031633146104405760405162461bcd60e51b815260040161037090610b93565b61040382826108aa565b3360009081526001602090815260408083206001600160a01b0386168452909152812054828110156104cc5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608401610370565b6104db33856103888685610b64565b5060019392505050565b60006102d9338484610617565b6001600160a01b0383166105545760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610370565b6001600160a01b0382166105b55760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610370565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b6001600160a01b03831661067b5760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610370565b6001600160a01b0382166106dd5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610370565b6001600160a01b038316600090815260208190526040902054818110156107555760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610370565b61075f8282610b64565b6001600160a01b038086166000908152602081905260408082209390935590851681529081208054849290610795908490610b7b565b92505081905550826001600160a01b0316846001600160a01b0316600080516020610bbb833981519152846040516107cf91815260200190565b60405180910390a350505050565b6001600160a01b0382166108335760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610370565b80600260008282546108459190610b7b565b90915550506001600160a01b03821660009081526020819052604081208054839290610872908490610b7b565b90915550506040518181526001600160a01b03831690600090600080516020610bbb8339815191529060200160405180910390a35050565b6001600160a01b03821661090a5760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608401610370565b6001600160a01b0382166000908152602081905260409020548181101561097e5760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608401610370565b6109888282610b64565b6001600160a01b038416600090815260208190526040812091909155600280548492906109b6908490610b64565b90915550506040518281526000906001600160a01b03851690600080516020610bbb8339815191529060200161060a565b600060208083528351808285015260005b81811015610a14578581018301518582016040015282016109f8565b81811115610a26576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b0381168114610a5357600080fd5b919050565b60008060408385031215610a6b57600080fd5b610a7483610a3c565b946020939093013593505050565b600080600060608486031215610a9757600080fd5b610aa084610a3c565b9250610aae60208501610a3c565b9150604084013590509250925092565b600060208284031215610ad057600080fd5b610ad982610a3c565b9392505050565b60008060408385031215610af357600080fd5b610afc83610a3c565b9150610b0a60208401610a3c565b90509250929050565b600181811c90821680610b2757607f821691505b60208210811415610b4857634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b600082821015610b7657610b76610b4e565b500390565b60008219821115610b8e57610b8e610b4e565b500190565b6020808252600d908201526c0a8a4829c86908a744282aaa89609b1b60408201526060019056feddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa26469706673582212200e6d35ef1ebff3fb23df47e3bb81d32388bde501b266ddc8ce3aaf280dd89ce464736f6c634300080a00338be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0a2646970667358221220cff232f965e34c6431035c3f70f7e0b6011ba39f963ef823f16365a840daf58964736f6c634300080a0033
Deployed Bytecode
0x60806040523480156200001157600080fd5b5060043610620004415760003560e01c80638456cb591162000239578063c9aba356116200013f578063e70875ad11620000c2578063e70875ad1462000967578063eb120bf4146200097e578063eb67acb51462000992578063edd636fb14620009a9578063efdcd97414620009b3578063f22ff9f414620009ca578063f2fde38b14620009e1578063fc0c546a14620009f8578063fdf4c0dc1462000a0c578063fe81a0241462000a1657600080fd5b8063c9aba35614620008a2578063cc11580514620008b2578063cd962a0614620008c9578063d5357d8914620008e0578063dc82697c1462000906578063ddca3f431462000910578063dfd5b1c9146200091a578063e07eace61462000925578063e14488e4146200093c578063e3e39368146200095357600080fd5b80639d3ef4b211620001c85780639d3ef4b214620007eb5780639e5914da1462000800578063a219d2181462000817578063a27eccc1146200082e578063a3d0bd481462000838578063a4d66daf146200084f578063a8c62e761462000859578063b3f00674146200086d578063b450dfce1462000881578063bc063e1a146200089857600080fd5b80638456cb5914620007435780638a0dac4a146200074d5780638da5cb5b14620007645780638f5aa090146200076e5780639290d427146200078557806392b29be3146200079c57806394929dc114620007a657806399abe5e814620007bd5780639af6485414620007d457600080fd5b80633f4ba83a116200034b57806362adade511620002ce57806362adade514620006965780636373ea6914620006a057806369fe0e2d14620006aa5780636cfd155314620006c15780636f47d99b14620006d8578063715018a614620006ed578063734d828714620006f7578063747efea114620007015780637692ee0a1462000715578063812e43fa146200072c57600080fd5b80633f4ba83a14620005e05780633fc8cef314620005ea578063400f7d3214620005fe578063408f3a30146200060857806344966ba0146200061f57806344ca67ec1462000633578063452a9320146200064a57806346840590146200065e57806355c7070114620006755780635c975abb146200068a57600080fd5b80631ed4fd9711620003d45780631ed4fd9714620005205780632047782a146200054657806325cdd860146200055057806325f66adf146200055a5780632758db0c146200056457806329811ee5146200057b5780632a3e4dc214620005925780633403c2fc14620005a9578063387af1bd14620005b35780633b28d53714620005c757600080fd5b806301d22ccd1462000446578063085a2b7814620004725780630986950b146200048b5780631072cbea14620004a457806312361ac214620004bb5780631441a5a914620004c557806315c44b8b14620004de57806318dc719514620004f25780631cf7a8ff1462000509575b600080fd5b60d2546200045a906001600160a01b031681565b60405162000469919062004401565b60405180910390f35b6200047c60da5481565b60405190815260200162000469565b620004a26200049c3660046200442b565b62000a20565b005b620004a2620004b536600462004469565b62000c71565b6200047c60dc5481565b60e8546200045a9061010090046001600160a01b031681565b60d9546200045a906001600160a01b031681565b620004a26200050336600462004585565b62000c9b565b620004a26200051a3660046200464a565b6200126e565b60d3546200053590600160b81b900460ff1681565b604051901515815260200162000469565b6200047c60e55481565b6200047c620012a6565b6200047c60db5481565b6200047c6200057536600462004673565b6200131f565b6200047c6200058c3660046200469b565b62001340565b6200045a620005a33660046200464a565b62001357565b620004a262001382565b60ca546200045a906001600160a01b031681565b620005d1620013af565b60405162000469919062004701565b620004a262001413565b60cd546200045a906001600160a01b031681565b6200047c60dd5481565b620004a2620006193660046200464a565b62001429565b60d6546200045a906001600160a01b031681565b620004a2620006443660046200464a565b62001438565b60d0546200045a906001600160a01b031681565b620004a26200066f36600462004716565b620014a0565b60d3546200053590600160a01b900460ff1681565b60335460ff1662000535565b6200047c60de5481565b6200047c60e95481565b620004a2620006bb3660046200464a565b620014c8565b620004a2620006d23660046200469b565b620014fc565b60d3546200053590600160b01b900460ff1681565b620004a262001543565b6200047c60e15481565b60d5546200045a906001600160a01b031681565b620004a26200072636600462004736565b620015b0565b620004a26200073d3660046200464a565b620015cf565b620004a262001604565b620004a26200075e3660046200469b565b62001618565b6200045a6200165f565b620004a26200077f36600462004716565b6200166e565b6200047c620007963660046200469b565b62001696565b6200047c60e25481565b620004a2620007b73660046200464a565b620016ec565b6200047c620007ce3660046200464a565b620016fb565b6200047c620007e53660046200464a565b62001758565b60d3546200053590600160a81b900460ff1681565b620004a2620008113660046200469b565b620017b5565b6200047c620008283660046200469b565b620017e7565b6200047c60d15481565b620004a2620008493660046200464a565b620017f4565b6200047c60c95481565b60d4546200045a906001600160a01b031681565b60e4546200045a906001600160a01b031681565b6200047c620008923660046200464a565b62001829565b6200047c614e2081565b6200047c670de0b6b3a764000081565b620004a2620008c336600462004716565b62001845565b620004a2620008da3660046200464a565b6200186d565b620008f7620008f136600462004800565b620018a2565b60405162000469919062004900565b6200047c62001c7e565b6200047c60e35481565b6200047c620186a081565b620004a26200093636600462004716565b62001d77565b6200047c6200094d3660046200469b565b62001d9f565b60d7546200045a906001600160a01b031681565b6200047c620009783660046200464a565b62001daf565b60d8546200045a906001600160a01b031681565b620004a2620009a336600462004716565b62001dcb565b6200047c60e65481565b620004a2620009c43660046200469b565b62001de8565b620004a2620009db3660046200498e565b62001e2f565b620004a2620009f23660046200469b565b62001f7a565b60cf546200045a906001600160a01b031681565b6200047c60e05481565b6200047c60df5481565b62000a2a62002060565b60d65460d75460ce8054604080516020808402820181019092528281526001600160a01b0395861695909416936000939092909183018282801562000a9957602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831162000a7a575b505060d85460d9549495506001600160a01b039081169416925050508115158115156000805b865181101562000b235786818151811062000ade5762000ade620049e3565b60200260200101519150831562000afb5762000afb828762002094565b821562000b0e5762000b0e828662002094565b8062000b1a8162004a0f565b91505062000abf565b5082801562000b3a57506001600160a01b03881615155b1562000b4c5762000b4c888662002094565b81801562000b6257506001600160a01b03871615155b1562000b745762000b74878562002094565b60d880546001600160a01b03808d166001600160a01b0319928316811790935560d98054918d1691909216811790915590151593501515915060005b865181101562000c145786818151811062000bcf5762000bcf620049e3565b60200260200101519150831562000bec5762000bec828c620020ab565b821562000bff5762000bff828b620020ab565b8062000c0b8162004a0f565b91505062000bb0565b5082801562000c2b57506001600160a01b03881615155b1562000c3d5762000c3d888b620020ab565b81801562000c5357506001600160a01b03871615155b1562000c655762000c65878a620020ab565b50505050505050505050565b62000c7b62002060565b60ca5462000c97906001600160a01b03848116911683620020c3565b5050565b600054610100900460ff168062000cb5575060005460ff16155b62000cdd5760405162461bcd60e51b815260040162000cd49062004a2d565b60405180910390fd5b600054610100900460ff1615801562000d00576000805461ffff19166101011790555b600062000d12600a620186a062004a7b565b60cf549091506001600160a01b03161562000d545760405162461bcd60e51b81526020600482015260016024820152603160f81b604482015260640162000cd4565b6001600160a01b0387161580159062000d7557506001600160a01b03861615155b801562000d8a57506001600160a01b038a1615155b62000da95760405162461bcd60e51b815260040162000cd49062004a9e565b620186a085111562000dcf5760405162461bcd60e51b815260040162000cd49062004ab9565b62000dde81620186a062004ad4565b84111562000e005760405162461bcd60e51b815260040162000cd49062004ab9565b8084101562000e235760405162461bcd60e51b815260040162000cd49062004aee565b62000e2d62002122565b62000e3a8b8a8a620021a7565b6000866001600160a01b031663747efea16040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000e7b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000ea1919062004b09565b90506000816001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000ee4573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000f0e919081019062004b58565b905062000f4960405180604001604052806015815260200174024b23632a1a2279020a0902a3930b731b43290169605d1b8152508262002238565b62000f706040518060400160405280600381526020016241415f60e81b8152508362002238565b60405162000f7e9062004372565b62000f8b92919062004c1b565b604051809103906000f08015801562000fa8573d6000803e3d6000fd5b5060d680546001600160a01b0319166001600160a01b0392909216919091179055604080518082019091526015815274024b23632a1a227902121102a3930b731b43290169605d1b602082015262001001908262002238565b620010286040518060400160405280600381526020016242425f60e81b8152508362002238565b604051620010369062004372565b6200104392919062004c1b565b604051809103906000f08015801562001060573d6000803e3d6000fd5b5060d780546001600160a01b03199081166001600160a01b039384161790915560cf805482168f841690811790915560d4805483168c851617905560d58054831686851617905560d28054909216928c1692909217905560da88905560db87905560e58490556040805163313ce56760e01b815290516000929163313ce5679160048083019260209291908290030181865afa15801562001105573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200112b919062004c4d565b6200113890600a62004d64565b60d181905560d380546001600160a01b0319908116737a250d5630b4cf539739df2c5dacb4c659f2488d1790915560cd805490911673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc217905586519091506200119d9060ce90602089019062004380565b5060dc81905560dd8190556107d060e2556105dc60e65560d3805462ffffff60a01b19166201010160a01b179055620011d78d8a620020ab565b60d554620011ef906001600160a01b03168a620020ab565b620011f962002266565b60e055505061271060e355505060e4805473fb3bd022d5dacf95ee28a6b07825d4ff9c5b38146001600160a01b03199182161790915560d080549091166001600160a01b03891617905560e8805460ff19166001179055801562000c65576000805461ff001916905550505050505050505050565b6200127862002060565b620186a08160e28190551115620012a35760405162461bcd60e51b815260040162000cd49062004ab9565b50565b60d6546000908190620012c2906001600160a01b0316620022dc565b60d754909150600090620012df906001600160a01b0316620022dc565b620012eb908362004d72565b905080620012fc5760009250505090565b806200130c620186a08462004d8d565b62001318919062004a7b565b9250505090565b60006200132b6200236f565b620013378383620023c2565b90505b92915050565b60006200133a8262001351620012a6565b6200247d565b60ce81815481106200136857600080fd5b6000918252602090912001546001600160a01b0316905081565b6200138c62002598565b62001396620025b7565b60d3805463ffffffff60a01b191661010160b01b179055565b606060ce8054806020026020016040519081016040528092919081815260200182805480156200140957602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311620013ea575b5050505050905090565b6200141d62002598565b620014276200262c565b565b6200143362002060565b60c955565b6200144262002060565b60e554811015620014675760405162461bcd60e51b815260040162000cd49062004aee565b60e5546200147990620186a062004ad4565b8160db8190551115620012a35760405162461bcd60e51b815260040162000cd49062004ab9565b620014aa62002060565b60d38054911515600160b81b0260ff60b81b19909216919091179055565b620014d262002060565b614e208160e38190551115620012a35760405162461bcd60e51b815260040162000cd49062004ab9565b6200150662002060565b60d280546001600160a01b0319166001600160a01b038316908117909155620012a35760405162461bcd60e51b815260040162000cd49062004a9e565b336200154e6200165f565b6001600160a01b031614620015775760405162461bcd60e51b815260040162000cd49062004daf565b6065546040516000916001600160a01b03169060008051602062005f70833981519152908390a3606580546001600160a01b0319169055565b620015ba62002060565b805162000c979060ce90602084019062004380565b620015d962002060565b620186a08160e58190551115620012a35760405162461bcd60e51b815260040162000cd49062004ab9565b6200160e62002598565b62001427620025b7565b6200162262002060565b60d080546001600160a01b0319166001600160a01b038316908117909155620012a35760405162461bcd60e51b815260040162000cd49062004a9e565b6065546001600160a01b031690565b6200167862002060565b60d38054911515600160a81b0260ff60a81b19909216919091179055565b60de5460df5460009190620016e384620016af62001c7e565b620016bb848662004d72565b60d6546001600160a01b03898116911614620016d85784620016da565b855b60da54620026a9565b50949350505050565b620016f662002060565b60e655565b60006200170a60335460ff1690565b158062001720575060d354600160a81b900460ff165b6200173f5760405162461bcd60e51b815260040162000cd49062004de4565b60d7546200133a9083906001600160a01b0316620028bb565b60006200176760335460ff1690565b15806200177d575060d354600160a01b900460ff165b6200179c5760405162461bcd60e51b815260040162000cd49062004de4565b60d6546200133a9083906001600160a01b0316620028bb565b620017bf62002060565b60e880546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b60006200133a8262002b31565b620017fe62002060565b620186a08160da8190551115620012a35760405162461bcd60e51b815260040162000cd49062004ab9565b60d6546000906200133a9083906001600160a01b031662002bcc565b6200184f62002060565b60d38054911515600160a01b0260ff60a01b19909216919091179055565b6200187762002060565b620186a08160e98190551115620012a35760405162461bcd60e51b815260040162000cd49062004dff565b6060620018ae6200236f565b6040805160038082526080820190925290816020015b6060815260200190600190039081620018c457505060d4549091506001600160a01b03168b8b6003818110620018fe57620018fe620049e3565b905060200201602081019062001915919062004716565b62001b995760008c8c6000818110620019325762001932620049e3565b905060200201602081019062001949919062004716565b62001afd576040516323b1c78360e21b81526001600160a01b03831690638ec71e0c906200197e908890889060040162004e1a565b6000604051808303816000875af11580156200199e573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620019c8919081019062004e49565b83600281518110620019de57620019de620049e3565b6020026020010181905250620019f362002c57565b62001ab682888880806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f820116905080830192505050505050508b8b80806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f820116905080830192505050505050508e8e8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525062002f9f92505050565b8560008151811062001acc5762001acc620049e3565b602002602001018660018151811062001ae95762001ae9620049e3565b602002602001018295508390528390525050505b4360cc55801562001b0f578062001b12565b60015b60e75562001b1f62003358565b8c8c600281811062001b355762001b35620049e3565b905060200201602081019062001b4c919062004716565b62001b5b5762001b5b6200345d565b8c8c600181811062001b715762001b71620049e3565b905060200201602081019062001b88919062004716565b62001b975762001b9762003581565b505b60cf5460009062001bb3906001600160a01b031662003665565b90506000620186a060e25462001bc862001c7e565b62001bd4919062004d8d565b62001be0919062004a7b565b90508082111562001c6d576001600160a01b03831663b6b55f2562001c06838562004ad4565b6040518263ffffffff1660e01b815260040162001c2591815260200190565b6020604051808303816000875af115801562001c45573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001c6b919062004c4d565b505b5050509a9950505050505050505050565b60d5546040805163313ce56760e01b815290516000926001600160a01b0316918391839163313ce5679160048083019260209291908290030181865afa15801562001ccd573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001cf3919062004c4d565b905060e15462001d02620036da565b60cf5462001d19906001600160a01b031662003665565b62001d2684600a62004d64565b62001d3062002266565b62001d3b8762003665565b62001d47919062004d8d565b62001d53919062004a7b565b62001d5f919062004d72565b62001d6b919062004ad4565b62001318919062004ad4565b62001d8162002060565b60d38054911515600160b01b0260ff60b01b19909216919091179055565b60006200133a8260db546200247d565b60d7546000906200133a9083906001600160a01b031662002bcc565b62001dd562002060565b60e8805460ff1916911515919091179055565b62001df262002060565b60e480546001600160a01b0319166001600160a01b038316908117909155620012a35760405162461bcd60e51b815260040162000cd49062004a9e565b62001e3962002060565b6001600160a01b03821662001e625760405162461bcd60e51b815260040162000cd49062004a9e565b60cf5460d4546001600160a01b03918216911662001e81828262002094565b60d55462001e99906001600160a01b03168262002094565b60d480546001600160a01b0319166001600160a01b038616179055825162001ec99060ce90602086019062004380565b506000846001600160a01b031663747efea16040518163ffffffff1660e01b8152600401602060405180830381865afa15801562001f0b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001f31919062004b09565b60d580546001600160a01b0319166001600160a01b038316179055905062001f5a8386620020ab565b62001f668186620020ab565b62001f7062002266565b60e0555050505050565b3362001f856200165f565b6001600160a01b03161462001fae5760405162461bcd60e51b815260040162000cd49062004daf565b6001600160a01b038116620020155760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840162000cd4565b6065546040516001600160a01b0380841692169060008051602062005f7083398151915290600090a3606580546001600160a01b0319166001600160a01b0392909216919091179055565b336200206b6200165f565b6001600160a01b031614620014275760405162461bcd60e51b815260040162000cd49062004ed7565b62000c976001600160a01b0383168260006200373c565b62000c976001600160a01b0383168260001962003849565b6200211d8363a9059cbb60e01b8484604051602401620020e592919062004ef2565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152620038f7565b505050565b600054610100900460ff16806200213c575060005460ff16155b6200215b5760405162461bcd60e51b815260040162000cd49062004a2d565b600054610100900460ff161580156200217e576000805461ffff19166101011790555b62002188620039d0565b6200219262003a40565b8015620012a3576000805461ff001916905550565b6001600160a01b038216620021d05760405162461bcd60e51b815260040162000cd49062004a9e565b6001600160a01b038116620021f95760405162461bcd60e51b815260040162000cd49062004a9e565b6200220362003abb565b6200220d62003b2b565b60c983905560ca80546001600160a01b0319166001600160a01b0384161790556200211d8162001f7a565b606082826040516020016200224f92919062004f0b565b604051602081830303815290604052905092915050565b60d4546040805163501ad8ff60e11b815290516000926001600160a01b03169163a035b1fe9160048083019260209291908290030181865afa158015620022b1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620022d7919062004c4d565b905090565b6000670de0b6b3a7640000620022f28362001696565b836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562002331573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002357919062004c4d565b62002363919062004d8d565b6200133a919062004a7b565b60d2546001600160a01b0316331480620023a357506200238e6200165f565b6001600160a01b0316336001600160a01b0316145b620014275760405162461bcd60e51b815260040162000cd49062004ed7565b60d45460405163852a12e360e01b8152600481018490526000916001600160a01b03169063852a12e3906024016020604051808303816000875af11580156200240f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002435919062004c4d565b905081156200246d57826200244c82606462004d72565b10156200246d5760405162461bcd60e51b815260040162000cd49062004aee565b828111156200133a575090919050565b60008060d460009054906101000a90046001600160a01b03166001600160a01b031663845bc8046040518163ffffffff1660e01b8152600401602060405180830381865afa158015620024d4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620024fa919062004c4d565b60da5460d654919250906001600160a01b038681169116148462002533578062002525578262002528565b60005b93505050506200133a565b8062002575576200254885620186a062004ad4565b6200255783620186a062004ad4565b62002563908562004d8d565b6200256f919062004a7b565b6200258e565b8462002582838562004d8d565b6200258e919062004a7b565b9695505050505050565b60d0546001600160a01b0316331480620023a357506200238e6200165f565b60335460ff1615620025dd5760405162461bcd60e51b815260040162000cd49062004f3e565b6033805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258620026133390565b60405162002622919062004401565b60405180910390a1565b60335460ff16620026775760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b604482015260640162000cd4565b6033805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa3362002613565b600080848611620026cb57620026bf8762002b31565b600091509150620028b1565b6000876001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200270c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002732919062004c4d565b905085158062002740575080155b156200275557505060d15490506000620028b1565b600062002763878962004ad4565b9050620186a060e3548262002779919062004d8d565b62002785919062004a7b565b62002791908262004ad4565b60d6549091506001600160a01b03908116908a16811480620027b45781620027c1565b60d7546001600160a01b03165b6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620027ff573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002825919062004c4d565b62002833578294506200287c565b6000620186a062002845898262004ad4565b62002851908662004d8d565b6200285d919062004a7b565b9050816200286c578062002878565b62002878818562004ad4565b9550505b83670de0b6b3a764000062002892878b62004d72565b6200289e919062004d8d565b620028aa919062004a7b565b9550505050505b9550959350505050565b600060026097541415620029125760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640162000cd4565b60026097556200292162003b91565b6200292b62003be0565b6200293562003358565b82620029b0576040516370a0823160e01b81526001600160a01b038316906370a08231906200296990339060040162004401565b602060405180830381865afa15801562002987573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620029ad919062004c4d565b92505b60008311620029d35760405162461bcd60e51b815260040162000cd49062004a9e565b60cf546001600160a01b03166000620029ec8262003665565b9050670de0b6b3a764000062002a028562002b31565b62002a0e908762004d8d565b62002a1a919062004a7b565b92508083111562002a58578062002a4962002a36828662004ad4565b60d354600160b01b900460ff16620023c2565b62002a55919062004d72565b92505b604051632770a7eb60e21b81526001600160a01b03851690639dc29fac9062002a88903390899060040162004ef2565b600060405180830381600087803b15801562002aa357600080fd5b505af115801562002ab8573d6000803e3d6000fd5b5062002ad3925050506001600160a01b0383163385620020c3565b60d6546001600160a01b038581169116141562002b0a578260de600082825462002afe919062004ad4565b9091555062002b249050565b8260df600082825462002b1e919062004ad4565b90915550505b5050600160975592915050565b6000816001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562002b72573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002b98919062004c4d565b62002ba557505060d15490565b60d6546001600160a01b0383811691161462002bc45760dd546200133a565b505060dc5490565b600062002bdb60335460ff1690565b1562002bfb5760405162461bcd60e51b815260040162000cd49062004f3e565b8262002c07576200133a565b62002c128362003c3e565b62002c1c62003c97565b62002c2662003be0565b62002c3062003358565b60cf5462002c4a906001600160a01b031633308662003cc9565b6200133783338462003d03565b60e85460ff1662002c6457565b60405163091030c360e01b8152734da27a545c0c5b758a6ba100e3a049001de870f590600090829063091030c39062002ca290309060040162004401565b602060405180830381865afa15801562002cc0573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002ce6919062004c4d565b9050801562002e4d576000826001600160a01b03166372b49d636040518163ffffffff1660e01b8152600401602060405180830381865afa15801562002d30573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002d56919062004c4d565b62002d62908362004d72565b9050428110156200211d57826001600160a01b031663359c4a966040518163ffffffff1660e01b8152600401602060405180830381865afa15801562002dac573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002dd2919062004c4d565b62002dde824262004ad4565b1162002e4b576040516301e9a69560e41b81526001600160a01b03841690631e9a69509062002e169030906000199060040162004ef2565b600060405180830381600087803b15801562002e3157600080fd5b505af115801562002e46573d6000803e3d6000fd5b505050505b505b60d460009054906101000a90046001600160a01b03166001600160a01b031663cdfbe9c56040518163ffffffff1660e01b81526004016020604051808303816000875af115801562002ea3573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002ec9919062004c4d565b506040516370a0823160e01b81526000906001600160a01b038416906370a082319062002efb90309060040162004401565b602060405180830381865afa15801562002f19573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002f3f919062004c4d565b111562000c9757816001600160a01b031663787a08a66040518163ffffffff1660e01b8152600401600060405180830381600087803b15801562002f8257600080fd5b505af115801562002f97573d6000803e3d6000fd5b505050505050565b60608060008060ce80548060200260200160405190810160405280929190818152602001828054801562002ffd57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831162002fde575b505050505090506000886001600160a01b031663c4f59f9b6040518163ffffffff1660e01b8152600401600060405180830381865afa15801562003045573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526200306f919081019062004f68565b60408051600380825260808201909252919250600091829160208201606080368337505060cd5482519293506001600160a01b0316918391506001908110620030bc57620030bc620049e3565b6001600160a01b03928316602091820292909201015260cf54825191169082906002908110620030f057620030f0620049e3565b60200260200101906001600160a01b031690816001600160a01b03168152505082516001600160401b038111156200312c576200312c62004498565b60405190808252806020026020018201604052801562003156578160200160208202803683370190505b50965082516001600160401b0381111562003175576200317562004498565b6040519080825280602002602001820160405280156200319f578160200160208202803683370190505b50955060005b83518110156200334957838181518110620031c457620031c4620049e3565b60200260200101519250888181518110620031e357620031e3620049e3565b602002602001015180620031fe5750620031fe858462003df1565b156200320a5762003334565b6001600160a01b038316734da27a545c0c5b758a6ba100e3a049001de870f514156200324857737fc66500c84a76ad7e9c93437bfc5ac33e2ddae992505b82826000815181106200325f576200325f620049e3565b60200260200101906001600160a01b031690816001600160a01b031681525050620032c583838d84815181106200329a576200329a620049e3565b60200260200101518d8581518110620032b757620032b7620049e3565b602002602001015162003e60565b898381518110620032da57620032da620049e3565b60200260200101898481518110620032f657620032f6620049e3565b60200260200101828152508281525050508681815181106200331c576200331c620049e3565b60200260200101518662003331919062004d72565b95505b80620033408162004a0f565b915050620031a5565b50505050509450945094915050565b60de5460df5460006200336c828462004d72565b905060006200337a62001c7e565b60da5490915082821115620033ce5760e354620186a0906200339d858562004ad4565b620033a9919062004d8d565b620033b5919062004a7b565b60e16000828254620033c8919062004d72565b90915550505b60d6546000908190620033ee906001600160a01b031685878a87620026a9565b60d7549193509150600090819062003413906001600160a01b031687898b89620026a9565b915091508260de60008282546200342b919062004d72565b925050819055508060df600082825462003446919062004d72565b90915550505060dc929092555060dd555050505050565b60e1548015620012a35760d85460e45460e8546001600160a01b03928316928315159281169161010090041660008115620034d257620186a060e95487620034a6919062004d8d565b620034b2919062004a7b565b60d654909150620034d090829084906001600160a01b031662003d03565b505b600062003505620034e4838962004ad4565b86620034f15785620034f3565b305b60d6546001600160a01b031662003d03565b600060e1559050841562003578576040516305dc812160e31b81526001600160a01b03871690632ee409089062003543908790859060040162004ef2565b600060405180830381600087803b1580156200355e57600080fd5b505af115801562003573573d6000803e3d6000fd5b505050505b50505050505050565b60db5460da5460e55460d95460d8546001600160a01b0391821691168115801590821515906000908390620035b35750815b15620035c657620035c3620012a6565b90505b828015620035e75750811580620035e75750620035e4868962004d72565b81115b156200360657620035fc85620186a062003f91565b5050505050505050565b81801562003627575082158062003627575062003624868962004ad4565b81105b156200363c57620035fc84620186a062003f91565b81156200364f576200364f848862003f91565b8215620035fc57620035fc85620186a062003f91565b6040516370a0823160e01b81526000906001600160a01b038316906370a08231906200369690309060040162004401565b602060405180830381865afa158015620036b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200133a919062004c4d565b60e65460cc54600091908290620036f2904362004ad4565b60e7549091506001811180156200370857508282105b156200373657826200371b838262004ad4565b62003727908362004d8d565b62003733919062004a7b565b93505b50505090565b801580620037ba5750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e90604401602060405180830381865afa15801562003792573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620037b8919062004c4d565b155b620038275760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b606482015260840162000cd4565b6200211d8363095ea7b360e01b8484604051602401620020e592919062004ef2565b604051636eb1769f60e11b81523060048201526001600160a01b038381166024830152600091839186169063dd62ed3e90604401602060405180830381865afa1580156200389b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620038c1919062004c4d565b620038cd919062004d72565b9050620038f18463095ea7b360e01b8584604051602401620020e592919062004ef2565b50505050565b60006200394e826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316620040d09092919063ffffffff16565b8051909150156200211d57808060200190518101906200396f919062005001565b6200211d5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840162000cd4565b600054610100900460ff1680620039ea575060005460ff16155b62003a095760405162461bcd60e51b815260040162000cd49062004a2d565b600054610100900460ff1615801562002192576000805461ffff19166101011790558015620012a3576000805461ff001916905550565b600054610100900460ff168062003a5a575060005460ff16155b62003a795760405162461bcd60e51b815260040162000cd49062004a2d565b600054610100900460ff1615801562003a9c576000805461ffff19166101011790555b6033805460ff191690558015620012a3576000805461ff001916905550565b600054610100900460ff168062003ad5575060005460ff16155b62003af45760405162461bcd60e51b815260040162000cd49062004a2d565b600054610100900460ff1615801562003b17576000805461ffff19166101011790555b62003b21620039d0565b62002192620040e9565b600054610100900460ff168062003b45575060005460ff16155b62003b645760405162461bcd60e51b815260040162000cd49062004a2d565b600054610100900460ff1615801562003b87576000805461ffff19166101011790555b620021926200418c565b60cb54324360405160200162003ba992919062005021565b604051602081830303815290604052805190602001201415620014275760405162461bcd60e51b815260040162000cd49062004dff565b600062003bec62002266565b60d354909150600160b81b900460ff1662003c39578060e054111562003c395760405162461bcd60e51b81526020600482015260016024820152600d60fa1b604482015260640162000cd4565b60e055565b60c9548062003c4b575050565b808262003c5762001c7e565b62003c63919062004d72565b111562000c975760405162461bcd60e51b81526020600482015260016024820152601960f91b604482015260640162000cd4565b324360405160200162003cac92919062005021565b60408051601f19818403018152919052805160209091012060cb55565b6040516001600160a01b0380851660248301528316604482015260648101829052620038f19085906323b872dd60e01b90608401620020e5565b600062003d108262002b31565b62003d24670de0b6b3a76400008662004d8d565b62003d30919062004a7b565b6040516340c10f1960e01b81529091506001600160a01b038316906340c10f199062003d63908690859060040162004ef2565b600060405180830381600087803b15801562003d7e57600080fd5b505af115801562003d93573d6000803e3d6000fd5b505060d6546001600160a01b0385811691161415915062003dd09050578360de600082825462003dc4919062004d72565b9091555062003dea9050565b8360df600082825462003de4919062004d72565b90915550505b9392505050565b6000805b835181101562003e5657826001600160a01b031684828151811062003e1e5762003e1e620049e3565b60200260200101516001600160a01b0316141562003e415760019150506200133a565b8062003e4d8162004a0f565b91505062003df5565b5060009392505050565b6000808362003e775762003e748662003665565b93505b8362003e895750600090508062003f88565b60d3546001600160a01b039081169062003ea7908816828762003849565b60006001600160a01b0382166338ed173987878a3062003ec942600162004d72565b6040518663ffffffff1660e01b815260040162003eeb95949392919062005043565b6000604051808303816000875af115801562003f0b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262003f35919081019062004e49565b90508060008151811062003f4d5762003f4d620049e3565b6020026020010151816001835162003f66919062004ad4565b8151811062003f795762003f79620049e3565b60200260200101519350935050505b94509492505050565b600060ce80548060200260200160405190810160405280929190818152602001828054801562003feb57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831162003fcc575b5050505050905060005b8151811015620038f1576000828281518110620040165762004016620049e3565b602002602001015190506000620186a085620040328462003665565b6200403e919062004d8d565b6200404a919062004a7b565b90508015620040b857604051637db4e28f60e01b81526001600160a01b03871690637db4e28f9062004083908590859060040162004ef2565b600060405180830381600087803b1580156200409e57600080fd5b505af1158015620040b3573d6000803e3d6000fd5b505050505b50508080620040c79062004a0f565b91505062003ff5565b6060620040e1848460008562004202565b949350505050565b600054610100900460ff168062004103575060005460ff16155b620041225760405162461bcd60e51b815260040162000cd49062004a2d565b600054610100900460ff1615801562004145576000805461ffff19166101011790555b606580546001600160a01b03191633908117909155604051819060009060008051602062005f70833981519152908290a3508015620012a3576000805461ff001916905550565b600054610100900460ff1680620041a6575060005460ff16155b620041c55760405162461bcd60e51b815260040162000cd49062004a2d565b600054610100900460ff16158015620041e8576000805461ffff19166101011790555b60016097558015620012a3576000805461ff001916905550565b606082471015620042655760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840162000cd4565b843b620042b55760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640162000cd4565b600080866001600160a01b03168587604051620042d3919062005081565b60006040518083038185875af1925050503d806000811462004312576040519150601f19603f3d011682016040523d82523d6000602084013e62004317565b606091505b50915091506200432982828662004334565b979650505050505050565b606083156200434557508162003dea565b825115620043565782518084602001fd5b8160405162461bcd60e51b815260040162000cd491906200509f565b610ebb80620050b583390190565b828054828255906000526020600020908101928215620043d8579160200282015b82811115620043d857825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190620043a1565b50620043e6929150620043ea565b5090565b5b80821115620043e65760008155600101620043eb565b6001600160a01b0391909116815260200190565b6001600160a01b0381168114620012a357600080fd5b600080604083850312156200443f57600080fd5b82356200444c8162004415565b915060208301356200445e8162004415565b809150509250929050565b600080604083850312156200447d57600080fd5b82356200448a8162004415565b946020939093013593505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b0381118282101715620044d957620044d962004498565b604052919050565b60006001600160401b03821115620044fd57620044fd62004498565b5060051b60200190565b600082601f8301126200451957600080fd5b81356020620045326200452c83620044e1565b620044ae565b82815260059290921b840181019181810190868411156200455257600080fd5b8286015b848110156200457a5780356200456c8162004415565b835291830191830162004556565b509695505050505050565b60008060008060008060008060006101208a8c031215620045a557600080fd5b8935985060208a0135620045b98162004415565b975060408a0135620045cb8162004415565b965060608a0135620045dd8162004415565b955060808a0135620045ef8162004415565b945060a08a0135620046018162004415565b935060c08a0135925060e08a013591506101008a01356001600160401b038111156200462c57600080fd5b6200463a8c828d0162004507565b9150509295985092959850929598565b6000602082840312156200465d57600080fd5b5035919050565b8015158114620012a357600080fd5b600080604083850312156200468757600080fd5b8235915060208301356200445e8162004664565b600060208284031215620046ae57600080fd5b813562003dea8162004415565b600081518084526020808501945080840160005b83811015620046f65781516001600160a01b031687529582019590820190600101620046cf565b509495945050505050565b602081526000620013376020830184620046bb565b6000602082840312156200472957600080fd5b813562003dea8162004664565b6000602082840312156200474957600080fd5b81356001600160401b038111156200476057600080fd5b620040e18482850162004507565b60008083601f8401126200478157600080fd5b5081356001600160401b038111156200479957600080fd5b6020830191508360208260051b8501011115620047b557600080fd5b9250929050565b60008083601f840112620047cf57600080fd5b5081356001600160401b03811115620047e757600080fd5b602083019150836020828501011115620047b557600080fd5b60008060008060008060008060008060a08b8d0312156200482057600080fd5b8a356001600160401b03808211156200483857600080fd5b620048468e838f016200476e565b909c509a5060208d01359150808211156200486057600080fd5b6200486e8e838f016200476e565b909a50985060408d01359150808211156200488857600080fd5b620048968e838f016200476e565b909850965060608d0135915080821115620048b057600080fd5b620048be8e838f016200476e565b909650945060808d0135915080821115620048d857600080fd5b50620048e78d828e01620047bc565b915080935050809150509295989b9194979a5092959850565b6000602080830181845280855180835260408601915060408160051b87010192508387016000805b838110156200498057888603603f19018552825180518088529088019088880190845b81811015620049695783518352928a0192918a01916001016200494b565b509097505050938601939186019160010162004928565b509398975050505050505050565b60008060408385031215620049a257600080fd5b8235620049af8162004415565b915060208301356001600160401b03811115620049cb57600080fd5b620049d98582860162004507565b9150509250929050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600060001982141562004a265762004a26620049f9565b5060010190565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b60008262004a9957634e487b7160e01b600052601260045260246000fd5b500490565b6020808252600190820152600360fc1b604082015260600190565b6020808252600190820152603760f81b604082015260600190565b60008282101562004ae95762004ae9620049f9565b500390565b6020808252600190820152603560f81b604082015260600190565b60006020828403121562004b1c57600080fd5b815162003dea8162004415565b60005b8381101562004b4657818101518382015260200162004b2c565b83811115620038f15750506000910152565b60006020828403121562004b6b57600080fd5b81516001600160401b038082111562004b8357600080fd5b818401915084601f83011262004b9857600080fd5b81518181111562004bad5762004bad62004498565b62004bc2601f8201601f1916602001620044ae565b915080825285602082850101111562004bda57600080fd5b620016e381602084016020860162004b29565b6000815180845262004c0781602086016020860162004b29565b601f01601f19169290920160200192915050565b60408152600062004c30604083018562004bed565b828103602084015262004c44818562004bed565b95945050505050565b60006020828403121562004c6057600080fd5b5051919050565b600181815b8085111562004ca857816000190482111562004c8c5762004c8c620049f9565b8085161562004c9a57918102915b93841c939080029062004c6c565b509250929050565b60008262004cc1575060016200133a565b8162004cd0575060006200133a565b816001811462004ce9576002811462004cf45762004d14565b60019150506200133a565b60ff84111562004d085762004d08620049f9565b50506001821b6200133a565b5060208310610133831016604e8410600b841016171562004d39575081810a6200133a565b62004d45838362004c67565b806000190482111562004d5c5762004d5c620049f9565b029392505050565b600062001337838362004cb0565b6000821982111562004d885762004d88620049f9565b500190565b600081600019048311821515161562004daa5762004daa620049f9565b500290565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b6020808252600190820152603360f81b604082015260600190565b6020808252600190820152600760fb1b604082015260600190565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b6000602080838503121562004e5d57600080fd5b82516001600160401b0381111562004e7457600080fd5b8301601f8101851362004e8657600080fd5b805162004e976200452c82620044e1565b81815260059190911b8201830190838101908783111562004eb757600080fd5b928401925b82841015620043295783518252928401929084019062004ebc565b6020808252600190820152601b60f91b604082015260600190565b6001600160a01b03929092168252602082015260400190565b6000835162004f1f81846020880162004b29565b83519083019062004f3581836020880162004b29565b01949350505050565b60208082526010908201526f14185d5cd8589b194e881c185d5cd95960821b604082015260600190565b6000602080838503121562004f7c57600080fd5b82516001600160401b0381111562004f9357600080fd5b8301601f8101851362004fa557600080fd5b805162004fb66200452c82620044e1565b81815260059190911b8201830190838101908783111562004fd657600080fd5b928401925b828410156200432957835162004ff18162004415565b8252928401929084019062004fdb565b6000602082840312156200501457600080fd5b815162003dea8162004664565b60609290921b6bffffffffffffffffffffffff19168252601482015260340190565b85815284602082015260a0604082015260006200506460a0830186620046bb565b6001600160a01b0394909416606083015250608001529392505050565b600082516200509581846020870162004b29565b9190910192915050565b60208152600062001337602083018462004bed56fe60806040523480156200001157600080fd5b5060405162000ebb38038062000ebb8339810160408190526200003491620001f4565b8151829082906200004d90600390602085019062000081565b5080516200006390600490602084019062000081565b5050600580546001600160a01b03191633179055506200029b915050565b8280546200008f906200025e565b90600052602060002090601f016020900481019282620000b35760008555620000fe565b82601f10620000ce57805160ff1916838001178555620000fe565b82800160010185558215620000fe579182015b82811115620000fe578251825591602001919060010190620000e1565b506200010c92915062000110565b5090565b5b808211156200010c576000815560010162000111565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200014f57600080fd5b81516001600160401b03808211156200016c576200016c62000127565b604051601f8301601f19908116603f0116810190828211818310171562000197576200019762000127565b81604052838152602092508683858801011115620001b457600080fd5b600091505b83821015620001d85785820183015181830184015290820190620001b9565b83821115620001ea5760008385830101525b9695505050505050565b600080604083850312156200020857600080fd5b82516001600160401b03808211156200022057600080fd5b6200022e868387016200013d565b935060208501519150808211156200024557600080fd5b5062000254858286016200013d565b9150509250929050565b600181811c908216806200027357607f821691505b602082108114156200029557634e487b7160e01b600052602260045260246000fd5b50919050565b610c1080620002ab6000396000f3fe608060405234801561001057600080fd5b50600436106100ca5760003560e01c806340c10f191161007c57806340c10f191461018257806370a082311461019757806395d89b41146101c05780639dc29fac146101c8578063a457c2d7146101db578063a9059cbb146101ee578063dd62ed3e1461020157600080fd5b806306fdde03146100cf57806307546172146100ed578063095ea7b31461011857806318160ddd1461013b57806323b872dd1461014d578063313ce56714610160578063395093511461016f575b600080fd5b6100d761023a565b6040516100e491906109e7565b60405180910390f35b600554610100906001600160a01b031681565b6040516001600160a01b0390911681526020016100e4565b61012b610126366004610a58565b6102cc565b60405190151581526020016100e4565b6002545b6040519081526020016100e4565b61012b61015b366004610a82565b6102e2565b604051601281526020016100e4565b61012b61017d366004610a58565b610398565b610195610190366004610a58565b6103cf565b005b61013f6101a5366004610abe565b6001600160a01b031660009081526020819052604090205490565b6100d7610407565b6101956101d6366004610a58565b610416565b61012b6101e9366004610a58565b61044a565b61012b6101fc366004610a58565b6104e5565b61013f61020f366004610ae0565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b60606003805461024990610b13565b80601f016020809104026020016040519081016040528092919081815260200182805461027590610b13565b80156102c25780601f10610297576101008083540402835291602001916102c2565b820191906000526020600020905b8154815290600101906020018083116102a557829003601f168201915b5050505050905090565b60006102d93384846104f2565b50600192915050565b60006102ef848484610617565b6001600160a01b0384166000908152600160209081526040808320338452909152902054828110156103795760405162461bcd60e51b815260206004820152602860248201527f45524332303a207472616e7366657220616d6f756e74206578636565647320616044820152676c6c6f77616e636560c01b60648201526084015b60405180910390fd5b61038d85336103888685610b64565b6104f2565b506001949350505050565b3360008181526001602090815260408083206001600160a01b038716845290915281205490916102d9918590610388908690610b7b565b6005546001600160a01b031633146103f95760405162461bcd60e51b815260040161037090610b93565b61040382826107dd565b5050565b60606004805461024990610b13565b6005546001600160a01b031633146104405760405162461bcd60e51b815260040161037090610b93565b61040382826108aa565b3360009081526001602090815260408083206001600160a01b0386168452909152812054828110156104cc5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608401610370565b6104db33856103888685610b64565b5060019392505050565b60006102d9338484610617565b6001600160a01b0383166105545760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610370565b6001600160a01b0382166105b55760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610370565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b6001600160a01b03831661067b5760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610370565b6001600160a01b0382166106dd5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610370565b6001600160a01b038316600090815260208190526040902054818110156107555760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610370565b61075f8282610b64565b6001600160a01b038086166000908152602081905260408082209390935590851681529081208054849290610795908490610b7b565b92505081905550826001600160a01b0316846001600160a01b0316600080516020610bbb833981519152846040516107cf91815260200190565b60405180910390a350505050565b6001600160a01b0382166108335760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610370565b80600260008282546108459190610b7b565b90915550506001600160a01b03821660009081526020819052604081208054839290610872908490610b7b565b90915550506040518181526001600160a01b03831690600090600080516020610bbb8339815191529060200160405180910390a35050565b6001600160a01b03821661090a5760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608401610370565b6001600160a01b0382166000908152602081905260409020548181101561097e5760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608401610370565b6109888282610b64565b6001600160a01b038416600090815260208190526040812091909155600280548492906109b6908490610b64565b90915550506040518281526000906001600160a01b03851690600080516020610bbb8339815191529060200161060a565b600060208083528351808285015260005b81811015610a14578581018301518582016040015282016109f8565b81811115610a26576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b0381168114610a5357600080fd5b919050565b60008060408385031215610a6b57600080fd5b610a7483610a3c565b946020939093013593505050565b600080600060608486031215610a9757600080fd5b610aa084610a3c565b9250610aae60208501610a3c565b9150604084013590509250925092565b600060208284031215610ad057600080fd5b610ad982610a3c565b9392505050565b60008060408385031215610af357600080fd5b610afc83610a3c565b9150610b0a60208401610a3c565b90509250929050565b600181811c90821680610b2757607f821691505b60208210811415610b4857634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b600082821015610b7657610b76610b4e565b500390565b60008219821115610b8e57610b8e610b4e565b500190565b6020808252600d908201526c0a8a4829c86908a744282aaa89609b1b60408201526060019056feddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa26469706673582212200e6d35ef1ebff3fb23df47e3bb81d32388bde501b266ddc8ce3aaf280dd89ce464736f6c634300080a00338be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0a2646970667358221220cff232f965e34c6431035c3f70f7e0b6011ba39f963ef823f16365a840daf58964736f6c634300080a0033
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
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.