Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 1 from a total of 1 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
0x60806040 | 15463508 | 723 days ago | IN | 0 ETH | 0.06129822 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
Vault
Compiler Version
v0.8.3+commit.8d00100c
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity ^0.8.0; /** * @title Vault Contract * @notice The Vault contract defines the storage for the Vault contracts * @author BankOfChain Protocol Inc */ import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol"; import "@openzeppelin/contracts/utils/math/Math.sol"; import "./VaultStorage.sol"; import "../exchanges/IExchangeAggregator.sol"; contract Vault is VaultStorage { using StableMath for uint256; using SafeERC20Upgradeable for IERC20Upgradeable; using EnumerableSet for EnumerableSet.AddressSet; using IterableIntMap for IterableIntMap.AddressToIntMap; function initialize( address _accessControlProxy, address _treasury, address _exchangeManager, address _valueInterpreter ) public initializer { _initAccessControl(_accessControlProxy); treasury = _treasury; exchangeManager = _exchangeManager; valueInterpreter = _valueInterpreter; rebasePaused = false; // Initial redeem fee of 0 basis points redeemFeeBps = 0; // 1 / 1000e4 rebaseThreshold = 1; // one week maxTimestampBetweenTwoReported = 604800; underlyingUnitsPerShare = 1e18; minCheckedStrategyTotalDebt = 1000e18; } modifier whenNotEmergency() { require(!emergencyShutdown, "ES"); _; } modifier whenNotAdjustPosition() { require(!adjustPositionPeriod, "AD"); _; } /** * @dev Verifies that the rebasing is not paused. */ modifier whenNotRebasePaused() { require(!rebasePaused, "RP"); _; } modifier isActiveStrategy(address _strategy) { checkActiveStrategy(_strategy); _; } /// @notice Version of vault function getVersion() external pure returns (string memory) { return "1.1.0"; } /// @notice Minting USDi supported assets function getSupportAssets() external view returns (address[] memory) { return assetSet.values(); } /// @notice Check '_asset' is supported or not function checkIsSupportAsset(address _asset) public view { require(assetSet.contains(_asset), "The asset not support"); } /// @notice Assets held by Vault function getTrackedAssets() external view returns (address[] memory) { return _getTrackedAssets(); } /// @notice Vault holds asset value directly in USD (1e18) function valueOfTrackedTokens() external view returns (uint256) { return _totalValueInVault(); } /// @notice Vault and vault buffer holds asset value directly in USD function valueOfTrackedTokensIncludeVaultBuffer() external view returns (uint256) { return _totalAssetInVaultAndVaultBuffer(); } /// @notice Vault total asset in USD(1e18) function totalAssets() external view returns (uint256) { return _totalValueInVault() + totalDebt; } /// @notice Vault and vault buffer total asset in USD function totalAssetsIncludeVaultBuffer() external view returns (uint256) { return _totalAssetInVaultAndVaultBuffer() + totalDebt; } /// @notice Vault total value(by chainlink price) in USD(1e18) function totalValue() external view returns (uint256) { return _totalValueInVault() + totalValueInStrategies(); } /** * @dev Internal to calculate total value of all assets held in Vault. * @return Total value(by chainlink price) in USD (1e18) */ function totalValueInVault() external view returns (uint256) { return _totalValueInVault(); } /** * @dev Internal to calculate total value of all assets held in Strategies. * @return _value Total value(by chainlink price) in USD (1e18) */ function totalValueInStrategies() public view returns (uint256 _value) { uint256 _strategyLength = strategySet.length(); for (uint256 i = 0; i < _strategyLength; i++) { uint256 estimatedTotalAssets = IStrategy(strategySet.at(i)).estimatedTotalAssets(); if (estimatedTotalAssets > 0) { _value = _value + estimatedTotalAssets; } } } /** * @notice Get pegToken price in USD * @return price in USD (1e18) */ function getPegTokenPrice() external view returns (uint256) { uint256 _totalSupply = IPegToken(pegTokenAddress).totalSupply(); uint256 _pegTokenPrice = 1e18; if (_totalSupply > 0) { address[] memory _trackedAssets = _getTrackedAssets(); uint256 _trackedAssetsLength = _trackedAssets.length; uint256[] memory _assetPrices = new uint256[](_trackedAssetsLength); uint256[] memory _assetDecimals = new uint256[](_trackedAssetsLength); uint256 _totalValueInVault = 0; uint256 _totalTransferValue = 0; for (uint256 i = 0; i < _trackedAssetsLength; i++) { address _trackedAsset = _trackedAssets[i]; uint256 _balance = _balanceOfToken(_trackedAsset, address(this)); if (_balance > 0) { _totalValueInVault = _totalValueInVault + _calculateAssetValue(_assetPrices, _assetDecimals, i, _trackedAsset, _balance); } _balance = transferFromVaultBufferAssetsMap[_trackedAsset]; if (_balance > 0) { _totalTransferValue = _totalTransferValue + _calculateAssetValue(_assetPrices, _assetDecimals, i, _trackedAsset, _balance); } } _pegTokenPrice = ((_totalValueInVault + totalDebt - _totalTransferValue) * 1e18) / _totalSupply; } return _pegTokenPrice; } /// @notice All strategies function getStrategies() external view returns (address[] memory) { return strategySet.values(); } /// @notice Check '_strategy' is active or not function checkActiveStrategy(address _strategy) public view { require(strategySet.contains(_strategy), "strategy not exist"); } /// @notice estimate Minting pending share /// @param _assets Address of the asset being deposited /// @param _amounts Amount of the asset being deposited /// @dev Support single asset or multi-assets /// @return _pending Share Amount function estimateMint(address[] memory _assets, uint256[] memory _amounts) public view returns (uint256) { return _estimateMint(_assets, _amounts); } /// @notice Minting share with stablecoins /// @param _assets Address of the asset being deposited /// @param _amounts Amount of the asset being deposited /// @dev Support single asset or multi-assets /// @return The amount of share minted function mint( address[] memory _assets, uint256[] memory _amounts, uint256 _minimumAmount ) external whenNotEmergency whenNotAdjustPosition nonReentrant returns (uint256) { uint256 _shareAmount = _estimateMint(_assets, _amounts); if (_minimumAmount > 0) { require(_shareAmount >= _minimumAmount, "Mint amount lower than minimum"); } for (uint256 i = 0; i < _assets.length; i++) { // Transfer the deposited coins to the vault IERC20Upgradeable(_assets[i]).safeTransferFrom(msg.sender, vaultBufferAddress, _amounts[i]); } IVaultBuffer(vaultBufferAddress).mint(msg.sender, _shareAmount); emit Mint(msg.sender, _assets, _amounts, _shareAmount); return _shareAmount; } /// @notice burn USDi,return stablecoins /// @param _amount Amount of USDi to burn /// @param _minimumAmount Minimum usd to receive in return function burn(uint256 _amount, uint256 _minimumAmount) external whenNotEmergency whenNotAdjustPosition nonReentrant returns (address[] memory _assets, uint256[] memory _amounts) { uint256 _accountBalance = IPegToken(pegTokenAddress).balanceOf(msg.sender); require(_amount > 0 && _amount <= _accountBalance, "USDi not enough"); address[] memory _trackedAssets = _getTrackedAssets(); uint256[] memory _assetPrices = new uint256[](_trackedAssets.length); uint256[] memory _assetDecimals = new uint256[](_trackedAssets.length); (uint256 _sharesAmount, uint256 _actualAsset) = _repayToVault( _amount, _accountBalance, _trackedAssets, _assetPrices, _assetDecimals ); uint256 _actuallyReceivedAmount = 0; (_assets, _amounts, _actuallyReceivedAmount) = _calculateAndTransfer( _actualAsset, _trackedAssets, _assetPrices, _assetDecimals ); if (_minimumAmount > 0) { require(_actuallyReceivedAmount >= _minimumAmount, "amount lower than minimum"); } _burnRebaseAndEmit( _amount, _actuallyReceivedAmount, _sharesAmount, _assets, _amounts, _trackedAssets, _assetPrices, _assetDecimals ); } /// @notice redeem the funds from specified strategy. function redeem( address _strategy, uint256 _amount, uint256 _outputCode ) external isKeeper isActiveStrategy(_strategy) nonReentrant { uint256 _strategyAssetValue = strategies[_strategy].totalDebt; require(_amount <= _strategyAssetValue); (address[] memory _assets, uint256[] memory _amounts) = IStrategy(_strategy).repay( _amount, _strategyAssetValue, _outputCode ); if (adjustPositionPeriod) { uint256 _assetsLength = _assets.length; for (uint256 i = 0; i < _assetsLength; i++) { uint256 _amount = _amounts[i]; if (_amount > 0) { redeemAssetsMap[_assets[i]] += _amount; } } } uint256 _nowStrategyTotalDebt = strategies[_strategy].totalDebt; uint256 _thisWithdrawValue = (_nowStrategyTotalDebt * _amount) / _strategyAssetValue; strategies[_strategy].totalDebt = _nowStrategyTotalDebt - _thisWithdrawValue; totalDebt -= _thisWithdrawValue; emit Redeem(_strategy, _amount, _assets, _amounts); } /// @notice Allocate funds in Vault to strategies. function lend(address _strategyAddr, IExchangeAggregator.ExchangeToken[] calldata _exchangeTokens) external isKeeper whenNotEmergency isActiveStrategy(_strategyAddr) nonReentrant { ( address[] memory _wants, uint256[] memory _ratios, uint256[] memory _toAmounts ) = _checkAndExchange(_strategyAddr, _exchangeTokens); //Definition rule 0 means unconstrained, currencies that do not participate are not in the returned wants uint256 _minProductIndex = 0; bool _isWantRatioIgnorable = IStrategy(_strategyAddr).isWantRatioIgnorable(); if (!_isWantRatioIgnorable && _ratios.length > 1) { for (uint256 i = 1; i < _ratios.length; i++) { if (_ratios[i] == 0) { //0 is free continue; } else if (_ratios[_minProductIndex] == 0) { //minProductIndex is assigned to the first index whose proportion is not 0 _minProductIndex = i; } else if ( _toAmounts[_minProductIndex] * _ratios[i] > _toAmounts[i] * _ratios[_minProductIndex] ) { _minProductIndex = i; } } } uint256 _minAmount = _toAmounts[_minProductIndex]; uint256 _minAspect = _ratios[_minProductIndex]; uint256 _lendValue; for (uint256 i = 0; i < _toAmounts.length; i++) { uint256 _actualAmount = _toAmounts[i]; if (_actualAmount > 0) { address _want = _wants[i]; if (!_isWantRatioIgnorable && _ratios[i] > 0) { _actualAmount = (_ratios[i] * _minAmount) / _minAspect; _toAmounts[i] = _actualAmount; } _lendValue = _lendValue + IValueInterpreter(valueInterpreter).calcCanonicalAssetValueInUsd( _want, _actualAmount ); IERC20Upgradeable(_want).safeTransfer(_strategyAddr, _actualAmount); } } IStrategy _strategy = IStrategy(_strategyAddr); _strategy.borrow(_wants, _toAmounts); address[] memory _rewardTokens; uint256[] memory _claimAmounts; _report(_strategyAddr, _rewardTokens, _claimAmounts, _lendValue); emit LendToStrategy(_strategyAddr, _wants, _toAmounts, _lendValue); } function exchange( address _fromToken, address _toToken, uint256 _amount, IExchangeAggregator.ExchangeParam memory _exchangeParam ) external isKeeper nonReentrant returns (uint256) { return _exchange(_fromToken, _toToken, _amount, _exchangeParam); } /// @notice Change USDi supply with Vault total assets. function rebase() external whenNotEmergency whenNotAdjustPosition whenNotRebasePaused nonReentrant { uint256 _totalAssets = _totalValueInVault() + totalDebt; _rebase(_totalAssets); } function report(address[] memory _rewardTokens, uint256[] memory _claimAmounts) external isActiveStrategy(msg.sender) { _report(msg.sender, _rewardTokens, _claimAmounts, 0); } /// @notice start Adjust Position function startAdjustPosition() external isKeeper whenNotAdjustPosition whenNotEmergency nonReentrant { adjustPositionPeriod = true; address[] memory _trackedAssets = _getTrackedAssets(); ( uint256[] memory _vaultAmounts, uint256[] memory _transferAmounts, bool _vaultBufferAboveZero ) = _calculateVault(_trackedAssets, true); uint256 _totalDebt = totalDebt; if (_vaultBufferAboveZero) { uint256 _trackedAssetsLength = _trackedAssets.length; uint256[] memory _assetPrices = new uint256[](_trackedAssetsLength); uint256[] memory _assetDecimals = new uint256[](_trackedAssetsLength); uint256 _totalValueInVault = 0; for (uint256 i = 0; i < _trackedAssetsLength; i++) { address _trackedAsset = _trackedAssets[i]; uint256 _amount = _vaultAmounts[i]; if (_amount > 0) { _totalValueInVault = _totalValueInVault + _calculateAssetValue(_assetPrices, _assetDecimals, i, _trackedAsset, _amount); } } uint256 _totalAssets = _totalValueInVault + _totalDebt; uint256 _totalShares = IPegToken(pegTokenAddress).totalShares(); if (!rebasePaused) { _rebase(_totalAssets, _totalShares); } IVaultBuffer(vaultBufferAddress).transferCashToVault(_trackedAssets, _transferAmounts); } uint256 _totalDebtOfBeforeAdjustPosition = _totalDebt; totalDebtOfBeforeAdjustPosition = _totalDebtOfBeforeAdjustPosition; emit StartAdjustPosition( _totalDebtOfBeforeAdjustPosition, _trackedAssets, _vaultAmounts, _transferAmounts ); } /// @notice end Adjust Position function endAdjustPosition() external isKeeper nonReentrant { require(adjustPositionPeriod, "AD OVER"); address[] memory _trackedAssets = _getTrackedAssets(); uint256 _trackedAssetsLength = _trackedAssets.length; uint256[] memory _assetPrices = new uint256[](_trackedAssetsLength); uint256[] memory _assetDecimals = new uint256[](_trackedAssetsLength); (uint256[] memory _vaultAmounts, , ) = _calculateVault(_trackedAssets, false); uint256 _transferValue = 0; uint256 _redeemValue = 0; uint256 _vaultValueOfNow = 0; uint256 _vaultValueOfBefore = 0; for (uint256 i = 0; i < _trackedAssetsLength; i++) { address _trackedAsset = _trackedAssets[i]; _transferValue = _transferValue + _calculateAssetValue( _assetPrices, _assetDecimals, i, _trackedAsset, transferFromVaultBufferAssetsMap[_trackedAsset] ); _redeemValue = _redeemValue + _calculateAssetValue( _assetPrices, _assetDecimals, i, _trackedAsset, redeemAssetsMap[_trackedAsset] ); _vaultValueOfNow = _vaultValueOfNow + _calculateAssetValue(_assetPrices, _assetDecimals, i, _trackedAsset, _vaultAmounts[i]); _vaultValueOfBefore = _vaultValueOfBefore + _calculateAssetValue( _assetPrices, _assetDecimals, i, _trackedAsset, beforeAdjustPositionAssetsMap[_trackedAsset] ); } uint256 _totalDebtOfBefore = totalDebtOfBeforeAdjustPosition; uint256 _totalDebtOfNow = totalDebt; uint256 _totalValueOfNow = _totalDebtOfNow + _vaultValueOfNow; uint256 _totalValueOfBefore = _totalDebtOfBefore + _vaultValueOfBefore; { uint256 _transferAssets = 0; uint256 _old2LendAssets = 0; if (_vaultValueOfNow + _transferValue < _vaultValueOfBefore) { _old2LendAssets = _vaultValueOfBefore - _vaultValueOfNow - _transferValue; } if (_redeemValue + _old2LendAssets > _totalValueOfBefore - _transferValue) { _redeemValue = _totalValueOfBefore - _transferValue - _old2LendAssets; } if (_totalValueOfNow > _totalValueOfBefore) { uint256 _gain = _totalValueOfNow - _totalValueOfBefore; if (_transferValue > 0) { _transferAssets = _transferValue + (_gain * _transferValue) / (_transferValue + _redeemValue + _old2LendAssets); } } else { uint256 _loss = _totalValueOfBefore - _totalValueOfNow; if (_transferValue > 0) { _transferAssets = _transferValue - (_loss * _transferValue) / (_transferValue + _redeemValue + _old2LendAssets); } } uint256 _totalShares = IPegToken(pegTokenAddress).totalShares(); if (!rebasePaused) { _totalShares = _rebase(_totalValueOfNow - _transferAssets, _totalShares); } if (_transferAssets > 0) { uint256 _sharesAmount = _calculateShare( _transferAssets, _totalValueOfNow - _transferAssets, _totalShares ); if (_sharesAmount > 0) { IPegToken(pegTokenAddress).mintShares(vaultBufferAddress, _sharesAmount); } } } { totalDebtOfBeforeAdjustPosition = 0; for (uint256 i = 0; i < _trackedAssetsLength; i++) { address _trackedAsset = _trackedAssets[i]; redeemAssetsMap[_trackedAsset] = 0; beforeAdjustPositionAssetsMap[_trackedAsset] = 0; transferFromVaultBufferAssetsMap[_trackedAsset] = 0; } if (!IVaultBuffer(vaultBufferAddress).isDistributing()) { IVaultBuffer(vaultBufferAddress).openDistribute(); } adjustPositionPeriod = false; } emit EndAdjustPosition( _transferValue, _redeemValue, _totalDebtOfNow, _totalValueOfNow, _totalValueOfBefore ); } function _calculateVault(address[] memory _trackedAssets, bool _dealVaultBuffer) internal returns ( uint256[] memory, uint256[] memory, bool ) { uint256 _trackedAssetsLength = _trackedAssets.length; uint256[] memory _transferAmounts = new uint256[](_trackedAssetsLength); uint256[] memory _vaultAmounts = new uint256[](_trackedAssetsLength); bool _vaultBufferAboveZero = false; for (uint256 i = 0; i < _trackedAssetsLength; i++) { address _trackedAsset = _trackedAssets[i]; uint256 _balance = 0; if (_dealVaultBuffer && assetSet.contains(_trackedAsset)) { _balance = _balanceOfToken(_trackedAsset, vaultBufferAddress); if (_balance > 0) { _transferAmounts[i] = _balance; _vaultBufferAboveZero = true; transferFromVaultBufferAssetsMap[_trackedAsset] = _balance; } } uint256 _vaultAmount = _balanceOfToken(_trackedAsset, address(this)); if (_vaultAmount > 0) { _vaultAmounts[i] = _vaultAmount; } if (_dealVaultBuffer && _vaultAmount + _balance > 0) { beforeAdjustPositionAssetsMap[_trackedAsset] = _vaultAmount + _balance; } } return (_vaultAmounts, _transferAmounts, _vaultBufferAboveZero); } /// @notice Assets held by Vault function _getTrackedAssets() internal view returns (address[] memory) { return trackedAssetsMap._inner._keys.values(); } function _totalValueInVault() internal view returns (uint256) { address[] memory _trackedAssets = _getTrackedAssets(); uint256 _trackedAssetsLength = _trackedAssets.length; uint256[] memory _assetPrices = new uint256[](_trackedAssetsLength); uint256[] memory _assetDecimals = new uint256[](_trackedAssetsLength); uint256 _totalValueInVault = _totalValueInVault(_trackedAssets, _assetPrices, _assetDecimals); return _totalValueInVault; } function _totalValueInVault( address[] memory _trackedAssets, uint256[] memory _assetPrices, uint256[] memory _assetDecimals ) internal view returns (uint256) { uint256 _totalValueInVault; uint256 _trackedAssetsLength = _trackedAssets.length; for (uint256 i = 0; i < _trackedAssetsLength; i++) { address _trackedAsset = _trackedAssets[i]; uint256 _balance = _balanceOfToken(_trackedAsset, address(this)); if (_balance > 0) { _totalValueInVault = _totalValueInVault + _calculateAssetValue(_assetPrices, _assetDecimals, i, _trackedAsset, _balance); } } return _totalValueInVault; } function _totalAssetInVaultAndVaultBuffer() internal view returns (uint256) { address[] memory _trackedAssets = _getTrackedAssets(); uint256 _totalAssetInVaultAndVaultBuffer = 0; //price in vault for (uint256 i = 0; i < _trackedAssets.length; i++) { address _trackedAsset = _trackedAssets[i]; uint256 _assetBalancesInVault = _balanceOfToken(_trackedAsset, address(this)); uint256 _assetBalancesInVaultBuffer = _balanceOfToken(_trackedAsset, vaultBufferAddress); uint256 _balance = _assetBalancesInVault + _assetBalancesInVaultBuffer; if (_balance > 0) { uint256 _price = _priceUSD(_trackedAsset); uint256 _decimal = trackedAssetDecimalsMap[_trackedAsset]; uint256 _value = _balance.mulTruncateScale(_price, 10**_decimal); _totalAssetInVaultAndVaultBuffer = _totalAssetInVaultAndVaultBuffer + _value; } } return _totalAssetInVaultAndVaultBuffer; } function _estimateMint(address[] memory _assets, uint256[] memory _amounts) private view returns (uint256) { _checkMintAssets(_assets, _amounts); uint256 _mintAmount = 0; for (uint256 i = 0; i < _assets.length; i++) { address _asset = _assets[i]; uint256 _assetPrice = IValueInterpreter(valueInterpreter).price(_asset); uint256 _assetDecimal = trackedAssetDecimalsMap[_asset]; _mintAmount += _amounts[i].mulTruncateScale(_assetPrice, 10**_assetDecimal); } uint256 _minimumInvestmentAmount = minimumInvestmentAmount; if (_minimumInvestmentAmount > 0) { require( _mintAmount >= _minimumInvestmentAmount, "Amount must be gt minimum Investment Amount" ); } return _mintAmount; } /// @notice withdraw from strategy queue function _repayFromWithdrawQueue(uint256 _needWithdrawValue) internal { uint256 _totalWithdrawValue; for (uint256 i = 0; i < withdrawQueue.length; i++) { address _strategy = withdrawQueue[i]; if (_strategy == ZERO_ADDRESS) break; uint256 _strategyTotalValue = strategies[_strategy].totalDebt; if (_strategyTotalValue <= 0) { continue; } uint256 _strategyWithdrawValue; if (_needWithdrawValue > _strategyTotalValue) { _strategyWithdrawValue = _strategyTotalValue; _needWithdrawValue -= _strategyWithdrawValue; } else { //If there is less than 1u left, then all redemption if (_needWithdrawValue + 1e18 >= _strategyTotalValue) { _strategyWithdrawValue = _strategyTotalValue; } else { _strategyWithdrawValue = _needWithdrawValue; } _needWithdrawValue = 0; } (address[] memory _assets, uint256[] memory _amounts) = IStrategy(_strategy).repay( _strategyWithdrawValue, _strategyTotalValue, 0 ); emit RepayFromStrategy( _strategy, _strategyWithdrawValue, _strategyTotalValue, _assets, _amounts ); uint256 _nowStrategyTotalDebt = strategies[_strategy].totalDebt; uint256 _thisWithdrawValue = (_nowStrategyTotalDebt * _strategyWithdrawValue) / _strategyTotalValue; strategies[_strategy].totalDebt = _nowStrategyTotalDebt - _thisWithdrawValue; _totalWithdrawValue += _thisWithdrawValue; if (_needWithdrawValue <= 0) { break; } } totalDebt -= _totalWithdrawValue; } /// @notice withdraw from vault buffer function _repayFromVaultBuffer( uint256 _needTransferValue, address[] memory _trackedAssets, uint256[] memory _assetPrices, uint256[] memory _assetDecimals, uint256 _totalAssets, uint256 _totalShares ) internal returns (uint256) { address[] memory _transferAssets = _trackedAssets; uint256 _transferAssetsLength = _transferAssets.length; uint256[] memory _amounts = new uint256[](_transferAssetsLength); uint256 _totalTransferValue; //price in vault for (uint256 i = 0; i < _transferAssetsLength; i++) { address _trackedAsset = _transferAssets[i]; if (assetSet.contains(_trackedAsset)) { uint256 _assetBalancesInVaultBuffer = _balanceOfToken(_trackedAsset, vaultBufferAddress); if (_assetBalancesInVaultBuffer > 0) { uint256 _value = _calculateAssetValue( _assetPrices, _assetDecimals, i, _trackedAsset, _assetBalancesInVaultBuffer ); if (_needTransferValue > _value) { _totalTransferValue = _totalTransferValue + _value; _needTransferValue = _needTransferValue - _value; _amounts[i] = _assetBalancesInVaultBuffer; } else { _totalTransferValue = _totalTransferValue + _needTransferValue; _amounts[i] = (_assetBalancesInVaultBuffer * _needTransferValue) / _value; _needTransferValue = 0; break; } } } } if (_totalTransferValue > 0) { IVaultBuffer(vaultBufferAddress).transferCashToVault(_transferAssets, _amounts); uint256 _totalTransferShares = _calculateShare( _totalTransferValue, _totalAssets, _totalShares ); IPegToken(pegTokenAddress).mintShares(vaultBufferAddress, _totalTransferShares); emit PegTokenSwapCash(_totalTransferValue, _transferAssets, _amounts); } return _totalTransferValue; } function _calculateShare( uint256 _amount, uint256 _totalAssets, uint256 _totalShares ) internal view returns (uint256) { uint256 _shareAmount = 0; if (_totalAssets > 0 && _totalShares > 0) { _shareAmount = (_amount * _totalShares) / _totalAssets; } if (_shareAmount == 0) { uint256 _underlyingUnitsPerShare = underlyingUnitsPerShare; if (_underlyingUnitsPerShare > 0) { _shareAmount = _amount.divPreciselyScale(_underlyingUnitsPerShare, 1e27); } else { _shareAmount = _amount * 1e9; } } return _shareAmount; } /// @notice calculate need transfer amount from vault ,set to outputs function _calculateOutputs( uint256 _needTransferAmount, address[] memory _trackedAssets, uint256[] memory _assetPrices, uint256[] memory _assetDecimals ) internal view returns (uint256[] memory) { uint256 _trackedAssetsLength = _trackedAssets.length; uint256[] memory _outputs = new uint256[](_trackedAssetsLength); for (uint256 i = 0; i < _trackedAssetsLength; i++) { address _trackedAsset = _trackedAssets[i]; uint256 _balance = _balanceOfToken(_trackedAsset, address(this)); if (_balance > 0) { uint256 _value = _calculateAssetValue( _assetPrices, _assetDecimals, i, _trackedAsset, _balance ); if (_value >= _needTransferAmount) { _outputs[i] = (_balance * _needTransferAmount) / _value; break; } else { _outputs[i] = _balance; _needTransferAmount = _needTransferAmount - _value; } } } return _outputs; } /// @notice calculate Asset value in usd by oracle price /// @param _assetPrices array of asset price /// @param _assetDecimals array of asset decimal /// @param _assetIndex index of the asset in trackedAssets array /// @param _trackedAsset address of the asset /// @return shareAmount function _calculateAssetValue( uint256[] memory _assetPrices, uint256[] memory _assetDecimals, uint256 _assetIndex, address _trackedAsset, uint256 _balance ) private view returns (uint256) { uint256 _assetPrice = _getAssetPrice(_assetPrices, _assetIndex, _trackedAsset); uint256 _assetDecimal = _getAssetDecimals(_assetDecimals, _assetIndex, _trackedAsset); uint256 _value = _balance.mulTruncateScale(_assetPrice, 10**_assetDecimal); return _value; } // @notice without exchange token and transfer form vault to user function _transfer( uint256[] memory _outputs, address[] memory _trackedAssets, uint256[] memory _assetPrices, uint256[] memory _assetDecimals ) internal returns (uint256) { uint256 _actualAmount; uint256 _trackedAssetsLength = _trackedAssets.length; for (uint256 i = 0; i < _trackedAssetsLength; i++) { uint256 _amount = _outputs[i]; if (_amount > 0) { address _trackedAsset = _trackedAssets[i]; uint256 _value = _calculateAssetValue( _assetPrices, _assetDecimals, i, _trackedAsset, _amount ); _actualAmount = _actualAmount + _value; IERC20Upgradeable(_trackedAsset).safeTransfer(msg.sender, _amount); } } return _actualAmount; } function _repayToVault( uint256 _amount, uint256 _accountBalance, address[] memory _trackedAssets, uint256[] memory _assetPrices, uint256[] memory _assetDecimals ) internal returns (uint256 _sharesAmount, uint256 _actualAsset) { uint256 _totalAssetInVault = _totalValueInVault(_trackedAssets, _assetPrices, _assetDecimals); uint256 _actualAmount = _amount; uint256 _currentTotalAssets = _totalAssetInVault + totalDebt; uint256 _currentTotalShares = IPegToken(pegTokenAddress).totalShares(); { uint256 _underlyingUnitsPerShare = underlyingUnitsPerShare; if (_accountBalance == _actualAmount) { _sharesAmount = IPegToken(pegTokenAddress).sharesOf(msg.sender); } else { _sharesAmount = _actualAmount.divPreciselyScale(_underlyingUnitsPerShare, 1e27); } // Calculate redeem fee if (redeemFeeBps > 0) { _actualAmount = _actualAmount - (_actualAmount * redeemFeeBps) / MAX_BPS; } uint256 _currentTotalSupply = _currentTotalShares.mulTruncateScale( _underlyingUnitsPerShare, 1e27 ); _actualAsset = (_actualAmount * _currentTotalAssets) / _currentTotalSupply; } // vault not enough,withdraw from vault buffer if (_totalAssetInVault < _actualAsset) { _totalAssetInVault = _totalAssetInVault + _repayFromVaultBuffer( _actualAsset - _totalAssetInVault, _trackedAssets, _assetPrices, _assetDecimals, _currentTotalAssets, _currentTotalShares ); } // vault not enough,withdraw from withdraw queue strategy if (_totalAssetInVault < _actualAsset) { _repayFromWithdrawQueue(_actualAsset - _totalAssetInVault); } } function _calculateAndTransfer( uint256 _actualAsset, address[] memory _trackedAssets, uint256[] memory _assetPrices, uint256[] memory _assetDecimals ) internal returns ( address[] memory, uint256[] memory, uint256 ) { // calculate need transfer amount from vault ,set to outputs uint256[] memory _outputs = _calculateOutputs( _actualAsset, _trackedAssets, _assetPrices, _assetDecimals ); uint256 _actuallyReceivedAmount = _transfer( _outputs, _trackedAssets, _assetPrices, _assetDecimals ); return (_trackedAssets, _outputs, _actuallyReceivedAmount); } // @notice burn usdi and check rebase function _burnRebaseAndEmit( uint256 _amount, uint256 _actualAmount, uint256 _shareAmount, address[] memory _assets, uint256[] memory _amounts, address[] memory _trackedAssets, uint256[] memory _assetPrices, uint256[] memory _assetDecimals ) internal { IPegToken(pegTokenAddress).burnShares(msg.sender, _shareAmount); // Until we can prove that we won't affect the prices of our assets // by withdrawing them, this should be here. // It's possible that a strategy was off on its asset total, perhaps // a reward token sold for more or for less than anticipated. if (!rebasePaused) { uint256 _totalValueInVault = _totalValueInVault(_trackedAssets, _assetPrices, _assetDecimals); _rebase(_totalValueInVault + totalDebt); } emit Burn(msg.sender, _amount, _actualAmount, _shareAmount, _assets, _amounts); } /** * @dev Calculate the total value of assets held by the Vault and all * strategies and update the supply of USDI, optionally sending a * portion of the yield to the trustee. */ function _rebase(uint256 _totalAssets) internal { uint256 _totalShares = IPegToken(pegTokenAddress).totalShares(); _rebase(_totalAssets, _totalShares); } function _rebase(uint256 _totalAssets, uint256 _totalShares) internal returns (uint256) { if (_totalShares == 0) { return _totalShares; } uint256 _underlyingUnitsPerShare = underlyingUnitsPerShare; uint256 _totalSupply = _totalShares.mulTruncateScale(_underlyingUnitsPerShare, 1e27); // Final check should use latest value if ( _totalAssets > _totalSupply && (_totalAssets - _totalSupply) * TEN_MILLION_BPS > _totalSupply * rebaseThreshold ) { // Yield fee collection address _treasuryAddress = treasury; uint256 _trusteeFeeBps = trusteeFeeBps; if (_trusteeFeeBps > 0 && _treasuryAddress != address(0)) { uint256 _yield = _totalAssets - _totalSupply; uint256 _fee = (_yield * _trusteeFeeBps) / MAX_BPS; require(_yield > _fee, "Fee must not be greater than yield"); if (_fee > 0) { uint256 _sharesAmount = (_fee * _totalShares) / (_totalAssets - _fee); if (_sharesAmount > 0) { IPegToken(pegTokenAddress).mintShares(_treasuryAddress, _sharesAmount); _totalShares = _totalShares + _sharesAmount; } } } uint256 _newUnderlyingUnitsPerShare = _totalAssets.divPreciselyScale(_totalShares, 1e27); if (_newUnderlyingUnitsPerShare != _underlyingUnitsPerShare) { underlyingUnitsPerShare = _newUnderlyingUnitsPerShare; emit Rebase(_totalShares, _totalAssets, _newUnderlyingUnitsPerShare); } } return _totalShares; } /// @notice check valid and exchange to want token function _checkAndExchange( address _strategy, IExchangeAggregator.ExchangeToken[] calldata _exchangeTokens ) internal returns ( address[] memory _wants, uint256[] memory _ratios, uint256[] memory toAmounts ) { (_wants, _ratios) = IStrategy(_strategy).getWantsInfo(); uint256 _wantsLength = _wants.length; toAmounts = new uint256[](_wantsLength); uint256 _exchangeTokensLength = _exchangeTokens.length; for (uint256 i = 0; i < _exchangeTokensLength; i++) { bool _findToToken = false; for (uint256 j = 0; j < _wantsLength; j++) { if (_exchangeTokens[i].toToken == _wants[j]) { _findToToken = true; break; } } require(_findToToken, "toToken invalid"); } for (uint256 j = 0; j < _wantsLength; j++) { for (uint256 i = 0; i < _exchangeTokensLength; i++) { IExchangeAggregator.ExchangeToken memory _exchangeToken = _exchangeTokens[i]; // not strategy need token,skip if (_wants[j] != _exchangeToken.toToken) continue; uint256 _toAmount; if (_exchangeToken.fromToken == _exchangeToken.toToken) { _toAmount = _exchangeToken.fromAmount; } else { if (_exchangeToken.fromAmount > 0) { _toAmount = _exchange( _exchangeToken.fromToken, _exchangeToken.toToken, _exchangeToken.fromAmount, _exchangeToken.exchangeParam ); } } toAmounts[j] = _toAmount; break; } } } function _exchange( address _fromToken, address _toToken, uint256 _amount, IExchangeAggregator.ExchangeParam memory _exchangeParam ) internal returns (uint256 _exchangeAmount) { require(trackedAssetsMap.contains(_toToken), "!T"); IExchangeAdapter.SwapDescription memory _swapDescription = IExchangeAdapter.SwapDescription({ amount: _amount, srcToken: _fromToken, dstToken: _toToken, receiver: address(this) }); IERC20Upgradeable(_fromToken).safeApprove(exchangeManager, 0); IERC20Upgradeable(_fromToken).safeApprove(exchangeManager, _amount); _exchangeAmount = IExchangeAggregator(exchangeManager).swap( _exchangeParam.platform, _exchangeParam.method, _exchangeParam.encodeExchangeArgs, _swapDescription ); uint256 oracleExpectedAmount = IValueInterpreter(valueInterpreter).calcCanonicalAssetValue( _fromToken, _amount, _toToken ); require( _exchangeAmount >= (oracleExpectedAmount * (MAX_BPS - _exchangeParam.slippage - _exchangeParam.oracleAdditionalSlippage)) / MAX_BPS, "OL" ); emit Exchange(_exchangeParam.platform, _fromToken, _amount, _toToken, _exchangeAmount); } function _report( address _strategy, address[] memory _rewardTokens, uint256[] memory _claimAmounts, uint256 _lendValue ) private { StrategyParams memory _strategyParam = strategies[_strategy]; uint256 _lastStrategyTotalDebt = _strategyParam.totalDebt + _lendValue; uint256 _nowStrategyTotalDebt = IStrategy(_strategy).estimatedTotalAssets(); uint256 _gain = 0; uint256 _loss = 0; if (_nowStrategyTotalDebt > _lastStrategyTotalDebt) { _gain = _nowStrategyTotalDebt - _lastStrategyTotalDebt; } else if (_nowStrategyTotalDebt < _lastStrategyTotalDebt) { _loss = _lastStrategyTotalDebt - _nowStrategyTotalDebt; } if (_strategyParam.enforceChangeLimit) { if ( block.timestamp - strategies[_strategy].lastReport < maxTimestampBetweenTwoReported && (_lastStrategyTotalDebt > minCheckedStrategyTotalDebt || _nowStrategyTotalDebt > minCheckedStrategyTotalDebt) ) { if (_gain > 0) { require( _gain <= ((_lastStrategyTotalDebt * _strategyParam.profitLimitRatio) / MAX_BPS), "GL" ); } else if (_loss > 0) { require( _loss <= ((_lastStrategyTotalDebt * _strategyParam.lossLimitRatio) / MAX_BPS), "LL" ); } } } else { strategies[_strategy].enforceChangeLimit = true; // The check is turned off only once and turned back on. } strategies[_strategy].totalDebt = _nowStrategyTotalDebt; totalDebt = totalDebt + _nowStrategyTotalDebt + _lendValue - _lastStrategyTotalDebt; strategies[_strategy].lastReport = block.timestamp; uint256 _type = 0; if (_lendValue > 0) { _type = 1; } emit StrategyReported( _strategy, _gain, _loss, _lastStrategyTotalDebt, _nowStrategyTotalDebt, _rewardTokens, _claimAmounts, _type ); } function _balanceOfToken(address _trackedAsset, address _owner) internal view returns (uint256) { return IERC20Upgradeable(_trackedAsset).balanceOf(_owner); } /** * @notice Get the supported asset Decimal * @return _assetDecimal asset Decimals */ function _getAssetDecimals( uint256[] memory _assetDecimals, uint256 _assetIndex, address _asset ) internal view returns (uint256) { uint256 _decimal = _assetDecimals[_assetIndex]; if (_decimal == 0) { _decimal = trackedAssetDecimalsMap[_asset]; _assetDecimals[_assetIndex] = _decimal; } return _decimal; } /** * @notice Get an array of the supported asset prices in USD * @return prices in USD (1e18) */ function _getAssetPrice( uint256[] memory _assetPrices, uint256 _assetIndex, address _asset ) internal view returns (uint256) { uint256 _price = _assetPrices[_assetIndex]; if (_price == 0) { _price = _priceUSD(_asset); _assetPrices[_assetIndex] = _price; } return _price; } /** * @dev Returns the total price in 18 digit USD for a given asset * @param _asset Address of the asset * @return _price USD price of 1 of the asset, in 18 decimal fixed */ function _priceUSD(address _asset) internal view returns (uint256 _price) { _price = IValueInterpreter(valueInterpreter).price(_asset); } function _checkMintAssets(address[] memory _assets, uint256[] memory _amounts) private view { require(!(IVaultBuffer(vaultBufferAddress).isDistributing()), "is distributing"); uint256 _assetsLength = _assets.length; uint256 _amountsLength = _amounts.length; require( _assetsLength > 0 && _assetsLength == _amountsLength, "Assets and amounts must be equal in length and not empty" ); for (uint256 i = 0; i < _assetsLength; i++) { checkIsSupportAsset(_assets[i]); require(_amounts[i] > 0, "Amount must be gt 0"); } } /** * @dev Falldown to the admin implementation * @notice This is a catch all for all functions not declared in core */ fallback() external payable { bytes32 _slot = ADMIN_IMPL_POSITION; assembly { // Copy msg.data. We take full control of memory in this inline assembly // block because it will not return to Solidity code. We overwrite the // Solidity scratch pad at memory position 0. calldatacopy(0, 0, calldatasize()) // Call the implementation. // out and outsize are 0 because we don't know the size yet. let result := delegatecall(gas(), sload(_slot), 0, calldatasize(), 0, 0) // Copy the returned data. returndatacopy(0, 0, returndatasize()) switch result // delegatecall returns 0 on error. case 0 { revert(0, returndatasize()) } default { return(0, returndatasize()) } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; import "../IERC20Upgradeable.sol"; import "../../../utils/AddressUpgradeable.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20Upgradeable { using AddressUpgradeable for address; function safeTransfer( IERC20Upgradeable token, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom( IERC20Upgradeable token, address from, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove( IERC20Upgradeable token, address spender, uint256 value ) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance( IERC20Upgradeable token, address spender, uint256 value ) internal { uint256 newAllowance = token.allowance(address(this), spender) + value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance( IERC20Upgradeable token, address spender, uint256 value ) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); uint256 newAllowance = oldAllowance - value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20Upgradeable token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/math/Math.sol) pragma solidity ^0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { enum Rounding { Down, // Toward negative infinity Up, // Toward infinity Zero // Toward zero } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a >= b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds up instead * of rounding down. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) * with further edits by Uniswap Labs also under MIT license. */ function mulDiv( uint256 x, uint256 y, uint256 denominator ) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. require(denominator > prod1); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1. // See https://cs.stackexchange.com/q/138556/92363. // Does not overflow because the denominator cannot be zero at this stage in the function. uint256 twos = denominator & (~denominator + 1); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works // in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv( uint256 x, uint256 y, uint256 denominator, Rounding rounding ) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. It the number is not a perfect square, the value is rounded down. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. // We also know that `k`, the position of the most significant bit, is such that `msb(a) = 2**k`. // This gives `2**k < a <= 2**(k+1)` → `2**(k/2) <= sqrt(a) < 2 ** (k/2+1)`. // Using an algorithm similar to the msb conmputation, we are able to compute `result = 2**(k/2)` which is a // good first aproximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1; uint256 x = a; if (x >> 128 > 0) { x >>= 128; result <<= 64; } if (x >> 64 > 0) { x >>= 64; result <<= 32; } if (x >> 32 > 0) { x >>= 32; result <<= 16; } if (x >> 16 > 0) { x >>= 16; result <<= 8; } if (x >> 8 > 0) { x >>= 8; result <<= 4; } if (x >> 4 > 0) { x >>= 4; result <<= 2; } if (x >> 2 > 0) { result <<= 1; } // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { uint256 result = sqrt(a); if (rounding == Rounding.Up && result * result < a) { result += 1; } return result; } }
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity ^0.8.0; import "../access-control/AccessControlMixin.sol"; import "../library/IterableIntMap.sol"; import "../library/StableMath.sol"; import "../token/IPegToken.sol"; import "./IVaultBuffer.sol"; import "../library/BocRoles.sol"; import "../strategy/IStrategy.sol"; import "../price-feeds/IValueInterpreter.sol"; import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol"; import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; contract VaultStorage is Initializable, ReentrancyGuardUpgradeable, AccessControlMixin { using StableMath for uint256; using EnumerableSet for EnumerableSet.AddressSet; using IterableIntMap for IterableIntMap.AddressToIntMap; /// @param lastReport The last report timestamp /// @param totalDebt The total asset of this strategy /// @param profitLimitRatio The limited ratio of profit /// @param lossLimitRatio The limited ratio for loss /// @param enforceChangeLimit The switch of enforce change Limit struct StrategyParams { uint256 lastReport; uint256 totalDebt; uint256 profitLimitRatio; uint256 lossLimitRatio; bool enforceChangeLimit; } /// @param strategy The new strategy to add /// @param profitLimitRatio The limited ratio of profit /// @param lossLimitRatio The limited ratio for loss struct StrategyAdd { address strategy; uint256 profitLimitRatio; uint256 lossLimitRatio; } event AddAsset(address _asset); event RemoveAsset(address _asset); event AddStrategies(address[] _strategies); event RemoveStrategies(address[] _strategies); event RemoveStrategyByForce(address _strategy); event Mint(address _account, address[] _assets, uint256[] _amounts, uint256 _mintAmount); event Burn( address _account, uint256 _amount, uint256 _actualAmount, uint256 _shareAmount, address[] _assets, uint256[] _amounts ); event Exchange( address _platform, address _srcAsset, uint256 _srcAmount, address _distAsset, uint256 _distAmount ); event Redeem(address _strategy, uint256 _debtChangeAmount, address[] _assets, uint256[] _amounts); event LendToStrategy( address indexed _strategy, address[] _wants, uint256[] _amounts, uint256 _lendValue ); event RepayFromStrategy( address indexed _strategy, uint256 _strategyWithdrawValue, uint256 _strategyTotalValue, address[] _assets, uint256[] _amounts ); event StrategyReported( address indexed _strategy, uint256 _gain, uint256 _loss, uint256 _lastStrategyTotalDebt, uint256 _nowStrategyTotalDebt, address[] _rewardTokens, uint256[] _claimAmounts, uint256 _type ); event RemoveStrategyFromQueue(address[] _strategies); event SetEmergencyShutdown(bool _shutdown); event RebasePaused(); event RebaseUnpaused(); event RebaseThresholdUpdated(uint256 _threshold); event TrusteeFeeBpsChanged(uint256 _basis); event MaxTimestampBetweenTwoReportedChanged(uint256 _maxTimestampBetweenTwoReported); event MinCheckedStrategyTotalDebtChanged(uint256 _minCheckedStrategyTotalDebt); event MinimumInvestmentAmountChanged(uint256 _minimumInvestmentAmount); event TreasuryAddressChanged(address _address); event ExchangeManagerAddressChanged(address _address); event SetAdjustPositionPeriod(bool _adjustPositionPeriod); event RedeemFeeUpdated(uint256 _redeemFeeBps); event SetWithdrawalQueue(address[] _queues); event Rebase(uint256 _totalShares, uint256 _totalValue, uint256 _newUnderlyingUnitsPerShare); event StartAdjustPosition( uint256 _totalDebtOfBeforeAdjustPosition, address[] _trackedAssets, uint256[] _vaultCashDetatil, uint256[] _vaultBufferCashDetail ); event EndAdjustPosition( uint256 _transferValue, uint256 _redeemValue, uint256 _totalDebt, uint256 _totalValueOfAfterAdjustPosition, uint256 _totalValueOfBeforeAdjustPosition ); event PegTokenSwapCash(uint256 _pegTokenAmount, address[] _assets, uint256[] _amounts); address internal constant ZERO_ADDRESS = address(0); //max percentage 100% uint256 internal constant MAX_BPS = 10000; // all strategy EnumerableSet.AddressSet internal strategySet; // Assets supported by the Vault, i.e. Stablecoins EnumerableSet.AddressSet internal assetSet; // Assets held by Vault IterableIntMap.AddressToIntMap internal trackedAssetsMap; // Decimals of the assets held by Vault mapping(address => uint256) internal trackedAssetDecimalsMap; //adjust Position Period bool public adjustPositionPeriod; // emergency shutdown bool public emergencyShutdown; // Pausing bools bool public rebasePaused; // over this difference ratio automatically rebase. rebaseThreshold is the numerator and the denominator is 10000000 x/10000000. uint256 public rebaseThreshold; // Deprecated uint256 public maxSupplyDiff; // Amount of yield collected in basis points uint256 public trusteeFeeBps; // Redemption fee in basis points uint256 public redeemFeeBps; //all strategy asset uint256 public totalDebt; // treasury contract that can collect a percentage of yield address public treasury; //valueInterpreter address public valueInterpreter; //exchangeManager address public exchangeManager; // strategy info mapping(address => StrategyParams) public strategies; //withdraw strategy set address[] public withdrawQueue; //keccak256("USDi.vault.governor.admin.impl"); bytes32 internal constant ADMIN_IMPL_POSITION = 0x3d78d3961e16fde088e2e26c1cfa163f5f8bb870709088dd68c87eb4091137e2; //vault Buffer Address address public vaultBufferAddress; // usdi PegToken address address public pegTokenAddress; // Assets held in Vault from vault buffer mapping(address => uint256) internal transferFromVaultBufferAssetsMap; // redeem Assets where ad mapping(address => uint256) internal redeemAssetsMap; // Assets held in Vault and buffer before Adjust Position mapping(address => uint256) internal beforeAdjustPositionAssetsMap; // totalDebt before Adjust Position uint256 internal totalDebtOfBeforeAdjustPosition; // totalAsset/totalShare uint256 public underlyingUnitsPerShare; //Maximum timestamp between two reported uint256 public maxTimestampBetweenTwoReported; //Minimum strategy total debt that will be checked for the strategy reporting uint256 public minCheckedStrategyTotalDebt; //Minimum investment amount uint256 public minimumInvestmentAmount; //max percentage 10000000/10000000 uint256 internal constant TEN_MILLION_BPS = 10000000; /** * @dev set the implementation for the admin, this needs to be in a base class else we cannot set it * @param _newImpl address of the implementation */ function setAdminImpl(address _newImpl) external onlyGovOrDelegate { require(AddressUpgradeable.isContract(_newImpl), "new implementation is not a contract"); bytes32 _position = ADMIN_IMPL_POSITION; assembly { sstore(_position, _newImpl) } } }
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity ^0.8.0; import "./IExchangeAdapter.sol"; interface IExchangeAggregator { /** * @param platform Called exchange platforms * @param method The method of the exchange platform * @param encodeExchangeArgs The encoded parameters to call * @param slippage The slippage when exchange * @param oracleAdditionalSlippage The additional slippage for oracle estimated */ struct ExchangeParam { address platform; uint8 method; bytes encodeExchangeArgs; uint256 slippage; uint256 oracleAdditionalSlippage; } /** * @param platform Called exchange platforms * @param method The method of the exchange platform * @param data The encoded parameters to call * @param swapDescription swap info */ struct SwapParam { address platform; uint8 method; bytes data; IExchangeAdapter.SwapDescription swapDescription; } /** * @param srcToken The token swap from * @param dstToken The token swap to * @param amount The amount to swap * @param exchangeParam The struct of ExchangeParam */ struct ExchangeToken { address fromToken; address toToken; uint256 fromAmount; ExchangeParam exchangeParam; } event ExchangeAdapterAdded(address[] _exchangeAdapters); event ExchangeAdapterRemoved(address[] _exchangeAdapters); event Swap( address _platform, uint256 _amount, address _srcToken, address _dstToken, uint256 _exchangeAmount, address indexed _receiver, address _sender ); function swap( address _platform, uint8 _method, bytes calldata _data, IExchangeAdapter.SwapDescription calldata _sd ) external payable returns (uint256); function batchSwap(SwapParam[] calldata _swapParams) external payable returns (uint256[] memory); function getExchangeAdapters() external view returns (address[] memory _exchangeAdapters, string[] memory _identifiers); function addExchangeAdapters(address[] calldata _exchangeAdapters) external; function removeExchangeAdapters(address[] calldata _exchangeAdapters) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20Upgradeable { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 amount ) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library AddressUpgradeable { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity >=0.6.0 <0.9.0; import "./IAccessControlProxy.sol"; abstract contract AccessControlMixin { IAccessControlProxy public accessControlProxy; function _initAccessControl(address _accessControlProxy) internal { accessControlProxy = IAccessControlProxy(_accessControlProxy); } modifier hasRole(bytes32 _role, address _account) { accessControlProxy.checkRole(_role, _account); _; } modifier onlyRole(bytes32 _role) { accessControlProxy.checkRole(_role, msg.sender); _; } modifier onlyGovOrDelegate() { accessControlProxy.checkGovOrDelegate(msg.sender); _; } modifier isVaultManager() { accessControlProxy.checkVaultOrGov(msg.sender); _; } modifier isKeeper() { accessControlProxy.checkKeeperOrVaultOrGov(msg.sender); _; } }
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity ^0.8.0; import '@openzeppelin/contracts/utils/structs/EnumerableSet.sol'; library IterableIntMap { using EnumerableSet for EnumerableSet.AddressSet; struct Map { // Storage of keys EnumerableSet.AddressSet _keys; mapping (address => int256) _values; } /** * @dev Adds a key-value pair to a map, or updates the value for an existing * key. O(1). * * Returns true if the key was added to the map, that is if it was not * already present. */ function _set(Map storage map, address key, int256 value) private returns (bool) { map._values[key] = value; return map._keys.add(key); } /** * @dev plus a key‘s value pair in a map * key. O(1). * * Returns true if the key was added to the map, that is if it was not * already present. */ function _plus(Map storage map, address key, int256 value) private { map._values[key] += value; map._keys.add(key); } /** * @dev minus a key‘s value pair in a map * key. O(1). * * Returns true if the key was added to the map, that is if it was not * already present. */ function _minus(Map storage map, address key, int256 value) private { map._values[key] -= value; map._keys.add(key); } /** * @dev Removes a key-value pair from a map. O(1). * * Returns true if the key was removed from the map, that is if it was present. */ function _remove(Map storage map, address key) private returns (bool) { delete map._values[key]; return map._keys.remove(key); } /** * @dev Returns true if the key is in the map. O(1). */ function _contains(Map storage map, address key) private view returns (bool) { return map._keys.contains(key); } /** * @dev Returns the number of key-value pairs in the map. O(1). */ function _length(Map storage map) private view returns (uint256) { return map._keys.length(); } /** * @dev Returns the key-value pair stored at position `index` in the map. O(1). * * Note that there are no guarantees on the ordering of entries inside the * array, and it may change when more entries are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function _at(Map storage map, uint256 index) private view returns (address, int256) { address key = map._keys.at(index); return (key, map._values[key]); } /** * @dev Returns the value associated with `key`. O(1). * * Requirements: * * - `key` must be in the map. */ function _get(Map storage map, address key) private view returns (int256) { int256 value = map._values[key]; return value; } struct AddressToIntMap { Map _inner; } /** * @dev Adds a key-value pair to a map, or updates the value for an existing * key. O(1). * * Returns true if the key was added to the map, that is if it was not * already present. */ function set(AddressToIntMap storage map, address key, int256 value) internal returns (bool) { return _set(map._inner, key, value); } /** * @dev plus a key‘s value pair in a map * key. O(1). * * Returns true if the key was added to the map, that is if it was not * already present. */ function plus(AddressToIntMap storage map, address key, int256 value) internal { return _plus(map._inner, key, value); } /** * @dev minus a key‘s value pair in a map * key. O(1). * * Returns true if the key was added to the map, that is if it was not * already present. */ function minus(AddressToIntMap storage map, address key, int256 value) internal { return _minus(map._inner, key, value); } /** * @dev Removes a value from a set. O(1). * * Returns true if the key was removed from the map, that is if it was present. */ function remove(AddressToIntMap storage map, address key) internal returns (bool) { return _remove(map._inner, key); } /** * @dev Returns true if the key is in the map. O(1). */ function contains(AddressToIntMap storage map, address key) internal view returns (bool) { return _contains(map._inner, key); } /** * @dev Returns the number of elements in the map. O(1). */ function length(AddressToIntMap storage map) internal view returns (uint256) { return _length(map._inner); } /** * @dev Returns the element stored at position `index` in the set. O(1). * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(AddressToIntMap storage map, uint256 index) internal view returns (address, int256) { return _at(map._inner, index); } /** * @dev Returns the value associated with `key`. O(1). * * Requirements: * * - `key` must be in the map. */ function get(AddressToIntMap storage map, address key) internal view returns (int256) { return _get(map._inner, key); } }
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity ^0.8.0; import {SafeMath} from "@openzeppelin/contracts/utils/math/SafeMath.sol"; // Based on StableMath from Stability Labs Pty. Ltd. // https://github.com/mstable/mStable-contracts/blob/master/contracts/shared/StableMath.sol library StableMath { /** * @dev Scaling unit for use in specific calculations, * where 1 * 10**18, or 1e18 represents a unit '1' */ uint256 private constant FULL_SCALE = 1e18; /*************************************** Helpers ****************************************/ /** * @dev Adjust the scale of an integer * @param to Decimals to scale to * @param from Decimals to scale from */ function scaleBy( uint256 x, uint256 to, uint256 from ) internal pure returns (uint256) { if (to > from) { x = x * (10 ** (to - from)); } else if (to < from) { x = x / (10 ** (from - to)); } return x; } /*************************************** Precise Arithmetic ****************************************/ /** * @dev Multiplies two precise units, and then truncates by the full scale * @param x Left hand input to multiplication * @param y Right hand input to multiplication * @return Result after multiplying the two inputs and then dividing by the shared * scale unit */ function mulTruncate(uint256 x, uint256 y) internal pure returns (uint256) { return mulTruncateScale(x, y, FULL_SCALE); } /** * @dev Multiplies two precise units, and then truncates by the given scale. For example, * when calculating 90% of 10e18, (10e18 * 9e17) / 1e18 = (9e36) / 1e18 = 9e18 * @param x Left hand input to multiplication * @param y Right hand input to multiplication * @param scale Scale unit * @return Result after multiplying the two inputs and then dividing by the shared * scale unit */ function mulTruncateScale( uint256 x, uint256 y, uint256 scale ) internal pure returns (uint256) { // e.g. assume scale = fullScale // z = 10e18 * 9e17 = 9e36 uint256 z = x * y; // return 9e36 / 1e18 = 9e18 return z / scale; } /** * @dev Multiplies two precise units, and then truncates by the full scale, rounding up the result * @param x Left hand input to multiplication * @param y Right hand input to multiplication * @return Result after multiplying the two inputs and then dividing by the shared * scale unit, rounded up to the closest base unit. */ function mulTruncateCeil(uint256 x, uint256 y) internal pure returns (uint256) { // e.g. 8e17 * 17268172638 = 138145381104e17 uint256 scaled = x * y; // e.g. 138145381104e17 + 9.99...e17 = 138145381113.99...e17 uint256 ceil = scaled + (FULL_SCALE - 1); // e.g. 13814538111.399...e18 / 1e18 = 13814538111 return ceil / FULL_SCALE; } /** * @dev Precisely divides two units, by first scaling the left hand operand. Useful * for finding percentage weightings, i.e. 8e18/10e18 = 80% (or 8e17) * @param x Left hand input to division * @param y Right hand input to division * @return Result after multiplying the left operand by the scale, and * executing the division on the right hand input. */ function divPrecisely(uint256 x, uint256 y) internal pure returns (uint256) { // e.g. 8e18 * 1e18 = 8e36 uint256 z = x * FULL_SCALE; // e.g. 8e36 / 10e18 = 8e17 return z / y; } /** * @dev Precisely divides two units, by first scaling the left hand operand. Useful * for finding percentage weightings, i.e. 8e18/10e18 = 80% (or 8e17) * @param x Left hand input to division * @param y Right hand input to division * @return Result after multiplying the left operand by the scale, and * executing the division on the right hand input. */ function divPreciselyScale(uint256 x, uint256 y, uint256 scale) internal pure returns (uint256) { // e.g. 8e18 * 1e18 = 8e36 uint256 z = x * scale; // e.g. 8e36 / 10e18 = 8e17 return z / y; } }
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity ^0.8.0; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; interface IPegToken is IERC20 { /** * @return the total shares minted. */ function totalShares() external view returns (uint256); /** * @return the shares of specified address. */ function sharesOf(address _account) external view returns (uint256); /** * @dev query the value that can be returned for a specified number of shares. * @return underlying units etc usd/eth. */ function getUnderlyingUnitsByShares(uint256 _sharesAmount) external view returns (uint256); /** * @dev query the shares that can be returned for a specified number of underlying uints. * @return the shares. */ function getSharesByUnderlyingUnits(uint256 _underlyingUnits) external view returns (uint256); /** * @dev change the pause state. * @param _isPaused. */ function changePauseState(bool _isPaused) external; /** * @notice Creates `_sharesAmount` shares and assigns them to `_recipient`, increasing the total amount of shares. * @dev This doesn't increase the token total supply. * * Requirements: * * - `_recipient` cannot be the zero address. * - the contract must not be paused. */ function mintShares(address _recipient, uint256 _sharesAmount) external; /** * @notice Destroys `_sharesAmount` shares from `_account`'s holdings, decreasing the total amount of shares. * @dev This doesn't decrease the token total supply. * * Requirements: * * - `_account` cannot be the zero address. * - `_account` must hold at least `_sharesAmount` shares. * - the contract must not be paused. */ function burnShares(address _account, uint256 _sharesAmount) external; }
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity ^0.8.0; interface IVaultBuffer { event OpenDistribute(); event CloseDistribute(); /// @notice mint pending shares /// @param _sender user account address /// @param _amount mint amount function mint(address _sender, uint256 _amount) external payable; /// @notice transfer cash to vault /// @param _assets transfer token /// @param _amounts transfer token amount function transferCashToVault(address[] memory _assets, uint256[] memory _amounts) external; function openDistribute() external; function distributeWhenDistributing() external returns (bool); function distributeOnce() external returns (bool); function isDistributing() external view returns (bool); function getDistributeLimit() external view returns (uint256); function setDistributeLimit(uint256 _limit) external; }
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity >=0.6.0 <0.9.0; library BocRoles { bytes32 internal constant GOV_ROLE = 0x00; bytes32 internal constant DELEGATE_ROLE = keccak256("DELEGATE_ROLE"); bytes32 internal constant VAULT_ROLE = keccak256("VAULT_ROLE"); bytes32 internal constant KEEPER_ROLE = keccak256("KEEPER_ROLE"); }
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity ^0.8.0; import "../vault/IVault.sol"; interface IStrategy { struct OutputInfo { uint256 outputCode; //0:default path,Greater than 0:specify output path address[] outputTokens; //output tokens } event Borrow(address[] _assets, uint256[] _amounts); event Repay(uint256 _withdrawShares, uint256 _totalShares, address[] _assets, uint256[] _amounts); event SetIsWantRatioIgnorable(bool _oldValue, bool _newValue); /// @notice Version of strategy function getVersion() external pure returns (string memory); /// @notice Name of strategy function name() external view returns (string memory); /// @notice ID of strategy function protocol() external view returns (uint16); /// @notice Vault address function vault() external view returns (IVault); /// @notice Harvester address function harvester() external view returns (address); /// @notice Provide the strategy need underlying token and ratio function getWantsInfo() external view returns (address[] memory _assets, uint256[] memory _ratios); /// @notice Provide the strategy need underlying token function getWants() external view returns (address[] memory _wants); // @notice Provide the strategy output path when withdraw. function getOutputsInfo() external view returns (OutputInfo[] memory _outputsInfo); /// @notice True means that can ignore ratios given by wants info function setIsWantRatioIgnorable(bool _isWantRatioIgnorable) external; /// @notice Returns the position details of the strategy. function getPositionDetail() external view returns ( address[] memory _tokens, uint256[] memory _amounts, bool _isUsd, uint256 _usdValue ); /// @notice Total assets of strategy in USD. function estimatedTotalAssets() external view returns (uint256); /// @notice 3rd protocol's pool total assets in USD. function get3rdPoolAssets() external view returns (uint256); /// @notice Harvests the Strategy, recognizing any profits or losses and adjusting the Strategy's position. function harvest() external returns (address[] memory _rewardsTokens, uint256[] memory _claimAmounts); /// @notice Strategy borrow funds from vault /// @param _assets borrow token address /// @param _amounts borrow token amount function borrow(address[] memory _assets, uint256[] memory _amounts) external; /// @notice Strategy repay the funds to vault /// @param _withdrawShares Numerator /// @param _totalShares Denominator function repay( uint256 _withdrawShares, uint256 _totalShares, uint256 _outputCode ) external returns (address[] memory _assets, uint256[] memory _amounts); /// @notice getter isWantRatioIgnorable function isWantRatioIgnorable() external view returns (bool); /// @notice Investable amount of strategy in USD function poolQuota() external view returns (uint256); }
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity ^0.8.0; interface IValueInterpreter { /// @notice Calculates the value of a given amount of one asset in terms of another asset /// @param _baseAsset The asset from which to convert /// @param _amount The amount of the _baseAsset to convert /// @param _quoteAsset The asset to which to convert /// @return _value The equivalent quantity in the _quoteAsset /// @dev Does not alter protocol state, /// but not a view because calls to price feeds can potentially update third party state function calcCanonicalAssetValue( address _baseAsset, uint256 _amount, address _quoteAsset ) external view returns (uint256); /// @notice Calculates the total value of given amounts of assets in a single quote asset /// @param _baseAssets The assets to convert /// @param _amounts The amounts of the _baseAssets to convert /// @param _quoteAsset The asset to which to convert /// @return _value The sum value of _baseAssets, denominated in the _quoteAsset /// @dev Does not alter protocol state, /// but not a view because calls to price feeds can potentially update third party state. /// Does not handle a derivative quote asset. function calcCanonicalAssetsTotalValue( address[] calldata _baseAssets, uint256[] calldata _amounts, address _quoteAsset ) external view returns (uint256); /// @dev Calculate the usd value of a specified number of assets /// @param _baseAsset Source token address /// @param _amount The amount of source token /// @return usd(1e18) function calcCanonicalAssetValueInUsd( address _baseAsset, uint256 _amount ) external view returns (uint256); /// @dev Calculate the usd value of baseUnit volume assets /// @param _baseAsset The ssset token address /// @return usd(1e18) function price(address _baseAsset) external view returns (uint256); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.2; import "../../utils/AddressUpgradeable.sol"; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ``` * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. * @custom:oz-retyped-from bool */ uint8 private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint8 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`. */ modifier initializer() { bool isTopLevelCall = _setInitializedVersion(1); if (isTopLevelCall) { _initializing = true; } _; if (isTopLevelCall) { _initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original * initialization step. This is essential to configure modules that are added through upgrades and that require * initialization. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. */ modifier reinitializer(uint8 version) { bool isTopLevelCall = _setInitializedVersion(version); if (isTopLevelCall) { _initializing = true; } _; if (isTopLevelCall) { _initializing = false; emit Initialized(version); } } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { require(_initializing, "Initializable: contract is not initializing"); _; } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. */ function _disableInitializers() internal virtual { _setInitializedVersion(type(uint8).max); } function _setInitializedVersion(uint8 version) private returns (bool) { // If the contract is initializing we ignore whether _initialized is set in order to support multiple // inheritance patterns, but we only do this in the context of a constructor, and for the lowest level // of initializers, because in other contexts the contract may have been reentered. if (_initializing) { require( version == 1 && !AddressUpgradeable.isContract(address(this)), "Initializable: contract is already initialized" ); return false; } else { require(_initialized < version, "Initializable: contract is already initialized"); _initialized = version; return true; } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol) 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 onlyInitializing { __ReentrancyGuard_init_unchained(); } function __ReentrancyGuard_init_unchained() internal onlyInitializing { _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 making 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; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/structs/EnumerableSet.sol) pragma solidity ^0.8.0; /** * @dev Library for managing * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive * types. * * Sets have the following properties: * * - Elements are added, removed, and checked for existence in constant time * (O(1)). * - Elements are enumerated in O(n). No guarantees are made on the ordering. * * ``` * contract Example { * // Add the library methods * using EnumerableSet for EnumerableSet.AddressSet; * * // Declare a set state variable * EnumerableSet.AddressSet private mySet; * } * ``` * * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) * and `uint256` (`UintSet`) are supported. * * [WARNING] * ==== * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable. * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. * * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet. * ==== */ library EnumerableSet { // To implement this library for multiple types with as little code // repetition as possible, we write it in terms of a generic Set type with // bytes32 values. // The Set implementation uses private functions, and user-facing // implementations (such as AddressSet) are just wrappers around the // underlying Set. // This means that we can only create new EnumerableSets for types that fit // in bytes32. struct Set { // Storage of set values bytes32[] _values; // Position of the value in the `values` array, plus 1 because index 0 // means a value is not in the set. mapping(bytes32 => uint256) _indexes; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function _add(Set storage set, bytes32 value) private returns (bool) { if (!_contains(set, value)) { set._values.push(value); // The value is stored at length-1, but we add 1 to all indexes // and use 0 as a sentinel value set._indexes[value] = set._values.length; return true; } else { return false; } } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function _remove(Set storage set, bytes32 value) private returns (bool) { // We read and store the value's index to prevent multiple reads from the same storage slot uint256 valueIndex = set._indexes[value]; if (valueIndex != 0) { // Equivalent to contains(set, value) // To delete an element from the _values array in O(1), we swap the element to delete with the last one in // the array, and then remove the last element (sometimes called as 'swap and pop'). // This modifies the order of the array, as noted in {at}. uint256 toDeleteIndex = valueIndex - 1; uint256 lastIndex = set._values.length - 1; if (lastIndex != toDeleteIndex) { bytes32 lastValue = set._values[lastIndex]; // Move the last value to the index where the value to delete is set._values[toDeleteIndex] = lastValue; // Update the index for the moved value set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex } // Delete the slot where the moved value was stored set._values.pop(); // Delete the index for the deleted slot delete set._indexes[value]; return true; } else { return false; } } /** * @dev Returns true if the value is in the set. O(1). */ function _contains(Set storage set, bytes32 value) private view returns (bool) { return set._indexes[value] != 0; } /** * @dev Returns the number of values on the set. O(1). */ function _length(Set storage set) private view returns (uint256) { return set._values.length; } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function _at(Set storage set, uint256 index) private view returns (bytes32) { return set._values[index]; } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function _values(Set storage set) private view returns (bytes32[] memory) { return set._values; } // Bytes32Set struct Bytes32Set { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _add(set._inner, value); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _remove(set._inner, value); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { return _contains(set._inner, value); } /** * @dev Returns the number of values in the set. O(1). */ function length(Bytes32Set storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { return _at(set._inner, index); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { return _values(set._inner); } // AddressSet struct AddressSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(AddressSet storage set, address value) internal returns (bool) { return _add(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(AddressSet storage set, address value) internal returns (bool) { return _remove(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(AddressSet storage set, address value) internal view returns (bool) { return _contains(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns the number of values in the set. O(1). */ function length(AddressSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(AddressSet storage set, uint256 index) internal view returns (address) { return address(uint160(uint256(_at(set._inner, index)))); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(AddressSet storage set) internal view returns (address[] memory) { bytes32[] memory store = _values(set._inner); address[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // UintSet struct UintSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(UintSet storage set, uint256 value) internal returns (bool) { return _add(set._inner, bytes32(value)); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(UintSet storage set, uint256 value) internal returns (bool) { return _remove(set._inner, bytes32(value)); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(UintSet storage set, uint256 value) internal view returns (bool) { return _contains(set._inner, bytes32(value)); } /** * @dev Returns the number of values on the set. O(1). */ function length(UintSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintSet storage set, uint256 index) internal view returns (uint256) { return uint256(_at(set._inner, index)); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(UintSet storage set) internal view returns (uint256[] memory) { bytes32[] memory store = _values(set._inner); uint256[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } }
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity >=0.6.0 <0.9.0; interface IAccessControlProxy { function isGovOrDelegate(address _account) external view returns (bool); function isVaultOrGov(address _account) external view returns (bool); function isKeeperOrVaultOrGov(address _account) external view returns (bool); function hasRole(bytes32 _role, address _account) external view returns (bool); function checkRole(bytes32 _role, address _account) external view; function checkGovOrDelegate(address _account) external view; function checkVaultOrGov(address _account) external view; function checkKeeperOrVaultOrGov(address _account) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (utils/math/SafeMath.sol) pragma solidity ^0.8.0; // CAUTION // This version of SafeMath should only be used with Solidity 0.8 or later, // because it relies on the compiler's built in overflow checks. /** * @dev Wrappers over Solidity's arithmetic operations. * * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler * now has built in overflow checking. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the subtraction of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b > a) return (false, 0); return (true, a - b); } } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a / b); } } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a % b); } } /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { return a + b; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return a - b; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { return a * b; } /** * @dev Returns the integer division of two unsigned integers, reverting on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return a / b; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return a % b; } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {trySub}. * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b <= a, errorMessage); return a - b; } } /** * @dev Returns the integer division of two unsigned integers, reverting with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b > 0, errorMessage); return a / b; } } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting with custom message when dividing by zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryMod}. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b > 0, errorMessage); return a % b; } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 amount ) external returns (bool); }
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity ^0.8.0; pragma experimental ABIEncoderV2; import "../exchanges/IExchangeAggregator.sol"; interface IVault { /// @param lastReport The last report timestamp /// @param totalDebt The total asset of this strategy /// @param profitLimitRatio The limited ratio of profit /// @param lossLimitRatio The limited ratio for loss /// @param enforceChangeLimit The switch of enforce change Limit struct StrategyParams { uint256 lastReport; uint256 totalDebt; uint256 profitLimitRatio; uint256 lossLimitRatio; bool enforceChangeLimit; } /// @param strategy The new strategy to add /// @param profitLimitRatio The limited ratio of profit /// @param lossLimitRatio The limited ratio for loss struct StrategyAdd { address strategy; uint256 profitLimitRatio; uint256 lossLimitRatio; } event AddAsset(address _asset); event RemoveAsset(address _asset); event AddStrategies(address[] _strategies); event RemoveStrategies(address[] _strategies); event RemoveStrategyByForce(address _strategy); event Mint(address _account, address[] _assets, uint256[] _amounts, uint256 _mintAmount); event Burn( address _account, uint256 _amount, uint256 _actualAmount, uint256 _shareAmount, address[] _assets, uint256[] _amounts ); event Exchange( address _platform, address _srcAsset, uint256 _srcAmount, address _distAsset, uint256 _distAmount ); event Redeem(address _strategy, uint256 _debtChangeAmount, address[] _assets, uint256[] _amounts); event LendToStrategy( address indexed _strategy, address[] _wants, uint256[] _amounts, uint256 _lendValue ); event RepayFromStrategy( address indexed _strategy, uint256 _strategyWithdrawValue, uint256 _strategyTotalValue, address[] _assets, uint256[] _amounts ); event RemoveStrategyFromQueue(address[] _strategies); event SetEmergencyShutdown(bool _shutdown); event RebasePaused(); event RebaseUnpaused(); event RebaseThresholdUpdated(uint256 _threshold); event TrusteeFeeBpsChanged(uint256 _basis); event MaxTimestampBetweenTwoReportedChanged(uint256 _maxTimestampBetweenTwoReported); event MinCheckedStrategyTotalDebtChanged(uint256 _minCheckedStrategyTotalDebt); event MinimumInvestmentAmountChanged(uint256 _minimumInvestmentAmount); event TreasuryAddressChanged(address _address); event ExchangeManagerAddressChanged(address _address); event SetAdjustPositionPeriod(bool _adjustPositionPeriod); event RedeemFeeUpdated(uint256 _redeemFeeBps); event SetWithdrawalQueue(address[] _queues); event Rebase(uint256 _totalShares, uint256 _totalValue, uint256 _newUnderlyingUnitsPerShare); event StrategyReported( address indexed _strategy, uint256 _gain, uint256 _loss, uint256 _lastStrategyTotalDebt, uint256 _nowStrategyTotalDebt, address[] _rewardTokens, uint256[] _claimAmounts, uint256 _type ); event StartAdjustPosition( uint256 _totalDebtOfBeforeAdjustPosition, address[] _trackedAssets, uint256[] _vaultCashDetatil, uint256[] _vaultBufferCashDetail ); event EndAdjustPosition( uint256 _transferValue, uint256 _redeemValue, uint256 _totalDebt, uint256 _totalValueOfAfterAdjustPosition, uint256 _totalValueOfBeforeAdjustPosition ); event PegTokenSwapCash(uint256 _pegTokenAmount, address[] _assets, uint256[] _amounts); /// @notice Version of vault function getVersion() external pure returns (string memory); /// @notice Minting USDi supported assets function getSupportAssets() external view returns (address[] memory _assets); /// @notice Check '_asset' is supported or not function checkIsSupportAsset(address _asset) external view; /// @notice Assets held by Vault function getTrackedAssets() external view returns (address[] memory _assets); /// @notice Vault holds asset value directly in USD function valueOfTrackedTokens() external view returns (uint256 _totalValue); /// @notice Vault and vault buffer holds asset value directly in USD function valueOfTrackedTokensIncludeVaultBuffer() external view returns (uint256 _totalValue); /// @notice Vault total asset in USD function totalAssets() external view returns (uint256); /// @notice Vault and vault buffer total asset in USD function totalAssetsIncludeVaultBuffer() external view returns (uint256); /// @notice Vault total value(by chainlink price) in USD(1e18) function totalValue() external view returns (uint256); /// @notice Start adjust position function startAdjustPosition() external; /// @notice End adjust position function endAdjustPosition() external; /// @notice Return underlying token per share token function underlyingUnitsPerShare() external view returns (uint256); /// @notice Get pegToken price in USD(1e18) function getPegTokenPrice() external view returns (uint256); /** * @dev Internal to calculate total value of all assets held in Vault. * @return _value Total value(by chainlink price) in USD (1e18) */ function totalValueInVault() external view returns (uint256 _value); /** * @dev Internal to calculate total value of all assets held in Strategies. * @return _value Total value(by chainlink price) in USD (1e18) */ function totalValueInStrategies() external view returns (uint256 _value); /// @notice Return all strategy addresses function getStrategies() external view returns (address[] memory _strategies); /// @notice Check '_strategy' is active or not function checkActiveStrategy(address _strategy) external view; /// @notice estimate Minting share with stablecoins /// @param _assets Address of the asset being deposited /// @param _amounts Amount of the asset being deposited /// @dev Support single asset or multi-assets /// @return _shareAmount function estimateMint(address[] memory _assets, uint256[] memory _amounts) external view returns (uint256 _shareAmount); /// @notice Minting share with stablecoins /// @param _assets Address of the asset being deposited /// @param _amounts Amount of the asset being deposited /// @dev Support single asset or multi-assets /// @return _shareAmount function mint( address[] memory _assets, uint256[] memory _amounts, uint256 _minimumAmount ) external returns (uint256 _shareAmount); /// @notice burn USDi,return stablecoins /// @param _amount Amount of USDi to burn /// @param _minimumAmount Minimum usd to receive in return function burn(uint256 _amount, uint256 _minimumAmount) external returns (address[] memory _assets, uint256[] memory _amounts); /// @notice Change USDi supply with Vault total assets. function rebase() external; /// @notice Allocate funds in Vault to strategies. function lend(address _strategy, IExchangeAggregator.ExchangeToken[] calldata _exchangeTokens) external; /// @notice Withdraw the funds from specified strategy. function redeem( address _strategy, uint256 _amount, uint256 _outputCode ) external; /** * @dev Exchange from '_fromToken' to '_toToken' * @param _fromToken The token swap from * @param _toToken The token swap to * @param _amount The amount to swap * @param _exchangeParam The struct of ExchangeParam, see {ExchangeParam} struct * @return _exchangeAmount The real amount to exchange * Emits a {Exchange} event. */ function exchange( address _fromToken, address _toToken, uint256 _amount, IExchangeAggregator.ExchangeParam memory _exchangeParam ) external returns (uint256); /** * @dev Report the current asset of strategy caller * @param _rewardTokens The reward token list * @param _claimAmounts The claim amount list * Emits a {StrategyReported} event. */ function report(address[] memory _rewardTokens, uint256[] memory _claimAmounts) external; /// @notice Shutdown the vault when an emergency occurs, cannot mint/burn. function setEmergencyShutdown(bool _active) external; /// @notice set adjustPositionPeriod true when adjust position occurs, cannot remove add asset/strategy and cannot mint/burn. function setAdjustPositionPeriod(bool _adjustPositionPeriod) external; /** * @dev Set a minimum difference ratio automatically rebase. * rebase * @param _threshold _threshold is the numerator and the denominator is 10000000 (x/10000000). */ function setRebaseThreshold(uint256 _threshold) external; /** * @dev Set a fee in basis points to be charged for a redeem. * @param _redeemFeeBps Basis point fee to be charged */ function setRedeemFeeBps(uint256 _redeemFeeBps) external; /** * @dev Sets the treasuryAddress that can receive a portion of yield. * Setting to the zero address disables this feature. */ function setTreasuryAddress(address _address) external; /** * @dev Sets the exchangeManagerAddress that can receive a portion of yield. */ function setExchangeManagerAddress(address _exchangeManagerAddress) external; /** * @dev Sets the TrusteeFeeBps to the percentage of yield that should be * received in basis points. */ function setTrusteeFeeBps(uint256 _basis) external; /// @notice set '_queues' as advance withdrawal queue function setWithdrawalQueue(address[] memory _queues) external; function setStrategyEnforceChangeLimit(address _strategy, bool _enabled) external; function setStrategySetLimitRatio( address _strategy, uint256 _lossRatioLimit, uint256 _profitLimitRatio ) external; /** * @dev Set the deposit paused flag to true to prevent rebasing. */ function pauseRebase() external; /** * @dev Set the deposit paused flag to true to allow rebasing. */ function unpauseRebase() external; /// @notice Added support for specific asset. function addAsset(address _asset) external; /// @notice Remove support for specific asset. function removeAsset(address _asset) external; /// @notice Add strategy to strategy list /// @dev The strategy added to the strategy list, /// Vault may invest funds into the strategy, /// and the strategy will invest the funds in the 3rd protocol function addStrategy(StrategyAdd[] memory _strategyAdds) external; /// @notice Remove strategy from strategy list /// @dev The removed policy withdraws funds from the 3rd protocol and returns to the Vault function removeStrategy(address[] memory _strategies) external; function forceRemoveStrategy(address _strategy) external; /*************************************** WithdrawalQueue ****************************************/ function getWithdrawalQueue() external view returns (address[] memory); function removeStrategyFromQueue(address[] memory _strategies) external; /// @notice Return the period of adjust position function adjustPositionPeriod() external view returns (bool); /// @notice Return the status of emergency shutdown switch function emergencyShutdown() external view returns (bool); /// @notice Return the status of rebase paused switch function rebasePaused() external view returns (bool); /// @notice Return the rebaseThreshold value, /// over this difference ratio automatically rebase. /// rebaseThreshold is the numerator and the denominator is 10000000 x/10000000. function rebaseThreshold() external view returns (uint256); /// @notice Return the Amount of yield collected in basis points function trusteeFeeBps() external view returns (uint256); /// @notice Return the redemption fee in basis points function redeemFeeBps() external view returns (uint256); /// @notice Return the total asset of all strategy function totalDebt() external view returns (uint256); /// @notice Return the exchange manager address function exchangeManager() external view returns (address); /// @notice Return all info of '_strategy' function strategies(address _strategy) external view returns (StrategyParams memory); /// @notice Return withdraw strategy address list function withdrawQueue() external view returns (address[] memory); /// @notice Return the address of treasury function treasury() external view returns (address); /// @notice Return the address of price oracle function valueInterpreter() external view returns (address); /// @notice Return the address of access control proxy contract function accessControlProxy() external view returns (address); /// @notice Set the minimum strategy total debt that will be checked for the strategy reporting function setMinCheckedStrategyTotalDebt(uint256 _minCheckedStrategyTotalDebt) external; /// @notice Return the minimum strategy total debt that will be checked for the strategy reporting function minCheckedStrategyTotalDebt() external view returns (uint256); /// @notice Set the maximum timestamp between two reported function setMaxTimestampBetweenTwoReported(uint256 _maxTimestampBetweenTwoReported) external; /// @notice The maximum timestamp between two reported function maxTimestampBetweenTwoReported() external view returns (uint256); /// @notice Set the minimum investment amount function setMinimumInvestmentAmount(uint256 _minimumInvestmentAmount) external; /// @notice Return the minimum investment amount function minimumInvestmentAmount() external view returns (uint256); /// @notice Set the address of vault buffer contract function setVaultBufferAddress(address _address) external; /// @notice Return the address of vault buffer contract function vaultBufferAddress() external view returns (address); /// @notice Set the address of PegToken contract function setPegTokenAddress(address _address) external; /// @notice Return the address of PegToken contract function pegTokenAddress() external view returns (address); /// @notice Set the new implement contract address function setAdminImpl(address _newImpl) external; }
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity >=0.6.0 <0.9.0; pragma experimental ABIEncoderV2; interface IExchangeAdapter { /** * @param amount The amount to swap * @param srcToken The token swap from * @param dstToken The token swap to * @param receiver The user to receive `dstToken` */ struct SwapDescription { uint256 amount; address srcToken; address dstToken; address receiver; } /// @notice The identifier of this exchange adapter function identifier() external pure returns (string memory _identifier); /** * @notice Swap with `_sd` data by using `_method` and `_data` on `_platform`. * @param _method The method of the exchange platform * @param _encodedCallArgs The encoded parameters to call * @param _sd The description info of this swap * @return The expected amountIn to swap */ function swap( uint8 _method, bytes calldata _encodedCallArgs, SwapDescription calldata _sd ) external payable returns (uint256); }
{ "optimizer": { "enabled": true, "runs": 200, "details": { "yul": true } }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_asset","type":"address"}],"name":"AddAsset","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"_strategies","type":"address[]"}],"name":"AddStrategies","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_account","type":"address"},{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_actualAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_shareAmount","type":"uint256"},{"indexed":false,"internalType":"address[]","name":"_assets","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"_amounts","type":"uint256[]"}],"name":"Burn","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_transferValue","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_redeemValue","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_totalDebt","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_totalValueOfAfterAdjustPosition","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_totalValueOfBeforeAdjustPosition","type":"uint256"}],"name":"EndAdjustPosition","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_platform","type":"address"},{"indexed":false,"internalType":"address","name":"_srcAsset","type":"address"},{"indexed":false,"internalType":"uint256","name":"_srcAmount","type":"uint256"},{"indexed":false,"internalType":"address","name":"_distAsset","type":"address"},{"indexed":false,"internalType":"uint256","name":"_distAmount","type":"uint256"}],"name":"Exchange","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_address","type":"address"}],"name":"ExchangeManagerAddressChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_strategy","type":"address"},{"indexed":false,"internalType":"address[]","name":"_wants","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"_amounts","type":"uint256[]"},{"indexed":false,"internalType":"uint256","name":"_lendValue","type":"uint256"}],"name":"LendToStrategy","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_maxTimestampBetweenTwoReported","type":"uint256"}],"name":"MaxTimestampBetweenTwoReportedChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_minCheckedStrategyTotalDebt","type":"uint256"}],"name":"MinCheckedStrategyTotalDebtChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_minimumInvestmentAmount","type":"uint256"}],"name":"MinimumInvestmentAmountChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_account","type":"address"},{"indexed":false,"internalType":"address[]","name":"_assets","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"_amounts","type":"uint256[]"},{"indexed":false,"internalType":"uint256","name":"_mintAmount","type":"uint256"}],"name":"Mint","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_pegTokenAmount","type":"uint256"},{"indexed":false,"internalType":"address[]","name":"_assets","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"_amounts","type":"uint256[]"}],"name":"PegTokenSwapCash","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_totalShares","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_totalValue","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_newUnderlyingUnitsPerShare","type":"uint256"}],"name":"Rebase","type":"event"},{"anonymous":false,"inputs":[],"name":"RebasePaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_threshold","type":"uint256"}],"name":"RebaseThresholdUpdated","type":"event"},{"anonymous":false,"inputs":[],"name":"RebaseUnpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_strategy","type":"address"},{"indexed":false,"internalType":"uint256","name":"_debtChangeAmount","type":"uint256"},{"indexed":false,"internalType":"address[]","name":"_assets","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"_amounts","type":"uint256[]"}],"name":"Redeem","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_redeemFeeBps","type":"uint256"}],"name":"RedeemFeeUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_asset","type":"address"}],"name":"RemoveAsset","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"_strategies","type":"address[]"}],"name":"RemoveStrategies","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_strategy","type":"address"}],"name":"RemoveStrategyByForce","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"_strategies","type":"address[]"}],"name":"RemoveStrategyFromQueue","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_strategy","type":"address"},{"indexed":false,"internalType":"uint256","name":"_strategyWithdrawValue","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_strategyTotalValue","type":"uint256"},{"indexed":false,"internalType":"address[]","name":"_assets","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"_amounts","type":"uint256[]"}],"name":"RepayFromStrategy","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"_adjustPositionPeriod","type":"bool"}],"name":"SetAdjustPositionPeriod","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"_shutdown","type":"bool"}],"name":"SetEmergencyShutdown","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"_queues","type":"address[]"}],"name":"SetWithdrawalQueue","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_totalDebtOfBeforeAdjustPosition","type":"uint256"},{"indexed":false,"internalType":"address[]","name":"_trackedAssets","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"_vaultCashDetatil","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"_vaultBufferCashDetail","type":"uint256[]"}],"name":"StartAdjustPosition","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_strategy","type":"address"},{"indexed":false,"internalType":"uint256","name":"_gain","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_loss","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_lastStrategyTotalDebt","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_nowStrategyTotalDebt","type":"uint256"},{"indexed":false,"internalType":"address[]","name":"_rewardTokens","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"_claimAmounts","type":"uint256[]"},{"indexed":false,"internalType":"uint256","name":"_type","type":"uint256"}],"name":"StrategyReported","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_address","type":"address"}],"name":"TreasuryAddressChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_basis","type":"uint256"}],"name":"TrusteeFeeBpsChanged","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"accessControlProxy","outputs":[{"internalType":"contract IAccessControlProxy","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"adjustPositionPeriod","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_minimumAmount","type":"uint256"}],"name":"burn","outputs":[{"internalType":"address[]","name":"_assets","type":"address[]"},{"internalType":"uint256[]","name":"_amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_strategy","type":"address"}],"name":"checkActiveStrategy","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_asset","type":"address"}],"name":"checkIsSupportAsset","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[],"name":"emergencyShutdown","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"endAdjustPosition","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_assets","type":"address[]"},{"internalType":"uint256[]","name":"_amounts","type":"uint256[]"}],"name":"estimateMint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_fromToken","type":"address"},{"internalType":"address","name":"_toToken","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"components":[{"internalType":"address","name":"platform","type":"address"},{"internalType":"uint8","name":"method","type":"uint8"},{"internalType":"bytes","name":"encodeExchangeArgs","type":"bytes"},{"internalType":"uint256","name":"slippage","type":"uint256"},{"internalType":"uint256","name":"oracleAdditionalSlippage","type":"uint256"}],"internalType":"struct IExchangeAggregator.ExchangeParam","name":"_exchangeParam","type":"tuple"}],"name":"exchange","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"exchangeManager","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPegTokenPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStrategies","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getSupportAssets","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTrackedAssets","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getVersion","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"_accessControlProxy","type":"address"},{"internalType":"address","name":"_treasury","type":"address"},{"internalType":"address","name":"_exchangeManager","type":"address"},{"internalType":"address","name":"_valueInterpreter","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_strategyAddr","type":"address"},{"components":[{"internalType":"address","name":"fromToken","type":"address"},{"internalType":"address","name":"toToken","type":"address"},{"internalType":"uint256","name":"fromAmount","type":"uint256"},{"components":[{"internalType":"address","name":"platform","type":"address"},{"internalType":"uint8","name":"method","type":"uint8"},{"internalType":"bytes","name":"encodeExchangeArgs","type":"bytes"},{"internalType":"uint256","name":"slippage","type":"uint256"},{"internalType":"uint256","name":"oracleAdditionalSlippage","type":"uint256"}],"internalType":"struct IExchangeAggregator.ExchangeParam","name":"exchangeParam","type":"tuple"}],"internalType":"struct IExchangeAggregator.ExchangeToken[]","name":"_exchangeTokens","type":"tuple[]"}],"name":"lend","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"maxSupplyDiff","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxTimestampBetweenTwoReported","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minCheckedStrategyTotalDebt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minimumInvestmentAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"_assets","type":"address[]"},{"internalType":"uint256[]","name":"_amounts","type":"uint256[]"},{"internalType":"uint256","name":"_minimumAmount","type":"uint256"}],"name":"mint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"pegTokenAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rebase","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rebasePaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rebaseThreshold","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_strategy","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_outputCode","type":"uint256"}],"name":"redeem","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"redeemFeeBps","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"_rewardTokens","type":"address[]"},{"internalType":"uint256[]","name":"_claimAmounts","type":"uint256[]"}],"name":"report","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newImpl","type":"address"}],"name":"setAdminImpl","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"startAdjustPosition","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"strategies","outputs":[{"internalType":"uint256","name":"lastReport","type":"uint256"},{"internalType":"uint256","name":"totalDebt","type":"uint256"},{"internalType":"uint256","name":"profitLimitRatio","type":"uint256"},{"internalType":"uint256","name":"lossLimitRatio","type":"uint256"},{"internalType":"bool","name":"enforceChangeLimit","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalAssets","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalAssetsIncludeVaultBuffer","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalDebt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalValue","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalValueInStrategies","outputs":[{"internalType":"uint256","name":"_value","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalValueInVault","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"treasury","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"trusteeFeeBps","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"underlyingUnitsPerShare","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"valueInterpreter","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"valueOfTrackedTokens","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"valueOfTrackedTokensIncludeVaultBuffer","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vaultBufferAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"withdrawQueue","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b50615b7880620000216000396000f3fe60806040526004361061027d5760003560e01c80637af690971161014f578063b390c0ab116100c1578063d4c3eea01161007a578063d4c3eea01461078b578063e5f36762146107a0578063e6f2e598146107c0578063f8c8765e146107e0578063fc0cfeee14610800578063fc7b9c18146108205761027d565b8063b390c0ab146106db578063b49a60bb14610709578063bca9a47e1461072b578063c4b9737014610740578063cd5a7e9e14610755578063ce7f8cff1461076b5761027d565b80639fb0fbc5116101135780639fb0fbc51461063a578063a688b5d114610650578063a819e6ef14610670578063af14052c14610690578063afddbb58146106a5578063b1d061ab146106c55761027d565b80637af69097146105d55780637e428dac146105c05780638e510b52146105f557806391b9a4181461060b5780639c311dbb146106255761027d565b806338582a3f116101f35780635e2a0023116101ac5780635e2a00231461052a57806361d027b31461054a57806362518ddf1461056a5780636618231f1461058a57806367715935146105a05780636c3e2e0a146105c05761027d565b806338582a3f1461043e57806339ebf8231461045357806352d38e5d146104ca57806353ca9f24146104e057806354f1a073146105005780635646d0ec146105155761027d565b80631abb0a4a116102455780631abb0a4a146103825780631e8de77b14610399578063207134b0146103b95780632b83cccd146103cf5780632ed60f2c146103ef5780633403c2fc1461040f5761027d565b806301e1d114146102c357806309f6442c146102eb5780630d8e6e2c14610301578063119e3c7014610335578063178522641461036d575b7f3d78d3961e16fde088e2e26c1cfa163f5f8bb870709088dd68c87eb4091137e2366000803760008036600084545af43d6000803e8080156102be573d6000f35b3d6000fd5b3480156102cf57600080fd5b506102d8610836565b6040519081526020015b60405180910390f35b3480156102f757600080fd5b506102d860405481565b34801561030d57600080fd5b5060408051808201825260058152640312e312e360dc1b602082015290516102e291906156a6565b34801561034157600080fd5b50604854610355906001600160a01b031681565b6040516001600160a01b0390911681526020016102e2565b34801561037957600080fd5b506102d8610852565b34801561038e57600080fd5b50610397610916565b005b3480156103a557600080fd5b506103976103b4366004615261565b61102f565b3480156103c557600080fd5b506102d8603f5481565b3480156103db57600080fd5b506103976103ea36600461522d565b61104b565b3480156103fb57600080fd5b506102d861040a366004615261565b61131f565b34801561041b57600080fd5b50603c5461042e90610100900460ff1681565b60405190151581526020016102e2565b34801561044a57600080fd5b506102d8611334565b34801561045f57600080fd5b506104a061046e3660046150cb565b604560205260009081526040902080546001820154600283015460038401546004909401549293919290919060ff1685565b6040805195865260208601949094529284019190915260608301521515608082015260a0016102e2565b3480156104d657600080fd5b506102d8603d5481565b3480156104ec57600080fd5b50603c5461042e9062010000900460ff1681565b34801561050c57600080fd5b506102d8611341565b34801561052157600080fd5b5061039761134b565b34801561053657600080fd5b506102d861054536600461537c565b611711565b34801561055657600080fd5b50604254610355906001600160a01b031681565b34801561057657600080fd5b50610355610585366004615405565b61193a565b34801561059657600080fd5b506102d860505481565b3480156105ac57600080fd5b50603354610355906001600160a01b031681565b3480156105cc57600080fd5b506102d8611964565b3480156105e157600080fd5b50604754610355906001600160a01b031681565b34801561060157600080fd5b506102d8603e5481565b34801561061757600080fd5b50603c5461042e9060ff1681565b34801561063157600080fd5b506102d861196e565b34801561064657600080fd5b506102d8604d5481565b34801561065c57600080fd5b50604454610355906001600160a01b031681565b34801561067c57600080fd5b5061039761068b3660046151ab565b611bbc565b34801561069c57600080fd5b50610397612160565b3480156106b157600080fd5b506102d86106c0366004615142565b61223b565b3480156106d157600080fd5b506102d8604f5481565b3480156106e757600080fd5b506106fb6106f6366004615435565b6122da565b6040516102e292919061564b565b34801561071557600080fd5b5061071e612578565b6040516102e29190615638565b34801561073757600080fd5b5061071e612584565b34801561074c57600080fd5b5061071e612590565b34801561076157600080fd5b506102d8604e5481565b34801561077757600080fd5b506103976107863660046150cb565b61259a565b34801561079757600080fd5b506102d86125e9565b3480156107ac57600080fd5b506103976107bb3660046150cb565b6125fb565b3480156107cc57600080fd5b50604354610355906001600160a01b031681565b3480156107ec57600080fd5b506103976107fb3660046150e7565b61264a565b34801561080c57600080fd5b5061039761081b3660046150cb565b612738565b34801561082c57600080fd5b506102d860415481565b600060415461084361281a565b61084d91906158c3565b905090565b60008061085f60346128e9565b905060005b818110156109115760006108796034836128fb565b6001600160a01b031663efbb5cb06040518163ffffffff1660e01b815260040160206040518083038186803b1580156108b157600080fd5b505afa1580156108c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108e9919061541d565b905080156108fe576108fb81856158c3565b93505b508061090981615ae6565b915050610864565b505090565b6033546040516311aec98d60e01b81523360048201526001600160a01b03909116906311aec98d90602401600060405180830381600087803b15801561095b57600080fd5b505af115801561096f573d6000803e3d6000fd5b505050506002600154141561099f5760405162461bcd60e51b81526004016109969061573f565b60405180910390fd5b6002600155603c5460ff166109e05760405162461bcd60e51b815260206004820152600760248201526620a21027ab22a960c91b6044820152606401610996565b60006109ea612907565b80519091506000816001600160401b03811115610a1757634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015610a40578160200160208202803683370190505b5090506000826001600160401b03811115610a6b57634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015610a94578160200160208202803683370190505b5090506000610aa4856000612913565b5050905060008060008060005b88811015610bf35760008a8281518110610adb57634e487b7160e01b600052603260045260246000fd5b60200260200101519050610b178989848460496000876001600160a01b03166001600160a01b0316815260200190815260200160002054612b2c565b610b2190876158c3565b9550610b5589898484604a6000876001600160a01b03166001600160a01b0316815260200190815260200160002054612b2c565b610b5f90866158c3565b9450610b95898984848b8781518110610b8857634e487b7160e01b600052603260045260246000fd5b6020026020010151612b2c565b610b9f90856158c3565b9350610bd389898484604b6000876001600160a01b03166001600160a01b0316815260200190815260200160002054612b2c565b610bdd90846158c3565b9250508080610beb90615ae6565b915050610ab1565b50604c546041546000610c0685836158c3565b90506000610c1485856158c3565b905060008086610c248b8a6158c3565b1015610c425789610c358989615a2e565b610c3f9190615a2e565b90505b610c4c8a84615a2e565b610c56828b6158c3565b1115610c745780610c678b85615a2e565b610c719190615a2e565b98505b82841115610ccc576000610c888486615a2e565b90508a15610cc65781610c9b8b8d6158c3565b610ca591906158c3565b610caf8c83615a0f565b610cb991906158db565b610cc3908c6158c3565b92505b50610d18565b6000610cd88585615a2e565b90508a15610d165781610ceb8b8d6158c3565b610cf591906158c3565b610cff8c83615a0f565b610d0991906158db565b610d13908c615a2e565b92505b505b60485460408051633a98ef3960e01b815290516000926001600160a01b031691633a98ef39916004808301926020929190829003018186803b158015610d5d57600080fd5b505afa158015610d71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d95919061541d565b603c5490915062010000900460ff16610dbe57610dbb610db58487615a2e565b82612b71565b90505b8215610e4d576000610dda84610dd48189615a2e565b84612da2565b90508015610e4b576048546047546040516329460cc560e11b81526001600160a01b0391821660048201526024810184905291169063528c198a90604401600060405180830381600087803b158015610e3257600080fd5b505af1158015610e46573d6000803e3d6000fd5b505050505b505b50506000604c81905590505b8c811015610ecf5760008e8281518110610e8357634e487b7160e01b600052603260045260246000fd5b6020908102919091018101516001600160a01b03166000908152604a82526040808220829055604b83528082208290556049909252908120555080610ec781615ae6565b915050610e59565b50604760009054906101000a90046001600160a01b03166001600160a01b03166345153af86040518163ffffffff1660e01b815260040160206040518083038186803b158015610f1e57600080fd5b505afa158015610f32573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f5691906153e5565b610fc357604760009054906101000a90046001600160a01b03166001600160a01b0316636b5b53716040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610faa57600080fd5b505af1158015610fbe573d6000803e3d6000fd5b505050505b603c805460ff19169055604080518981526020810189905290810184905260608101839052608081018290527fcba28a6e335abfe9107150a5b5d2cce58719830735abd62327b9dbc8055fa9ba9060a00160405180910390a15050600180555050505050505050505050565b336110398161259a565b6110463384846000612e1a565b505050565b6033546040516311aec98d60e01b81523360048201526001600160a01b03909116906311aec98d90602401600060405180830381600087803b15801561109057600080fd5b505af11580156110a4573d6000803e3d6000fd5b50505050826110b28161259a565b600260015414156110d55760405162461bcd60e51b81526004016109969061573f565b600260019081556001600160a01b038516600090815260456020526040902001548084111561110357600080fd5b60405163895a748560e01b815260048101859052602481018290526044810184905260009081906001600160a01b0388169063895a748590606401600060405180830381600087803b15801561115857600080fd5b505af115801561116c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261119491908101906152c1565b603c54919350915060ff161561125e57815160005b8181101561125b5760008382815181106111d357634e487b7160e01b600052603260045260246000fd5b6020026020010151905060008111156112485780604a600087858151811061120b57634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600082825461124291906158c3565b90915550505b508061125381615ae6565b9150506111a9565b50505b6001600160a01b03871660009081526045602052604081206001015490846112868984615a0f565b61129091906158db565b905061129c8183615a2e565b6001600160a01b038a16600090815260456020526040812060010191909155604180548392906112cd908490615a2e565b90915550506040517f72dfda45f3c6c752a1cbef9d63f47877b3c19dbc227919bcfbbc26673bc96e1090611308908b908b9088908890615558565b60405180910390a150506001805550505050505050565b600061132b8383613117565b90505b92915050565b60006041546108436132da565b600061084d6132da565b6033546040516311aec98d60e01b81523360048201526001600160a01b03909116906311aec98d90602401600060405180830381600087803b15801561139057600080fd5b505af11580156113a4573d6000803e3d6000fd5b5050603c5460ff161591506113cd90505760405162461bcd60e51b8152600401610996906156b9565b603c54610100900460ff16156113f55760405162461bcd60e51b8152600401610996906156d5565b600260015414156114185760405162461bcd60e51b81526004016109969061573f565b60026001908155603c805460ff191690911790556000611436612907565b90506000806000611448846001612913565b604154929550909350915081156116c05784516000816001600160401b0381111561148357634e487b7160e01b600052604160045260246000fd5b6040519080825280602002602001820160405280156114ac578160200160208202803683370190505b5090506000826001600160401b038111156114d757634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015611500578160200160208202803683370190505b5090506000805b8481101561159f5760008a828151811061153157634e487b7160e01b600052603260045260246000fd5b6020026020010151905060008a838151811061155d57634e487b7160e01b600052603260045260246000fd5b60200260200101519050600081111561158a5761157d8686858585612b2c565b61158790856158c3565b93505b5050808061159790615ae6565b915050611507565b5060006115ac86836158c3565b90506000604860009054906101000a90046001600160a01b03166001600160a01b0316633a98ef396040518163ffffffff1660e01b815260040160206040518083038186803b1580156115fe57600080fd5b505afa158015611612573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611636919061541d565b603c5490915062010000900460ff16611655576116538282612b71565b505b604754604051637615eab160e11b81526001600160a01b039091169063ec2bd56290611687908e908d9060040161564b565b600060405180830381600087803b1580156116a157600080fd5b505af11580156116b5573d6000803e3d6000fd5b505050505050505050505b604c81905560405181907fbe4b7098b96c8f167582de3b9de443834380e1265a9a4453dbcf620e5ae63cac906116fd9083908990899089906157ab565b60405180910390a150506001805550505050565b603c54600090610100900460ff161561173c5760405162461bcd60e51b8152600401610996906156d5565b603c5460ff161561175f5760405162461bcd60e51b8152600401610996906156b9565b600260015414156117825760405162461bcd60e51b81526004016109969061573f565b600260015560006117938585613117565b905082156117eb57828110156117eb5760405162461bcd60e51b815260206004820152601e60248201527f4d696e7420616d6f756e74206c6f776572207468616e206d696e696d756d00006044820152606401610996565b60005b855181101561188c5761187a33604760009054906101000a90046001600160a01b031687848151811061183157634e487b7160e01b600052603260045260246000fd5b602002602001015189858151811061185957634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b03166133cd909392919063ffffffff16565b8061188481615ae6565b9150506117ee565b506047546040516340c10f1960e01b8152336004820152602481018390526001600160a01b03909116906340c10f1990604401600060405180830381600087803b1580156118d957600080fd5b505af11580156118ed573d6000803e3d6000fd5b505050507f62a0e51e012d92909587a2f2aa7f4016592ddf30135d505e2e0038b7f446a5bd338686846040516119269493929190615510565b60405180910390a160018055949350505050565b6046818154811061194a57600080fd5b6000918252602090912001546001600160a01b0316905081565b600061084d61281a565b600080604860009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156119bf57600080fd5b505afa1580156119d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119f7919061541d565b9050670de0b6b3a76400008115611bb6576000611a12612907565b80519091506000816001600160401b03811115611a3f57634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015611a68578160200160208202803683370190505b5090506000826001600160401b03811115611a9357634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015611abc578160200160208202803683370190505b50905060008060005b85811015611b76576000878281518110611aef57634e487b7160e01b600052603260045260246000fd5b602002602001015190506000611b05823061343e565b90508015611b2757611b1a8787858585612b2c565b611b2490866158c3565b94505b506001600160a01b0381166000908152604960205260409020548015611b6157611b548787858585612b2c565b611b5e90856158c3565b93505b50508080611b6e90615ae6565b915050611ac5565b50878160415484611b8791906158c3565b611b919190615a2e565b611ba390670de0b6b3a7640000615a0f565b611bad91906158db565b96505050505050505b91505090565b6033546040516311aec98d60e01b81523360048201526001600160a01b03909116906311aec98d90602401600060405180830381600087803b158015611c0157600080fd5b505af1158015611c15573d6000803e3d6000fd5b5050603c54610100900460ff16159150611c4390505760405162461bcd60e51b8152600401610996906156d5565b82611c4d8161259a565b60026001541415611c705760405162461bcd60e51b81526004016109969061573f565b600260015560008080611c848787876134bb565b925092509250600080886001600160a01b031663970d44ee6040518163ffffffff1660e01b815260040160206040518083038186803b158015611cc657600080fd5b505afa158015611cda573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cfe91906153e5565b905080158015611d0f575060018451115b15611e5f5760015b8451811015611e5d57848181518110611d4057634e487b7160e01b600052603260045260246000fd5b602002602001015160001415611d5557611e4b565b848381518110611d7557634e487b7160e01b600052603260045260246000fd5b602002602001015160001415611d8d57809250611e4b565b848381518110611dad57634e487b7160e01b600052603260045260246000fd5b6020026020010151848281518110611dd557634e487b7160e01b600052603260045260246000fd5b6020026020010151611de79190615a0f565b858281518110611e0757634e487b7160e01b600052603260045260246000fd5b6020026020010151858581518110611e2f57634e487b7160e01b600052603260045260246000fd5b6020026020010151611e419190615a0f565b1115611e4b578092505b80611e5581615ae6565b915050611d17565b505b6000838381518110611e8157634e487b7160e01b600052603260045260246000fd5b602002602001015190506000858481518110611ead57634e487b7160e01b600052603260045260246000fd5b60200260200101519050600080600090505b8651811015612094576000878281518110611eea57634e487b7160e01b600052603260045260246000fd5b6020026020010151905060008111156120815760008a8381518110611f1f57634e487b7160e01b600052603260045260246000fd5b6020026020010151905086158015611f5e575060008a8481518110611f5457634e487b7160e01b600052603260045260246000fd5b6020026020010151115b15611fd15784868b8581518110611f8557634e487b7160e01b600052603260045260246000fd5b6020026020010151611f979190615a0f565b611fa191906158db565b915081898481518110611fc457634e487b7160e01b600052603260045260246000fd5b6020026020010181815250505b60435460405163ebd6d95560e01b81526001600160a01b038381166004830152602482018590529091169063ebd6d9559060440160206040518083038186803b15801561201d57600080fd5b505afa158015612031573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612055919061541d565b61205f90856158c3565b935061207f8f83836001600160a01b03166137f49092919063ffffffff16565b505b508061208c81615ae6565b915050611ebf565b50604051630e7949d360e21b81528c906001600160a01b038216906339e5274c906120c5908c908b9060040161564b565b600060405180830381600087803b1580156120df57600080fd5b505af11580156120f3573d6000803e3d6000fd5b505050506060806121068f838387612e1a565b8e6001600160a01b03167fa320f26f9e050a2dbc872470ba0413f8dbb2134c86680cfb6e911c68bb6f911b8c8b8760405161214393929190615670565b60405180910390a250506001805550505050505050505050505050565b603c54610100900460ff16156121885760405162461bcd60e51b8152600401610996906156d5565b603c5460ff16156121ab5760405162461bcd60e51b8152600401610996906156b9565b603c5462010000900460ff16156121e95760405162461bcd60e51b8152602060048201526002602482015261052560f41b6044820152606401610996565b6002600154141561220c5760405162461bcd60e51b81526004016109969061573f565b600260015560415460009061221f61281a565b61222991906158c3565b905061223481613824565b5060018055565b6033546040516311aec98d60e01b81523360048201526000916001600160a01b0316906311aec98d90602401600060405180830381600087803b15801561228157600080fd5b505af1158015612295573d6000803e3d6000fd5b50505050600260015414156122bc5760405162461bcd60e51b81526004016109969061573f565b60026001556122cd858585856138ad565b6001805595945050505050565b603c546060908190610100900460ff16156123075760405162461bcd60e51b8152600401610996906156d5565b603c5460ff161561232a5760405162461bcd60e51b8152600401610996906156b9565b6002600154141561234d5760405162461bcd60e51b81526004016109969061573f565b60026001556048546040516370a0823160e01b81523360048201526000916001600160a01b0316906370a082319060240160206040518083038186803b15801561239657600080fd5b505afa1580156123aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123ce919061541d565b90506000851180156123e05750808511155b61241e5760405162461bcd60e51b815260206004820152600f60248201526e0aaa688d240dcdee840cadcdeeaced608b1b6044820152606401610996565b6000612428612907565b9050600081516001600160401b0381111561245357634e487b7160e01b600052604160045260246000fd5b60405190808252806020026020018201604052801561247c578160200160208202803683370190505b509050600082516001600160401b038111156124a857634e487b7160e01b600052604160045260246000fd5b6040519080825280602002602001820160405280156124d1578160200160208202803683370190505b5090506000806124e48a87878787613b3e565b9150915060006124f682878787613d4f565b919a5098509050891561255357898110156125535760405162461bcd60e51b815260206004820152601960248201527f616d6f756e74206c6f776572207468616e206d696e696d756d000000000000006044820152606401610996565b6125638b82858c8c8b8b8b613d80565b50505050505050600180819055509250929050565b606061084d6034613e68565b606061084d6036613e68565b606061084d612907565b6125a5603482613e75565b6125e65760405162461bcd60e51b81526020600482015260126024820152711cdd1c985d1959de481b9bdd08195e1a5cdd60721b6044820152606401610996565b50565b60006125f3610852565b61084361281a565b612606603682613e75565b6125e65760405162461bcd60e51b8152602060048201526015602482015274151a1948185cdcd95d081b9bdd081cdd5c1c1bdc9d605a1b6044820152606401610996565b60006126566001613e97565b9050801561266e576000805461ff0019166101001790555b603380546001600160a01b038781166001600160a01b03199283161790925560428054821687841617905560448054821686841617905560438054909116918416919091179055603c805462ff00001916905560006040556001603d5562093a80604e55670de0b6b3a7640000604d55683635c9adc5dea00000604f558015612731576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050565b603354604051630881b00560e41b81523360048201526001600160a01b039091169063881b00509060240160006040518083038186803b15801561277b57600080fd5b505afa15801561278f573d6000803e3d6000fd5b505050506001600160a01b0381163b6127f65760405162461bcd60e51b8152602060048201526024808201527f6e657720696d706c656d656e746174696f6e206973206e6f74206120636f6e746044820152631c9858dd60e21b6064820152608401610996565b7f3d78d3961e16fde088e2e26c1cfa163f5f8bb870709088dd68c87eb4091137e255565b600080612825612907565b80519091506000816001600160401b0381111561285257634e487b7160e01b600052604160045260246000fd5b60405190808252806020026020018201604052801561287b578160200160208202803683370190505b5090506000826001600160401b038111156128a657634e487b7160e01b600052604160045260246000fd5b6040519080825280602002602001820160405280156128cf578160200160208202803683370190505b50905060006128df858484613f1c565b9550505050505090565b60006128f3825490565b90505b919050565b600061132b8383613fa7565b606061084d6038613e68565b606080600080855190506000816001600160401b0381111561294557634e487b7160e01b600052604160045260246000fd5b60405190808252806020026020018201604052801561296e578160200160208202803683370190505b5090506000826001600160401b0381111561299957634e487b7160e01b600052604160045260246000fd5b6040519080825280602002602001820160405280156129c2578160200160208202803683370190505b5090506000805b84811015612b1d5760008a82815181106129f357634e487b7160e01b600052603260045260246000fd5b6020026020010151905060008a8015612a125750612a12603683613e75565b15612a8657604754612a2e9083906001600160a01b031661343e565b90508015612a865780868481518110612a5757634e487b7160e01b600052603260045260246000fd5b6020908102919091018101919091526001600160a01b0383166000908152604990915260409020819055600193505b6000612a92833061343e565b90508015612ac85780868581518110612abb57634e487b7160e01b600052603260045260246000fd5b6020026020010181815250505b8b8015612ade57506000612adc83836158c3565b115b15612b0757612aed82826158c3565b6001600160a01b0384166000908152604b60205260409020555b5050508080612b1590615ae6565b9150506129c9565b50909891975095509350505050565b600080612b3a878686613fdf565b90506000612b49878787614054565b90506000612b6483612b5c84600a615941565b8791906140c8565b9998505050505050505050565b600081612b7f57508061132e565b604d546000612b9b84836b033b2e3c9fd0803ce80000006140c8565b90508085118015612bce5750603d54612bb49082615a0f565b62989680612bc28388615a2e565b612bcc9190615a0f565b115b15612d9957604254603f546001600160a01b03909116908015801590612bfc57506001600160a01b03821615155b15612d2c576000612c0d8489615a2e565b90506000612710612c1e8484615a0f565b612c2891906158db565b9050808211612c845760405162461bcd60e51b815260206004820152602260248201527f466565206d757374206e6f742062652067726561746572207468616e207969656044820152611b1960f21b6064820152608401610996565b8015612d29576000612c96828b615a2e565b612ca08a84615a0f565b612caa91906158db565b90508015612d27576048546040516329460cc560e11b81526001600160a01b038781166004830152602482018490529091169063528c198a90604401600060405180830381600087803b158015612d0057600080fd5b505af1158015612d14573d6000803e3d6000fd5b505050508089612d2491906158c3565b98505b505b50505b6000612d4588886b033b2e3c9fd0803ce80000006140ea565b9050848114612d9557604d81905560408051888152602081018a90529081018290527fc6642d24d84e7f3d36ca39f5cce10e75639d9b158d5193aa350e2f900653e4c09060600160405180910390a15b5050505b50919392505050565b6000808315801590612db45750600083115b15612dd15783612dc48487615a0f565b612dce91906158db565b90505b80612e1057604d548015612dfd57612df686826b033b2e3c9fd0803ce80000006140ea565b9150612e0e565b612e0b86633b9aca00615a0f565b91505b505b90505b9392505050565b6001600160a01b0384166000908152604560209081526040808320815160a081018352815481526001820154938101849052600282015492810192909252600381015460608301526004015460ff16151560808201529190612e7d9084906158c3565b90506000866001600160a01b031663efbb5cb06040518163ffffffff1660e01b815260040160206040518083038186803b158015612eba57600080fd5b505afa158015612ece573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ef2919061541d565b905060008083831115612f1057612f098484615a2e565b9150612f25565b83831015612f2557612f228385615a2e565b90505b84608001511561302b57604e546001600160a01b038a16600090815260456020526040902054612f559042615a2e565b108015612f6e5750604f54841180612f6e5750604f5483115b15613026578115612fcf57612710856040015185612f8c9190615a0f565b612f9691906158db565b821115612fca5760405162461bcd60e51b815260206004820152600260248201526111d360f21b6044820152606401610996565b613026565b801561302657612710856060015185612fe89190615a0f565b612ff291906158db565b8111156130265760405162461bcd60e51b8152602060048201526002602482015261131360f21b6044820152606401610996565b613052565b6001600160a01b0389166000908152604560205260409020600401805460ff191660011790555b6001600160a01b0389166000908152604560205260409020600101839055604154849087906130829086906158c3565b61308c91906158c3565b6130969190615a2e565b6041556001600160a01b038916600090815260456020526040812042905586156130be575060015b896001600160a01b03167f6d35366477ec3dbdcc668ff1cf0df6df18998d6bbfbea924257ccbdfca3b1f35848488888e8e886040516131039796959493929190615809565b60405180910390a250505050505050505050565b60006131238383614103565b6000805b845181101561326457600085828151811061315257634e487b7160e01b600052603260045260246000fd5b60209081029190910101516043546040516315d5220f60e31b81526001600160a01b0380841660048301529293506000929091169063aea910789060240160206040518083038186803b1580156131a857600080fd5b505afa1580156131bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131e0919061541d565b6001600160a01b0383166000908152603b60205260409020549091506132428261320b83600a615941565b89878151811061322b57634e487b7160e01b600052603260045260246000fd5b60200260200101516140c89092919063ffffffff16565b61324c90866158c3565b9450505050808061325c90615ae6565b915050613127565b5060505480156132d257808210156132d25760405162461bcd60e51b815260206004820152602b60248201527f416d6f756e74206d757374206265206774206d696e696d756d20496e7665737460448201526a1b595b9d08105b5bdd5b9d60aa1b6064820152608401610996565b509392505050565b6000806132e5612907565b90506000805b82518110156133c657600083828151811061331657634e487b7160e01b600052603260045260246000fd5b60200260200101519050600061332c823061343e565b6047549091506000906133499084906001600160a01b031661343e565b9050600061335782846158c3565b905080156133af57600061336a85614306565b6001600160a01b0386166000908152603b602052604081205491925061339d8361339584600a615941565b8691906140c8565b90506133a9818a6158c3565b98505050505b5050505080806133be90615ae6565b9150506132eb565b5091505090565b6040516001600160a01b03808516602483015283166044820152606481018290526134389085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152614384565b50505050565b6040516370a0823160e01b81526001600160a01b038281166004830152600091908416906370a082319060240160206040518083038186803b15801561348357600080fd5b505afa158015613497573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061132b919061541d565b6060806060856001600160a01b031663adc58dd96040518163ffffffff1660e01b815260040160006040518083038186803b1580156134f957600080fd5b505afa15801561350d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261353591908101906152c1565b81519194509250806001600160401b0381111561356257634e487b7160e01b600052604160045260246000fd5b60405190808252806020026020018201604052801561358b578160200160208202803683370190505b5091508460005b81811015613697576000805b84811015613644578781815181106135c657634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b03168a8a858181106135f757634e487b7160e01b600052603260045260246000fd5b9050602002810190613609919061585b565b61361a9060408101906020016150cb565b6001600160a01b031614156136325760019150613644565b8061363c81615ae6565b91505061359e565b50806136845760405162461bcd60e51b815260206004820152600f60248201526e1d1bd51bdad95b881a5b9d985b1a59608a1b6044820152606401610996565b508061368f81615ae6565b915050613592565b5060005b828110156137e85760005b828110156137d55760008989838181106136d057634e487b7160e01b600052603260045260246000fd5b90506020028101906136e2919061585b565b6136eb90615a45565b905080602001516001600160a01b031688848151811061371b57634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b03161461373757506137c3565b600081602001516001600160a01b031682600001516001600160a01b031614156137665750604081015161378f565b60408201511561378f5761378c82600001518360200151846040015185606001516138ad565b90505b808785815181106137b057634e487b7160e01b600052603260045260246000fd5b60200260200101818152505050506137d5565b806137cd81615ae6565b9150506136a6565b50806137e081615ae6565b91505061369b565b50505093509350939050565b6040516001600160a01b03831660248201526044810182905261104690849063a9059cbb60e01b90606401613401565b60485460408051633a98ef3960e01b815290516000926001600160a01b031691633a98ef39916004808301926020929190829003018186803b15801561386957600080fd5b505afa15801561387d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138a1919061541d565b90506110468282612b71565b60006138ba603885614456565b6138eb5760405162461bcd60e51b8152602060048201526002602482015261085560f21b6044820152606401610996565b604080516080810182528481526001600160a01b038088166020830181905287821693830193909352306060830152604454919261392d929091166000614462565b604454613947906001600160a01b03888116911686614462565b60445483516020850151604080870151905163538d5ab960e11b81526001600160a01b039094169363a71ab57293613987939092909187906004016155d6565b602060405180830381600087803b1580156139a157600080fd5b505af11580156139b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139d9919061541d565b604354604051632633f08360e11b81526001600160a01b03898116600483015260248201889052888116604483015292945060009290911690634c67e1069060640160206040518083038186803b158015613a3357600080fd5b505afa158015613a47573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a6b919061541d565b905061271084608001518560600151612710613a879190615a2e565b613a919190615a2e565b613a9b9083615a0f565b613aa591906158db565b831015613ad95760405162461bcd60e51b815260206004820152600260248201526113d360f21b6044820152606401610996565b8351604080516001600160a01b0392831681528983166020820152808201889052918816606083015260808201859052517fec43bc4dddba4c8ae8d4f92f53b39989eaf64022bec70471d105647e57c7891c9181900360a00190a15050949350505050565b6000806000613b4e868686613f1c565b6041549091508890600090613b6390846158c3565b90506000604860009054906101000a90046001600160a01b03166001600160a01b0316633a98ef396040518163ffffffff1660e01b815260040160206040518083038186803b158015613bb557600080fd5b505afa158015613bc9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613bed919061541d565b604d549091508a841415613c7d57604854604051633d7ad0b760e21b81523360048201526001600160a01b039091169063f5eb42dc9060240160206040518083038186803b158015613c3e57600080fd5b505afa158015613c52573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c76919061541d565b9650613c97565b613c9484826b033b2e3c9fd0803ce80000006140ea565b96505b60405415613cc75761271060405485613cb09190615a0f565b613cba91906158db565b613cc49085615a2e565b93505b6000613ce083836b033b2e3c9fd0803ce80000006140c8565b905080613ced8587615a0f565b613cf791906158db565b9650505084841015613d2757613d1a613d108587615a2e565b8a8a8a8686614586565b613d2490856158c3565b93505b84841015613d4157613d41613d3c8587615a2e565b614857565b505050509550959350505050565b606080600080613d6188888888614aa2565b90506000613d7182898989614c01565b97999198509095505050505050565b604854604051633b9e9f0160e21b8152336004820152602481018890526001600160a01b039091169063ee7a7c0490604401600060405180830381600087803b158015613dcc57600080fd5b505af1158015613de0573d6000803e3d6000fd5b5050603c5462010000900460ff169150613e1d9050576000613e03848484613f1c565b9050613e1b60415482613e1691906158c3565b613824565b505b7f41d90e25634e59cdc487695ce90710379a58f86f34cd95ae7e104a526aac04b9338989898989604051613e5696959493929190615591565b60405180910390a15050505050505050565b60606000612e1383614cc6565b6001600160a01b0381166000908152600183016020526040812054151561132b565b60008054610100900460ff1615613ede578160ff166001148015613eba5750303b155b613ed65760405162461bcd60e51b8152600401610996906156f1565b5060006128f6565b60005460ff808416911610613f055760405162461bcd60e51b8152600401610996906156f1565b506000805460ff191660ff831617905560016128f6565b82516000908190815b81811015613f9c576000878281518110613f4f57634e487b7160e01b600052603260045260246000fd5b602002602001015190506000613f65823061343e565b90508015613f8757613f7a8888858585612b2c565b613f8490866158c3565b94505b50508080613f9490615ae6565b915050613f25565b509095945050505050565b6000826000018281548110613fcc57634e487b7160e01b600052603260045260246000fd5b9060005260206000200154905092915050565b60008084848151811061400257634e487b7160e01b600052603260045260246000fd5b602002602001015190508060001415612e105761401e83614306565b90508085858151811061404157634e487b7160e01b600052603260045260246000fd5b6020908102919091010152949350505050565b60008084848151811061407757634e487b7160e01b600052603260045260246000fd5b602002602001015190508060001415612e1057506001600160a01b0382166000908152603b60205260409020548451819086908690811061404157634e487b7160e01b600052603260045260246000fd5b6000806140d58486615a0f565b90506140e183826158db565b95945050505050565b6000806140f78386615a0f565b90506140e184826158db565b604760009054906101000a90046001600160a01b03166001600160a01b03166345153af86040518163ffffffff1660e01b815260040160206040518083038186803b15801561415157600080fd5b505afa158015614165573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061418991906153e5565b156141c85760405162461bcd60e51b815260206004820152600f60248201526e697320646973747269627574696e6760881b6044820152606401610996565b8151815181158015906141da57508082145b61424c5760405162461bcd60e51b815260206004820152603860248201527f41737365747320616e6420616d6f756e7473206d75737420626520657175616c60448201527f20696e206c656e67746820616e64206e6f7420656d70747900000000000000006064820152608401610996565b60005b828110156127315761428785828151811061427a57634e487b7160e01b600052603260045260246000fd5b60200260200101516125fb565b60008482815181106142a957634e487b7160e01b600052603260045260246000fd5b6020026020010151116142f45760405162461bcd60e51b81526020600482015260136024820152720416d6f756e74206d757374206265206774203606c1b6044820152606401610996565b806142fe81615ae6565b91505061424f565b6043546040516315d5220f60e31b81526001600160a01b038381166004830152600092169063aea910789060240160206040518083038186803b15801561434c57600080fd5b505afa158015614360573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128f3919061541d565b60006143d9826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316614d229092919063ffffffff16565b80519091501561104657808060200190518101906143f791906153e5565b6110465760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610996565b600061132b8383614d31565b8015806144eb5750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e9060440160206040518083038186803b1580156144b157600080fd5b505afa1580156144c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144e9919061541d565b155b6145565760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b6064820152608401610996565b6040516001600160a01b03831660248201526044810182905261104690849063095ea7b360e01b90606401613401565b8451600090869082816001600160401b038111156145b457634e487b7160e01b600052604160045260246000fd5b6040519080825280602002602001820160405280156145dd578160200160208202803683370190505b5090506000805b8381101561472a57600085828151811061460e57634e487b7160e01b600052603260045260246000fd5b6020026020010151905061462c816036613e7590919063ffffffff16565b156147175760475460009061464b9083906001600160a01b031661343e565b905080156147155760006146628d8d868686612b2c565b9050808f11156146b85761467681866158c3565b9450808f6146849190615a2e565b9e50818685815181106146a757634e487b7160e01b600052603260045260246000fd5b602002602001018181525050614713565b6146c28f866158c3565b9450808f836146d19190615a0f565b6146db91906158db565b8685815181106146fb57634e487b7160e01b600052603260045260246000fd5b60200260200101818152505060009e5050505061472a565b505b505b508061472281615ae6565b9150506145e4565b50801561484957604754604051637615eab160e11b81526001600160a01b039091169063ec2bd56290614763908790869060040161564b565b600060405180830381600087803b15801561477d57600080fd5b505af1158015614791573d6000803e3d6000fd5b5050505060006147a2828989612da2565b6048546047546040516329460cc560e11b81526001600160a01b03918216600482015260248101849052929350169063528c198a90604401600060405180830381600087803b1580156147f457600080fd5b505af1158015614808573d6000803e3d6000fd5b505050507f07afc15fb70b2f450b68377bcdb1f517c3b24d4f8f10e18f02635e8771281ac182868560405161483f93929190615776565b60405180910390a1505b9a9950505050505050505050565b6000805b604654811015614a865760006046828154811061488857634e487b7160e01b600052603260045260246000fd5b6000918252602090912001546001600160a01b03169050806148aa5750614a86565b6001600160a01b038116600090815260456020526040902060010154806148d2575050614a74565b6000818611156148ef5750806148e88187615a2e565b9550614916565b8161490287670de0b6b3a76400006158c3565b1061490e575080614911565b50845b600095505b60405163895a748560e01b815260048101829052602481018390526000604482018190529081906001600160a01b0386169063895a748590606401600060405180830381600087803b15801561496b57600080fd5b505af115801561497f573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526149a791908101906152c1565b91509150846001600160a01b03167f8784f8bc43bb3cadc89640d1bde1d352aaf5dbb424e50a2bd4c642111409bf7d848685856040516149ea94939291906157ea565b60405180910390a26001600160a01b0385166000908152604560205260408120600101549085614a1a8684615a0f565b614a2491906158db565b9050614a308183615a2e565b6001600160a01b038816600090815260456020526040902060010155614a56818a6158c3565b985060008a11614a6c5750505050505050614a86565b505050505050505b80614a7e81615ae6565b91505061485b565b508060416000828254614a999190615a2e565b90915550505050565b82516060906000816001600160401b03811115614acf57634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015614af8578160200160208202803683370190505b50905060005b82811015614bf6576000878281518110614b2857634e487b7160e01b600052603260045260246000fd5b602002602001015190506000614b3e823061343e565b90508015614be1576000614b558989868686612b2c565b90508a8110614ba75780614b698c84615a0f565b614b7391906158db565b858581518110614b9357634e487b7160e01b600052603260045260246000fd5b602002602001018181525050505050614bf6565b81858581518110614bc857634e487b7160e01b600052603260045260246000fd5b6020908102919091010152614bdd818c615a2e565b9a50505b50508080614bee90615ae6565b915050614afe565b509695505050505050565b82516000908190815b81811015614cba576000888281518110614c3457634e487b7160e01b600052603260045260246000fd5b602002602001015190506000811115614ca7576000888381518110614c6957634e487b7160e01b600052603260045260246000fd5b602002602001015190506000614c828989868587612b2c565b9050614c8e81876158c3565b9550614ca46001600160a01b03831633856137f4565b50505b5080614cb281615ae6565b915050614c0a565b50909695505050505050565b606081600001805480602002602001604051908101604052809291908181526020018280548015614d1657602002820191906000526020600020905b815481526020019060010190808311614d02575b50505050509050919050565b6060612e108484600085614d3d565b600061132b8383613e75565b606082471015614d9e5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610996565b6001600160a01b0385163b614df55760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610996565b600080866001600160a01b03168587604051614e1191906154f4565b60006040518083038185875af1925050503d8060008114614e4e576040519150601f19603f3d011682016040523d82523d6000602084013e614e53565b606091505b5091509150614e63828286614e6e565b979650505050505050565b60608315614e7d575081612e13565b825115614e8d5782518084602001fd5b8160405162461bcd60e51b815260040161099691906156a6565b600082601f830112614eb7578081fd5b81356020614ecc614ec7836158a0565b615870565b80838252828201915082860187848660051b8901011115614eeb578586fd5b855b85811015614f12578135614f0081615b2d565b84529284019290840190600101614eed565b5090979650505050505050565b600082601f830112614f2f578081fd5b81356020614f3f614ec7836158a0565b80838252828201915082860187848660051b8901011115614f5e578586fd5b855b85811015614f1257813584529284019290840190600101614f60565b600082601f830112614f8c578081fd5b81516020614f9c614ec7836158a0565b80838252828201915082860187848660051b8901011115614fbb578586fd5b855b85811015614f1257815184529284019290840190600101614fbd565b600082601f830112614fe9578081fd5b81356001600160401b0381111561500257615002615b17565b615015601f8201601f1916602001615870565b818152846020838601011115615029578283fd5b816020850160208301379081016020019190915292915050565b600060a08284031215615054578081fd5b61505e60a0615870565b9050813561506b81615b2d565b8152602082013560ff8116811461508157600080fd5b602082015260408201356001600160401b0381111561509f57600080fd5b6150ab84828501614fd9565b604083015250606082013560608201526080820135608082015292915050565b6000602082840312156150dc578081fd5b8135612e1381615b2d565b600080600080608085870312156150fc578283fd5b843561510781615b2d565b9350602085013561511781615b2d565b9250604085013561512781615b2d565b9150606085013561513781615b2d565b939692955090935050565b60008060008060808587031215615157578384fd5b843561516281615b2d565b9350602085013561517281615b2d565b92506040850135915060608501356001600160401b03811115615193578182fd5b61519f87828801615043565b91505092959194509250565b6000806000604084860312156151bf578081fd5b83356151ca81615b2d565b925060208401356001600160401b03808211156151e5578283fd5b818601915086601f8301126151f8578283fd5b813581811115615206578384fd5b8760208260051b850101111561521a578384fd5b6020830194508093505050509250925092565b600080600060608486031215615241578081fd5b833561524c81615b2d565b95602085013595506040909401359392505050565b60008060408385031215615273578182fd5b82356001600160401b0380821115615289578384fd5b61529586838701614ea7565b935060208501359150808211156152aa578283fd5b506152b785828601614f1f565b9150509250929050565b600080604083850312156152d3578182fd5b82516001600160401b03808211156152e9578384fd5b818501915085601f8301126152fc578384fd5b8151602061530c614ec7836158a0565b8083825282820191508286018a848660051b890101111561532b578889fd5b8896505b8487101561535657805161534281615b2d565b83526001969096019591830191830161532f565b509188015191965090935050508082111561536f578283fd5b506152b785828601614f7c565b600080600060608486031215615390578081fd5b83356001600160401b03808211156153a6578283fd5b6153b287838801614ea7565b945060208601359150808211156153c7578283fd5b506153d486828701614f1f565b925050604084013590509250925092565b6000602082840312156153f6578081fd5b81518015158114612e13578182fd5b600060208284031215615416578081fd5b5035919050565b60006020828403121561542e578081fd5b5051919050565b60008060408385031215615447578182fd5b50508035926020909101359150565b6000815180845260208085019450808401835b8381101561548e5781516001600160a01b031687529582019590820190600101615469565b509495945050505050565b6000815180845260208085019450808401835b8381101561548e578151875295820195908201906001016154ac565b600081518084526154e0816020860160208601615aba565b601f01601f19169290920160200192915050565b60008251615506818460208701615aba565b9190910192915050565b6001600160a01b038516815260806020820181905260009061553490830186615456565b82810360408401526155468186615499565b91505082606083015295945050505050565b600060018060a01b03861682528460208301526080604083015261557f6080830185615456565b8281036060840152614e638185615499565b600060018060a01b038816825286602083015285604083015284606083015260c060808301526155c460c0830185615456565b82810360a0840152612b648185615499565b600060018060a01b03808716835260ff8616602084015260e0604084015261560160e08401866154c8565b9150835160608401528060208501511660808401528060408501511660a08401528060608501511660c08401525095945050505050565b60006020825261132b6020830184615456565b60006040825261565e6040830185615456565b82810360208401526140e18185615499565b6000606082526156836060830186615456565b82810360208401526156958186615499565b915050826040830152949350505050565b60006020825261132b60208301846154c8565b602080825260029082015261105160f21b604082015260600190565b602080825260029082015261455360f01b604082015260600190565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b60008482526060602083015261578f6060830185615456565b82810360408401526157a18185615499565b9695505050505050565b6000858252608060208301526157c46080830186615456565b82810360408401526157d68186615499565b90508281036060840152614e638185615499565b60008582528460208301526080604083015261557f6080830185615456565b600088825287602083015286604083015285606083015260e0608083015261583460e0830186615456565b82810360a08401526158468186615499565b9150508260c083015298975050505050505050565b60008235607e19833603018112615506578182fd5b604051601f8201601f191681016001600160401b038111828210171561589857615898615b17565b604052919050565b60006001600160401b038211156158b9576158b9615b17565b5060051b60200190565b600082198211156158d6576158d6615b01565b500190565b6000826158f657634e487b7160e01b81526012600452602481fd5b500490565b80825b600180861161590d5750615938565b81870482111561591f5761591f615b01565b8086161561592c57918102915b9490941c9380026158fe565b94509492505050565b600061132b600019848460008261595a57506001612e13565b8161596757506000612e13565b816001811461597d5760028114615987576159b4565b6001915050612e13565b60ff84111561599857615998615b01565b6001841b9150848211156159ae576159ae615b01565b50612e13565b5060208310610133831016604e8410600b84101617156159e7575081810a838111156159e2576159e2615b01565b612e13565b6159f484848460016158fb565b808604821115615a0657615a06615b01565b02949350505050565b6000816000190483118215151615615a2957615a29615b01565b500290565b600082821015615a4057615a40615b01565b500390565b600060808236031215615a56578081fd5b615a606080615870565b8235615a6b81615b2d565b81526020830135615a7b81615b2d565b60208201526040838101359082015260608301356001600160401b03811115615aa2578283fd5b615aae36828601615043565b60608301525092915050565b60005b83811015615ad5578181015183820152602001615abd565b838111156134385750506000910152565b6000600019821415615afa57615afa615b01565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b03811681146125e657600080fdfea2646970667358221220aa1cd7ac66af40f91b156c90beed3b8f85c70703e2ce1670baa42cdc7d53409e64736f6c63430008030033
Deployed Bytecode
0x60806040526004361061027d5760003560e01c80637af690971161014f578063b390c0ab116100c1578063d4c3eea01161007a578063d4c3eea01461078b578063e5f36762146107a0578063e6f2e598146107c0578063f8c8765e146107e0578063fc0cfeee14610800578063fc7b9c18146108205761027d565b8063b390c0ab146106db578063b49a60bb14610709578063bca9a47e1461072b578063c4b9737014610740578063cd5a7e9e14610755578063ce7f8cff1461076b5761027d565b80639fb0fbc5116101135780639fb0fbc51461063a578063a688b5d114610650578063a819e6ef14610670578063af14052c14610690578063afddbb58146106a5578063b1d061ab146106c55761027d565b80637af69097146105d55780637e428dac146105c05780638e510b52146105f557806391b9a4181461060b5780639c311dbb146106255761027d565b806338582a3f116101f35780635e2a0023116101ac5780635e2a00231461052a57806361d027b31461054a57806362518ddf1461056a5780636618231f1461058a57806367715935146105a05780636c3e2e0a146105c05761027d565b806338582a3f1461043e57806339ebf8231461045357806352d38e5d146104ca57806353ca9f24146104e057806354f1a073146105005780635646d0ec146105155761027d565b80631abb0a4a116102455780631abb0a4a146103825780631e8de77b14610399578063207134b0146103b95780632b83cccd146103cf5780632ed60f2c146103ef5780633403c2fc1461040f5761027d565b806301e1d114146102c357806309f6442c146102eb5780630d8e6e2c14610301578063119e3c7014610335578063178522641461036d575b7f3d78d3961e16fde088e2e26c1cfa163f5f8bb870709088dd68c87eb4091137e2366000803760008036600084545af43d6000803e8080156102be573d6000f35b3d6000fd5b3480156102cf57600080fd5b506102d8610836565b6040519081526020015b60405180910390f35b3480156102f757600080fd5b506102d860405481565b34801561030d57600080fd5b5060408051808201825260058152640312e312e360dc1b602082015290516102e291906156a6565b34801561034157600080fd5b50604854610355906001600160a01b031681565b6040516001600160a01b0390911681526020016102e2565b34801561037957600080fd5b506102d8610852565b34801561038e57600080fd5b50610397610916565b005b3480156103a557600080fd5b506103976103b4366004615261565b61102f565b3480156103c557600080fd5b506102d8603f5481565b3480156103db57600080fd5b506103976103ea36600461522d565b61104b565b3480156103fb57600080fd5b506102d861040a366004615261565b61131f565b34801561041b57600080fd5b50603c5461042e90610100900460ff1681565b60405190151581526020016102e2565b34801561044a57600080fd5b506102d8611334565b34801561045f57600080fd5b506104a061046e3660046150cb565b604560205260009081526040902080546001820154600283015460038401546004909401549293919290919060ff1685565b6040805195865260208601949094529284019190915260608301521515608082015260a0016102e2565b3480156104d657600080fd5b506102d8603d5481565b3480156104ec57600080fd5b50603c5461042e9062010000900460ff1681565b34801561050c57600080fd5b506102d8611341565b34801561052157600080fd5b5061039761134b565b34801561053657600080fd5b506102d861054536600461537c565b611711565b34801561055657600080fd5b50604254610355906001600160a01b031681565b34801561057657600080fd5b50610355610585366004615405565b61193a565b34801561059657600080fd5b506102d860505481565b3480156105ac57600080fd5b50603354610355906001600160a01b031681565b3480156105cc57600080fd5b506102d8611964565b3480156105e157600080fd5b50604754610355906001600160a01b031681565b34801561060157600080fd5b506102d8603e5481565b34801561061757600080fd5b50603c5461042e9060ff1681565b34801561063157600080fd5b506102d861196e565b34801561064657600080fd5b506102d8604d5481565b34801561065c57600080fd5b50604454610355906001600160a01b031681565b34801561067c57600080fd5b5061039761068b3660046151ab565b611bbc565b34801561069c57600080fd5b50610397612160565b3480156106b157600080fd5b506102d86106c0366004615142565b61223b565b3480156106d157600080fd5b506102d8604f5481565b3480156106e757600080fd5b506106fb6106f6366004615435565b6122da565b6040516102e292919061564b565b34801561071557600080fd5b5061071e612578565b6040516102e29190615638565b34801561073757600080fd5b5061071e612584565b34801561074c57600080fd5b5061071e612590565b34801561076157600080fd5b506102d8604e5481565b34801561077757600080fd5b506103976107863660046150cb565b61259a565b34801561079757600080fd5b506102d86125e9565b3480156107ac57600080fd5b506103976107bb3660046150cb565b6125fb565b3480156107cc57600080fd5b50604354610355906001600160a01b031681565b3480156107ec57600080fd5b506103976107fb3660046150e7565b61264a565b34801561080c57600080fd5b5061039761081b3660046150cb565b612738565b34801561082c57600080fd5b506102d860415481565b600060415461084361281a565b61084d91906158c3565b905090565b60008061085f60346128e9565b905060005b818110156109115760006108796034836128fb565b6001600160a01b031663efbb5cb06040518163ffffffff1660e01b815260040160206040518083038186803b1580156108b157600080fd5b505afa1580156108c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108e9919061541d565b905080156108fe576108fb81856158c3565b93505b508061090981615ae6565b915050610864565b505090565b6033546040516311aec98d60e01b81523360048201526001600160a01b03909116906311aec98d90602401600060405180830381600087803b15801561095b57600080fd5b505af115801561096f573d6000803e3d6000fd5b505050506002600154141561099f5760405162461bcd60e51b81526004016109969061573f565b60405180910390fd5b6002600155603c5460ff166109e05760405162461bcd60e51b815260206004820152600760248201526620a21027ab22a960c91b6044820152606401610996565b60006109ea612907565b80519091506000816001600160401b03811115610a1757634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015610a40578160200160208202803683370190505b5090506000826001600160401b03811115610a6b57634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015610a94578160200160208202803683370190505b5090506000610aa4856000612913565b5050905060008060008060005b88811015610bf35760008a8281518110610adb57634e487b7160e01b600052603260045260246000fd5b60200260200101519050610b178989848460496000876001600160a01b03166001600160a01b0316815260200190815260200160002054612b2c565b610b2190876158c3565b9550610b5589898484604a6000876001600160a01b03166001600160a01b0316815260200190815260200160002054612b2c565b610b5f90866158c3565b9450610b95898984848b8781518110610b8857634e487b7160e01b600052603260045260246000fd5b6020026020010151612b2c565b610b9f90856158c3565b9350610bd389898484604b6000876001600160a01b03166001600160a01b0316815260200190815260200160002054612b2c565b610bdd90846158c3565b9250508080610beb90615ae6565b915050610ab1565b50604c546041546000610c0685836158c3565b90506000610c1485856158c3565b905060008086610c248b8a6158c3565b1015610c425789610c358989615a2e565b610c3f9190615a2e565b90505b610c4c8a84615a2e565b610c56828b6158c3565b1115610c745780610c678b85615a2e565b610c719190615a2e565b98505b82841115610ccc576000610c888486615a2e565b90508a15610cc65781610c9b8b8d6158c3565b610ca591906158c3565b610caf8c83615a0f565b610cb991906158db565b610cc3908c6158c3565b92505b50610d18565b6000610cd88585615a2e565b90508a15610d165781610ceb8b8d6158c3565b610cf591906158c3565b610cff8c83615a0f565b610d0991906158db565b610d13908c615a2e565b92505b505b60485460408051633a98ef3960e01b815290516000926001600160a01b031691633a98ef39916004808301926020929190829003018186803b158015610d5d57600080fd5b505afa158015610d71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d95919061541d565b603c5490915062010000900460ff16610dbe57610dbb610db58487615a2e565b82612b71565b90505b8215610e4d576000610dda84610dd48189615a2e565b84612da2565b90508015610e4b576048546047546040516329460cc560e11b81526001600160a01b0391821660048201526024810184905291169063528c198a90604401600060405180830381600087803b158015610e3257600080fd5b505af1158015610e46573d6000803e3d6000fd5b505050505b505b50506000604c81905590505b8c811015610ecf5760008e8281518110610e8357634e487b7160e01b600052603260045260246000fd5b6020908102919091018101516001600160a01b03166000908152604a82526040808220829055604b83528082208290556049909252908120555080610ec781615ae6565b915050610e59565b50604760009054906101000a90046001600160a01b03166001600160a01b03166345153af86040518163ffffffff1660e01b815260040160206040518083038186803b158015610f1e57600080fd5b505afa158015610f32573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f5691906153e5565b610fc357604760009054906101000a90046001600160a01b03166001600160a01b0316636b5b53716040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610faa57600080fd5b505af1158015610fbe573d6000803e3d6000fd5b505050505b603c805460ff19169055604080518981526020810189905290810184905260608101839052608081018290527fcba28a6e335abfe9107150a5b5d2cce58719830735abd62327b9dbc8055fa9ba9060a00160405180910390a15050600180555050505050505050505050565b336110398161259a565b6110463384846000612e1a565b505050565b6033546040516311aec98d60e01b81523360048201526001600160a01b03909116906311aec98d90602401600060405180830381600087803b15801561109057600080fd5b505af11580156110a4573d6000803e3d6000fd5b50505050826110b28161259a565b600260015414156110d55760405162461bcd60e51b81526004016109969061573f565b600260019081556001600160a01b038516600090815260456020526040902001548084111561110357600080fd5b60405163895a748560e01b815260048101859052602481018290526044810184905260009081906001600160a01b0388169063895a748590606401600060405180830381600087803b15801561115857600080fd5b505af115801561116c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261119491908101906152c1565b603c54919350915060ff161561125e57815160005b8181101561125b5760008382815181106111d357634e487b7160e01b600052603260045260246000fd5b6020026020010151905060008111156112485780604a600087858151811061120b57634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600082825461124291906158c3565b90915550505b508061125381615ae6565b9150506111a9565b50505b6001600160a01b03871660009081526045602052604081206001015490846112868984615a0f565b61129091906158db565b905061129c8183615a2e565b6001600160a01b038a16600090815260456020526040812060010191909155604180548392906112cd908490615a2e565b90915550506040517f72dfda45f3c6c752a1cbef9d63f47877b3c19dbc227919bcfbbc26673bc96e1090611308908b908b9088908890615558565b60405180910390a150506001805550505050505050565b600061132b8383613117565b90505b92915050565b60006041546108436132da565b600061084d6132da565b6033546040516311aec98d60e01b81523360048201526001600160a01b03909116906311aec98d90602401600060405180830381600087803b15801561139057600080fd5b505af11580156113a4573d6000803e3d6000fd5b5050603c5460ff161591506113cd90505760405162461bcd60e51b8152600401610996906156b9565b603c54610100900460ff16156113f55760405162461bcd60e51b8152600401610996906156d5565b600260015414156114185760405162461bcd60e51b81526004016109969061573f565b60026001908155603c805460ff191690911790556000611436612907565b90506000806000611448846001612913565b604154929550909350915081156116c05784516000816001600160401b0381111561148357634e487b7160e01b600052604160045260246000fd5b6040519080825280602002602001820160405280156114ac578160200160208202803683370190505b5090506000826001600160401b038111156114d757634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015611500578160200160208202803683370190505b5090506000805b8481101561159f5760008a828151811061153157634e487b7160e01b600052603260045260246000fd5b6020026020010151905060008a838151811061155d57634e487b7160e01b600052603260045260246000fd5b60200260200101519050600081111561158a5761157d8686858585612b2c565b61158790856158c3565b93505b5050808061159790615ae6565b915050611507565b5060006115ac86836158c3565b90506000604860009054906101000a90046001600160a01b03166001600160a01b0316633a98ef396040518163ffffffff1660e01b815260040160206040518083038186803b1580156115fe57600080fd5b505afa158015611612573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611636919061541d565b603c5490915062010000900460ff16611655576116538282612b71565b505b604754604051637615eab160e11b81526001600160a01b039091169063ec2bd56290611687908e908d9060040161564b565b600060405180830381600087803b1580156116a157600080fd5b505af11580156116b5573d6000803e3d6000fd5b505050505050505050505b604c81905560405181907fbe4b7098b96c8f167582de3b9de443834380e1265a9a4453dbcf620e5ae63cac906116fd9083908990899089906157ab565b60405180910390a150506001805550505050565b603c54600090610100900460ff161561173c5760405162461bcd60e51b8152600401610996906156d5565b603c5460ff161561175f5760405162461bcd60e51b8152600401610996906156b9565b600260015414156117825760405162461bcd60e51b81526004016109969061573f565b600260015560006117938585613117565b905082156117eb57828110156117eb5760405162461bcd60e51b815260206004820152601e60248201527f4d696e7420616d6f756e74206c6f776572207468616e206d696e696d756d00006044820152606401610996565b60005b855181101561188c5761187a33604760009054906101000a90046001600160a01b031687848151811061183157634e487b7160e01b600052603260045260246000fd5b602002602001015189858151811061185957634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b03166133cd909392919063ffffffff16565b8061188481615ae6565b9150506117ee565b506047546040516340c10f1960e01b8152336004820152602481018390526001600160a01b03909116906340c10f1990604401600060405180830381600087803b1580156118d957600080fd5b505af11580156118ed573d6000803e3d6000fd5b505050507f62a0e51e012d92909587a2f2aa7f4016592ddf30135d505e2e0038b7f446a5bd338686846040516119269493929190615510565b60405180910390a160018055949350505050565b6046818154811061194a57600080fd5b6000918252602090912001546001600160a01b0316905081565b600061084d61281a565b600080604860009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156119bf57600080fd5b505afa1580156119d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119f7919061541d565b9050670de0b6b3a76400008115611bb6576000611a12612907565b80519091506000816001600160401b03811115611a3f57634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015611a68578160200160208202803683370190505b5090506000826001600160401b03811115611a9357634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015611abc578160200160208202803683370190505b50905060008060005b85811015611b76576000878281518110611aef57634e487b7160e01b600052603260045260246000fd5b602002602001015190506000611b05823061343e565b90508015611b2757611b1a8787858585612b2c565b611b2490866158c3565b94505b506001600160a01b0381166000908152604960205260409020548015611b6157611b548787858585612b2c565b611b5e90856158c3565b93505b50508080611b6e90615ae6565b915050611ac5565b50878160415484611b8791906158c3565b611b919190615a2e565b611ba390670de0b6b3a7640000615a0f565b611bad91906158db565b96505050505050505b91505090565b6033546040516311aec98d60e01b81523360048201526001600160a01b03909116906311aec98d90602401600060405180830381600087803b158015611c0157600080fd5b505af1158015611c15573d6000803e3d6000fd5b5050603c54610100900460ff16159150611c4390505760405162461bcd60e51b8152600401610996906156d5565b82611c4d8161259a565b60026001541415611c705760405162461bcd60e51b81526004016109969061573f565b600260015560008080611c848787876134bb565b925092509250600080886001600160a01b031663970d44ee6040518163ffffffff1660e01b815260040160206040518083038186803b158015611cc657600080fd5b505afa158015611cda573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cfe91906153e5565b905080158015611d0f575060018451115b15611e5f5760015b8451811015611e5d57848181518110611d4057634e487b7160e01b600052603260045260246000fd5b602002602001015160001415611d5557611e4b565b848381518110611d7557634e487b7160e01b600052603260045260246000fd5b602002602001015160001415611d8d57809250611e4b565b848381518110611dad57634e487b7160e01b600052603260045260246000fd5b6020026020010151848281518110611dd557634e487b7160e01b600052603260045260246000fd5b6020026020010151611de79190615a0f565b858281518110611e0757634e487b7160e01b600052603260045260246000fd5b6020026020010151858581518110611e2f57634e487b7160e01b600052603260045260246000fd5b6020026020010151611e419190615a0f565b1115611e4b578092505b80611e5581615ae6565b915050611d17565b505b6000838381518110611e8157634e487b7160e01b600052603260045260246000fd5b602002602001015190506000858481518110611ead57634e487b7160e01b600052603260045260246000fd5b60200260200101519050600080600090505b8651811015612094576000878281518110611eea57634e487b7160e01b600052603260045260246000fd5b6020026020010151905060008111156120815760008a8381518110611f1f57634e487b7160e01b600052603260045260246000fd5b6020026020010151905086158015611f5e575060008a8481518110611f5457634e487b7160e01b600052603260045260246000fd5b6020026020010151115b15611fd15784868b8581518110611f8557634e487b7160e01b600052603260045260246000fd5b6020026020010151611f979190615a0f565b611fa191906158db565b915081898481518110611fc457634e487b7160e01b600052603260045260246000fd5b6020026020010181815250505b60435460405163ebd6d95560e01b81526001600160a01b038381166004830152602482018590529091169063ebd6d9559060440160206040518083038186803b15801561201d57600080fd5b505afa158015612031573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612055919061541d565b61205f90856158c3565b935061207f8f83836001600160a01b03166137f49092919063ffffffff16565b505b508061208c81615ae6565b915050611ebf565b50604051630e7949d360e21b81528c906001600160a01b038216906339e5274c906120c5908c908b9060040161564b565b600060405180830381600087803b1580156120df57600080fd5b505af11580156120f3573d6000803e3d6000fd5b505050506060806121068f838387612e1a565b8e6001600160a01b03167fa320f26f9e050a2dbc872470ba0413f8dbb2134c86680cfb6e911c68bb6f911b8c8b8760405161214393929190615670565b60405180910390a250506001805550505050505050505050505050565b603c54610100900460ff16156121885760405162461bcd60e51b8152600401610996906156d5565b603c5460ff16156121ab5760405162461bcd60e51b8152600401610996906156b9565b603c5462010000900460ff16156121e95760405162461bcd60e51b8152602060048201526002602482015261052560f41b6044820152606401610996565b6002600154141561220c5760405162461bcd60e51b81526004016109969061573f565b600260015560415460009061221f61281a565b61222991906158c3565b905061223481613824565b5060018055565b6033546040516311aec98d60e01b81523360048201526000916001600160a01b0316906311aec98d90602401600060405180830381600087803b15801561228157600080fd5b505af1158015612295573d6000803e3d6000fd5b50505050600260015414156122bc5760405162461bcd60e51b81526004016109969061573f565b60026001556122cd858585856138ad565b6001805595945050505050565b603c546060908190610100900460ff16156123075760405162461bcd60e51b8152600401610996906156d5565b603c5460ff161561232a5760405162461bcd60e51b8152600401610996906156b9565b6002600154141561234d5760405162461bcd60e51b81526004016109969061573f565b60026001556048546040516370a0823160e01b81523360048201526000916001600160a01b0316906370a082319060240160206040518083038186803b15801561239657600080fd5b505afa1580156123aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123ce919061541d565b90506000851180156123e05750808511155b61241e5760405162461bcd60e51b815260206004820152600f60248201526e0aaa688d240dcdee840cadcdeeaced608b1b6044820152606401610996565b6000612428612907565b9050600081516001600160401b0381111561245357634e487b7160e01b600052604160045260246000fd5b60405190808252806020026020018201604052801561247c578160200160208202803683370190505b509050600082516001600160401b038111156124a857634e487b7160e01b600052604160045260246000fd5b6040519080825280602002602001820160405280156124d1578160200160208202803683370190505b5090506000806124e48a87878787613b3e565b9150915060006124f682878787613d4f565b919a5098509050891561255357898110156125535760405162461bcd60e51b815260206004820152601960248201527f616d6f756e74206c6f776572207468616e206d696e696d756d000000000000006044820152606401610996565b6125638b82858c8c8b8b8b613d80565b50505050505050600180819055509250929050565b606061084d6034613e68565b606061084d6036613e68565b606061084d612907565b6125a5603482613e75565b6125e65760405162461bcd60e51b81526020600482015260126024820152711cdd1c985d1959de481b9bdd08195e1a5cdd60721b6044820152606401610996565b50565b60006125f3610852565b61084361281a565b612606603682613e75565b6125e65760405162461bcd60e51b8152602060048201526015602482015274151a1948185cdcd95d081b9bdd081cdd5c1c1bdc9d605a1b6044820152606401610996565b60006126566001613e97565b9050801561266e576000805461ff0019166101001790555b603380546001600160a01b038781166001600160a01b03199283161790925560428054821687841617905560448054821686841617905560438054909116918416919091179055603c805462ff00001916905560006040556001603d5562093a80604e55670de0b6b3a7640000604d55683635c9adc5dea00000604f558015612731576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050565b603354604051630881b00560e41b81523360048201526001600160a01b039091169063881b00509060240160006040518083038186803b15801561277b57600080fd5b505afa15801561278f573d6000803e3d6000fd5b505050506001600160a01b0381163b6127f65760405162461bcd60e51b8152602060048201526024808201527f6e657720696d706c656d656e746174696f6e206973206e6f74206120636f6e746044820152631c9858dd60e21b6064820152608401610996565b7f3d78d3961e16fde088e2e26c1cfa163f5f8bb870709088dd68c87eb4091137e255565b600080612825612907565b80519091506000816001600160401b0381111561285257634e487b7160e01b600052604160045260246000fd5b60405190808252806020026020018201604052801561287b578160200160208202803683370190505b5090506000826001600160401b038111156128a657634e487b7160e01b600052604160045260246000fd5b6040519080825280602002602001820160405280156128cf578160200160208202803683370190505b50905060006128df858484613f1c565b9550505050505090565b60006128f3825490565b90505b919050565b600061132b8383613fa7565b606061084d6038613e68565b606080600080855190506000816001600160401b0381111561294557634e487b7160e01b600052604160045260246000fd5b60405190808252806020026020018201604052801561296e578160200160208202803683370190505b5090506000826001600160401b0381111561299957634e487b7160e01b600052604160045260246000fd5b6040519080825280602002602001820160405280156129c2578160200160208202803683370190505b5090506000805b84811015612b1d5760008a82815181106129f357634e487b7160e01b600052603260045260246000fd5b6020026020010151905060008a8015612a125750612a12603683613e75565b15612a8657604754612a2e9083906001600160a01b031661343e565b90508015612a865780868481518110612a5757634e487b7160e01b600052603260045260246000fd5b6020908102919091018101919091526001600160a01b0383166000908152604990915260409020819055600193505b6000612a92833061343e565b90508015612ac85780868581518110612abb57634e487b7160e01b600052603260045260246000fd5b6020026020010181815250505b8b8015612ade57506000612adc83836158c3565b115b15612b0757612aed82826158c3565b6001600160a01b0384166000908152604b60205260409020555b5050508080612b1590615ae6565b9150506129c9565b50909891975095509350505050565b600080612b3a878686613fdf565b90506000612b49878787614054565b90506000612b6483612b5c84600a615941565b8791906140c8565b9998505050505050505050565b600081612b7f57508061132e565b604d546000612b9b84836b033b2e3c9fd0803ce80000006140c8565b90508085118015612bce5750603d54612bb49082615a0f565b62989680612bc28388615a2e565b612bcc9190615a0f565b115b15612d9957604254603f546001600160a01b03909116908015801590612bfc57506001600160a01b03821615155b15612d2c576000612c0d8489615a2e565b90506000612710612c1e8484615a0f565b612c2891906158db565b9050808211612c845760405162461bcd60e51b815260206004820152602260248201527f466565206d757374206e6f742062652067726561746572207468616e207969656044820152611b1960f21b6064820152608401610996565b8015612d29576000612c96828b615a2e565b612ca08a84615a0f565b612caa91906158db565b90508015612d27576048546040516329460cc560e11b81526001600160a01b038781166004830152602482018490529091169063528c198a90604401600060405180830381600087803b158015612d0057600080fd5b505af1158015612d14573d6000803e3d6000fd5b505050508089612d2491906158c3565b98505b505b50505b6000612d4588886b033b2e3c9fd0803ce80000006140ea565b9050848114612d9557604d81905560408051888152602081018a90529081018290527fc6642d24d84e7f3d36ca39f5cce10e75639d9b158d5193aa350e2f900653e4c09060600160405180910390a15b5050505b50919392505050565b6000808315801590612db45750600083115b15612dd15783612dc48487615a0f565b612dce91906158db565b90505b80612e1057604d548015612dfd57612df686826b033b2e3c9fd0803ce80000006140ea565b9150612e0e565b612e0b86633b9aca00615a0f565b91505b505b90505b9392505050565b6001600160a01b0384166000908152604560209081526040808320815160a081018352815481526001820154938101849052600282015492810192909252600381015460608301526004015460ff16151560808201529190612e7d9084906158c3565b90506000866001600160a01b031663efbb5cb06040518163ffffffff1660e01b815260040160206040518083038186803b158015612eba57600080fd5b505afa158015612ece573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ef2919061541d565b905060008083831115612f1057612f098484615a2e565b9150612f25565b83831015612f2557612f228385615a2e565b90505b84608001511561302b57604e546001600160a01b038a16600090815260456020526040902054612f559042615a2e565b108015612f6e5750604f54841180612f6e5750604f5483115b15613026578115612fcf57612710856040015185612f8c9190615a0f565b612f9691906158db565b821115612fca5760405162461bcd60e51b815260206004820152600260248201526111d360f21b6044820152606401610996565b613026565b801561302657612710856060015185612fe89190615a0f565b612ff291906158db565b8111156130265760405162461bcd60e51b8152602060048201526002602482015261131360f21b6044820152606401610996565b613052565b6001600160a01b0389166000908152604560205260409020600401805460ff191660011790555b6001600160a01b0389166000908152604560205260409020600101839055604154849087906130829086906158c3565b61308c91906158c3565b6130969190615a2e565b6041556001600160a01b038916600090815260456020526040812042905586156130be575060015b896001600160a01b03167f6d35366477ec3dbdcc668ff1cf0df6df18998d6bbfbea924257ccbdfca3b1f35848488888e8e886040516131039796959493929190615809565b60405180910390a250505050505050505050565b60006131238383614103565b6000805b845181101561326457600085828151811061315257634e487b7160e01b600052603260045260246000fd5b60209081029190910101516043546040516315d5220f60e31b81526001600160a01b0380841660048301529293506000929091169063aea910789060240160206040518083038186803b1580156131a857600080fd5b505afa1580156131bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131e0919061541d565b6001600160a01b0383166000908152603b60205260409020549091506132428261320b83600a615941565b89878151811061322b57634e487b7160e01b600052603260045260246000fd5b60200260200101516140c89092919063ffffffff16565b61324c90866158c3565b9450505050808061325c90615ae6565b915050613127565b5060505480156132d257808210156132d25760405162461bcd60e51b815260206004820152602b60248201527f416d6f756e74206d757374206265206774206d696e696d756d20496e7665737460448201526a1b595b9d08105b5bdd5b9d60aa1b6064820152608401610996565b509392505050565b6000806132e5612907565b90506000805b82518110156133c657600083828151811061331657634e487b7160e01b600052603260045260246000fd5b60200260200101519050600061332c823061343e565b6047549091506000906133499084906001600160a01b031661343e565b9050600061335782846158c3565b905080156133af57600061336a85614306565b6001600160a01b0386166000908152603b602052604081205491925061339d8361339584600a615941565b8691906140c8565b90506133a9818a6158c3565b98505050505b5050505080806133be90615ae6565b9150506132eb565b5091505090565b6040516001600160a01b03808516602483015283166044820152606481018290526134389085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152614384565b50505050565b6040516370a0823160e01b81526001600160a01b038281166004830152600091908416906370a082319060240160206040518083038186803b15801561348357600080fd5b505afa158015613497573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061132b919061541d565b6060806060856001600160a01b031663adc58dd96040518163ffffffff1660e01b815260040160006040518083038186803b1580156134f957600080fd5b505afa15801561350d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261353591908101906152c1565b81519194509250806001600160401b0381111561356257634e487b7160e01b600052604160045260246000fd5b60405190808252806020026020018201604052801561358b578160200160208202803683370190505b5091508460005b81811015613697576000805b84811015613644578781815181106135c657634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b03168a8a858181106135f757634e487b7160e01b600052603260045260246000fd5b9050602002810190613609919061585b565b61361a9060408101906020016150cb565b6001600160a01b031614156136325760019150613644565b8061363c81615ae6565b91505061359e565b50806136845760405162461bcd60e51b815260206004820152600f60248201526e1d1bd51bdad95b881a5b9d985b1a59608a1b6044820152606401610996565b508061368f81615ae6565b915050613592565b5060005b828110156137e85760005b828110156137d55760008989838181106136d057634e487b7160e01b600052603260045260246000fd5b90506020028101906136e2919061585b565b6136eb90615a45565b905080602001516001600160a01b031688848151811061371b57634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b03161461373757506137c3565b600081602001516001600160a01b031682600001516001600160a01b031614156137665750604081015161378f565b60408201511561378f5761378c82600001518360200151846040015185606001516138ad565b90505b808785815181106137b057634e487b7160e01b600052603260045260246000fd5b60200260200101818152505050506137d5565b806137cd81615ae6565b9150506136a6565b50806137e081615ae6565b91505061369b565b50505093509350939050565b6040516001600160a01b03831660248201526044810182905261104690849063a9059cbb60e01b90606401613401565b60485460408051633a98ef3960e01b815290516000926001600160a01b031691633a98ef39916004808301926020929190829003018186803b15801561386957600080fd5b505afa15801561387d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138a1919061541d565b90506110468282612b71565b60006138ba603885614456565b6138eb5760405162461bcd60e51b8152602060048201526002602482015261085560f21b6044820152606401610996565b604080516080810182528481526001600160a01b038088166020830181905287821693830193909352306060830152604454919261392d929091166000614462565b604454613947906001600160a01b03888116911686614462565b60445483516020850151604080870151905163538d5ab960e11b81526001600160a01b039094169363a71ab57293613987939092909187906004016155d6565b602060405180830381600087803b1580156139a157600080fd5b505af11580156139b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139d9919061541d565b604354604051632633f08360e11b81526001600160a01b03898116600483015260248201889052888116604483015292945060009290911690634c67e1069060640160206040518083038186803b158015613a3357600080fd5b505afa158015613a47573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a6b919061541d565b905061271084608001518560600151612710613a879190615a2e565b613a919190615a2e565b613a9b9083615a0f565b613aa591906158db565b831015613ad95760405162461bcd60e51b815260206004820152600260248201526113d360f21b6044820152606401610996565b8351604080516001600160a01b0392831681528983166020820152808201889052918816606083015260808201859052517fec43bc4dddba4c8ae8d4f92f53b39989eaf64022bec70471d105647e57c7891c9181900360a00190a15050949350505050565b6000806000613b4e868686613f1c565b6041549091508890600090613b6390846158c3565b90506000604860009054906101000a90046001600160a01b03166001600160a01b0316633a98ef396040518163ffffffff1660e01b815260040160206040518083038186803b158015613bb557600080fd5b505afa158015613bc9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613bed919061541d565b604d549091508a841415613c7d57604854604051633d7ad0b760e21b81523360048201526001600160a01b039091169063f5eb42dc9060240160206040518083038186803b158015613c3e57600080fd5b505afa158015613c52573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c76919061541d565b9650613c97565b613c9484826b033b2e3c9fd0803ce80000006140ea565b96505b60405415613cc75761271060405485613cb09190615a0f565b613cba91906158db565b613cc49085615a2e565b93505b6000613ce083836b033b2e3c9fd0803ce80000006140c8565b905080613ced8587615a0f565b613cf791906158db565b9650505084841015613d2757613d1a613d108587615a2e565b8a8a8a8686614586565b613d2490856158c3565b93505b84841015613d4157613d41613d3c8587615a2e565b614857565b505050509550959350505050565b606080600080613d6188888888614aa2565b90506000613d7182898989614c01565b97999198509095505050505050565b604854604051633b9e9f0160e21b8152336004820152602481018890526001600160a01b039091169063ee7a7c0490604401600060405180830381600087803b158015613dcc57600080fd5b505af1158015613de0573d6000803e3d6000fd5b5050603c5462010000900460ff169150613e1d9050576000613e03848484613f1c565b9050613e1b60415482613e1691906158c3565b613824565b505b7f41d90e25634e59cdc487695ce90710379a58f86f34cd95ae7e104a526aac04b9338989898989604051613e5696959493929190615591565b60405180910390a15050505050505050565b60606000612e1383614cc6565b6001600160a01b0381166000908152600183016020526040812054151561132b565b60008054610100900460ff1615613ede578160ff166001148015613eba5750303b155b613ed65760405162461bcd60e51b8152600401610996906156f1565b5060006128f6565b60005460ff808416911610613f055760405162461bcd60e51b8152600401610996906156f1565b506000805460ff191660ff831617905560016128f6565b82516000908190815b81811015613f9c576000878281518110613f4f57634e487b7160e01b600052603260045260246000fd5b602002602001015190506000613f65823061343e565b90508015613f8757613f7a8888858585612b2c565b613f8490866158c3565b94505b50508080613f9490615ae6565b915050613f25565b509095945050505050565b6000826000018281548110613fcc57634e487b7160e01b600052603260045260246000fd5b9060005260206000200154905092915050565b60008084848151811061400257634e487b7160e01b600052603260045260246000fd5b602002602001015190508060001415612e105761401e83614306565b90508085858151811061404157634e487b7160e01b600052603260045260246000fd5b6020908102919091010152949350505050565b60008084848151811061407757634e487b7160e01b600052603260045260246000fd5b602002602001015190508060001415612e1057506001600160a01b0382166000908152603b60205260409020548451819086908690811061404157634e487b7160e01b600052603260045260246000fd5b6000806140d58486615a0f565b90506140e183826158db565b95945050505050565b6000806140f78386615a0f565b90506140e184826158db565b604760009054906101000a90046001600160a01b03166001600160a01b03166345153af86040518163ffffffff1660e01b815260040160206040518083038186803b15801561415157600080fd5b505afa158015614165573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061418991906153e5565b156141c85760405162461bcd60e51b815260206004820152600f60248201526e697320646973747269627574696e6760881b6044820152606401610996565b8151815181158015906141da57508082145b61424c5760405162461bcd60e51b815260206004820152603860248201527f41737365747320616e6420616d6f756e7473206d75737420626520657175616c60448201527f20696e206c656e67746820616e64206e6f7420656d70747900000000000000006064820152608401610996565b60005b828110156127315761428785828151811061427a57634e487b7160e01b600052603260045260246000fd5b60200260200101516125fb565b60008482815181106142a957634e487b7160e01b600052603260045260246000fd5b6020026020010151116142f45760405162461bcd60e51b81526020600482015260136024820152720416d6f756e74206d757374206265206774203606c1b6044820152606401610996565b806142fe81615ae6565b91505061424f565b6043546040516315d5220f60e31b81526001600160a01b038381166004830152600092169063aea910789060240160206040518083038186803b15801561434c57600080fd5b505afa158015614360573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128f3919061541d565b60006143d9826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316614d229092919063ffffffff16565b80519091501561104657808060200190518101906143f791906153e5565b6110465760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610996565b600061132b8383614d31565b8015806144eb5750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e9060440160206040518083038186803b1580156144b157600080fd5b505afa1580156144c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144e9919061541d565b155b6145565760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b6064820152608401610996565b6040516001600160a01b03831660248201526044810182905261104690849063095ea7b360e01b90606401613401565b8451600090869082816001600160401b038111156145b457634e487b7160e01b600052604160045260246000fd5b6040519080825280602002602001820160405280156145dd578160200160208202803683370190505b5090506000805b8381101561472a57600085828151811061460e57634e487b7160e01b600052603260045260246000fd5b6020026020010151905061462c816036613e7590919063ffffffff16565b156147175760475460009061464b9083906001600160a01b031661343e565b905080156147155760006146628d8d868686612b2c565b9050808f11156146b85761467681866158c3565b9450808f6146849190615a2e565b9e50818685815181106146a757634e487b7160e01b600052603260045260246000fd5b602002602001018181525050614713565b6146c28f866158c3565b9450808f836146d19190615a0f565b6146db91906158db565b8685815181106146fb57634e487b7160e01b600052603260045260246000fd5b60200260200101818152505060009e5050505061472a565b505b505b508061472281615ae6565b9150506145e4565b50801561484957604754604051637615eab160e11b81526001600160a01b039091169063ec2bd56290614763908790869060040161564b565b600060405180830381600087803b15801561477d57600080fd5b505af1158015614791573d6000803e3d6000fd5b5050505060006147a2828989612da2565b6048546047546040516329460cc560e11b81526001600160a01b03918216600482015260248101849052929350169063528c198a90604401600060405180830381600087803b1580156147f457600080fd5b505af1158015614808573d6000803e3d6000fd5b505050507f07afc15fb70b2f450b68377bcdb1f517c3b24d4f8f10e18f02635e8771281ac182868560405161483f93929190615776565b60405180910390a1505b9a9950505050505050505050565b6000805b604654811015614a865760006046828154811061488857634e487b7160e01b600052603260045260246000fd5b6000918252602090912001546001600160a01b03169050806148aa5750614a86565b6001600160a01b038116600090815260456020526040902060010154806148d2575050614a74565b6000818611156148ef5750806148e88187615a2e565b9550614916565b8161490287670de0b6b3a76400006158c3565b1061490e575080614911565b50845b600095505b60405163895a748560e01b815260048101829052602481018390526000604482018190529081906001600160a01b0386169063895a748590606401600060405180830381600087803b15801561496b57600080fd5b505af115801561497f573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526149a791908101906152c1565b91509150846001600160a01b03167f8784f8bc43bb3cadc89640d1bde1d352aaf5dbb424e50a2bd4c642111409bf7d848685856040516149ea94939291906157ea565b60405180910390a26001600160a01b0385166000908152604560205260408120600101549085614a1a8684615a0f565b614a2491906158db565b9050614a308183615a2e565b6001600160a01b038816600090815260456020526040902060010155614a56818a6158c3565b985060008a11614a6c5750505050505050614a86565b505050505050505b80614a7e81615ae6565b91505061485b565b508060416000828254614a999190615a2e565b90915550505050565b82516060906000816001600160401b03811115614acf57634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015614af8578160200160208202803683370190505b50905060005b82811015614bf6576000878281518110614b2857634e487b7160e01b600052603260045260246000fd5b602002602001015190506000614b3e823061343e565b90508015614be1576000614b558989868686612b2c565b90508a8110614ba75780614b698c84615a0f565b614b7391906158db565b858581518110614b9357634e487b7160e01b600052603260045260246000fd5b602002602001018181525050505050614bf6565b81858581518110614bc857634e487b7160e01b600052603260045260246000fd5b6020908102919091010152614bdd818c615a2e565b9a50505b50508080614bee90615ae6565b915050614afe565b509695505050505050565b82516000908190815b81811015614cba576000888281518110614c3457634e487b7160e01b600052603260045260246000fd5b602002602001015190506000811115614ca7576000888381518110614c6957634e487b7160e01b600052603260045260246000fd5b602002602001015190506000614c828989868587612b2c565b9050614c8e81876158c3565b9550614ca46001600160a01b03831633856137f4565b50505b5080614cb281615ae6565b915050614c0a565b50909695505050505050565b606081600001805480602002602001604051908101604052809291908181526020018280548015614d1657602002820191906000526020600020905b815481526020019060010190808311614d02575b50505050509050919050565b6060612e108484600085614d3d565b600061132b8383613e75565b606082471015614d9e5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610996565b6001600160a01b0385163b614df55760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610996565b600080866001600160a01b03168587604051614e1191906154f4565b60006040518083038185875af1925050503d8060008114614e4e576040519150601f19603f3d011682016040523d82523d6000602084013e614e53565b606091505b5091509150614e63828286614e6e565b979650505050505050565b60608315614e7d575081612e13565b825115614e8d5782518084602001fd5b8160405162461bcd60e51b815260040161099691906156a6565b600082601f830112614eb7578081fd5b81356020614ecc614ec7836158a0565b615870565b80838252828201915082860187848660051b8901011115614eeb578586fd5b855b85811015614f12578135614f0081615b2d565b84529284019290840190600101614eed565b5090979650505050505050565b600082601f830112614f2f578081fd5b81356020614f3f614ec7836158a0565b80838252828201915082860187848660051b8901011115614f5e578586fd5b855b85811015614f1257813584529284019290840190600101614f60565b600082601f830112614f8c578081fd5b81516020614f9c614ec7836158a0565b80838252828201915082860187848660051b8901011115614fbb578586fd5b855b85811015614f1257815184529284019290840190600101614fbd565b600082601f830112614fe9578081fd5b81356001600160401b0381111561500257615002615b17565b615015601f8201601f1916602001615870565b818152846020838601011115615029578283fd5b816020850160208301379081016020019190915292915050565b600060a08284031215615054578081fd5b61505e60a0615870565b9050813561506b81615b2d565b8152602082013560ff8116811461508157600080fd5b602082015260408201356001600160401b0381111561509f57600080fd5b6150ab84828501614fd9565b604083015250606082013560608201526080820135608082015292915050565b6000602082840312156150dc578081fd5b8135612e1381615b2d565b600080600080608085870312156150fc578283fd5b843561510781615b2d565b9350602085013561511781615b2d565b9250604085013561512781615b2d565b9150606085013561513781615b2d565b939692955090935050565b60008060008060808587031215615157578384fd5b843561516281615b2d565b9350602085013561517281615b2d565b92506040850135915060608501356001600160401b03811115615193578182fd5b61519f87828801615043565b91505092959194509250565b6000806000604084860312156151bf578081fd5b83356151ca81615b2d565b925060208401356001600160401b03808211156151e5578283fd5b818601915086601f8301126151f8578283fd5b813581811115615206578384fd5b8760208260051b850101111561521a578384fd5b6020830194508093505050509250925092565b600080600060608486031215615241578081fd5b833561524c81615b2d565b95602085013595506040909401359392505050565b60008060408385031215615273578182fd5b82356001600160401b0380821115615289578384fd5b61529586838701614ea7565b935060208501359150808211156152aa578283fd5b506152b785828601614f1f565b9150509250929050565b600080604083850312156152d3578182fd5b82516001600160401b03808211156152e9578384fd5b818501915085601f8301126152fc578384fd5b8151602061530c614ec7836158a0565b8083825282820191508286018a848660051b890101111561532b578889fd5b8896505b8487101561535657805161534281615b2d565b83526001969096019591830191830161532f565b509188015191965090935050508082111561536f578283fd5b506152b785828601614f7c565b600080600060608486031215615390578081fd5b83356001600160401b03808211156153a6578283fd5b6153b287838801614ea7565b945060208601359150808211156153c7578283fd5b506153d486828701614f1f565b925050604084013590509250925092565b6000602082840312156153f6578081fd5b81518015158114612e13578182fd5b600060208284031215615416578081fd5b5035919050565b60006020828403121561542e578081fd5b5051919050565b60008060408385031215615447578182fd5b50508035926020909101359150565b6000815180845260208085019450808401835b8381101561548e5781516001600160a01b031687529582019590820190600101615469565b509495945050505050565b6000815180845260208085019450808401835b8381101561548e578151875295820195908201906001016154ac565b600081518084526154e0816020860160208601615aba565b601f01601f19169290920160200192915050565b60008251615506818460208701615aba565b9190910192915050565b6001600160a01b038516815260806020820181905260009061553490830186615456565b82810360408401526155468186615499565b91505082606083015295945050505050565b600060018060a01b03861682528460208301526080604083015261557f6080830185615456565b8281036060840152614e638185615499565b600060018060a01b038816825286602083015285604083015284606083015260c060808301526155c460c0830185615456565b82810360a0840152612b648185615499565b600060018060a01b03808716835260ff8616602084015260e0604084015261560160e08401866154c8565b9150835160608401528060208501511660808401528060408501511660a08401528060608501511660c08401525095945050505050565b60006020825261132b6020830184615456565b60006040825261565e6040830185615456565b82810360208401526140e18185615499565b6000606082526156836060830186615456565b82810360208401526156958186615499565b915050826040830152949350505050565b60006020825261132b60208301846154c8565b602080825260029082015261105160f21b604082015260600190565b602080825260029082015261455360f01b604082015260600190565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b60008482526060602083015261578f6060830185615456565b82810360408401526157a18185615499565b9695505050505050565b6000858252608060208301526157c46080830186615456565b82810360408401526157d68186615499565b90508281036060840152614e638185615499565b60008582528460208301526080604083015261557f6080830185615456565b600088825287602083015286604083015285606083015260e0608083015261583460e0830186615456565b82810360a08401526158468186615499565b9150508260c083015298975050505050505050565b60008235607e19833603018112615506578182fd5b604051601f8201601f191681016001600160401b038111828210171561589857615898615b17565b604052919050565b60006001600160401b038211156158b9576158b9615b17565b5060051b60200190565b600082198211156158d6576158d6615b01565b500190565b6000826158f657634e487b7160e01b81526012600452602481fd5b500490565b80825b600180861161590d5750615938565b81870482111561591f5761591f615b01565b8086161561592c57918102915b9490941c9380026158fe565b94509492505050565b600061132b600019848460008261595a57506001612e13565b8161596757506000612e13565b816001811461597d5760028114615987576159b4565b6001915050612e13565b60ff84111561599857615998615b01565b6001841b9150848211156159ae576159ae615b01565b50612e13565b5060208310610133831016604e8410600b84101617156159e7575081810a838111156159e2576159e2615b01565b612e13565b6159f484848460016158fb565b808604821115615a0657615a06615b01565b02949350505050565b6000816000190483118215151615615a2957615a29615b01565b500290565b600082821015615a4057615a40615b01565b500390565b600060808236031215615a56578081fd5b615a606080615870565b8235615a6b81615b2d565b81526020830135615a7b81615b2d565b60208201526040838101359082015260608301356001600160401b03811115615aa2578283fd5b615aae36828601615043565b60608301525092915050565b60005b83811015615ad5578181015183820152602001615abd565b838111156134385750506000910152565b6000600019821415615afa57615afa615b01565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b03811681146125e657600080fdfea2646970667358221220aa1cd7ac66af40f91b156c90beed3b8f85c70703e2ce1670baa42cdc7d53409e64736f6c63430008030033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 26 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.