编译器
0.6.10+commit.00c0fcaf
文件 1 的 21:AaveLeverageStrategyExtension.sol
pragma solidity 0.6.10;
pragma experimental ABIEncoderV2;
import { Address } from "@openzeppelin/contracts/utils/Address.sol";
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { Math } from "@openzeppelin/contracts/math/Math.sol";
import { SafeCast } from "@openzeppelin/contracts/utils/SafeCast.sol";
import { SafeMath } from "@openzeppelin/contracts/math/SafeMath.sol";
import { BaseExtension } from "../lib/BaseExtension.sol";
import { IBaseManager } from "../interfaces/IBaseManager.sol";
import { IChainlinkAggregatorV3 } from "../interfaces/IChainlinkAggregatorV3.sol";
import { ILeverageModule } from "../interfaces/ILeverageModule.sol";
import { IProtocolDataProvider } from "../interfaces/IProtocolDataProvider.sol";
import { ISetToken } from "../interfaces/ISetToken.sol";
import { PreciseUnitMath } from "../lib/PreciseUnitMath.sol";
import { StringArrayUtils } from "../lib/StringArrayUtils.sol";
contract AaveLeverageStrategyExtension is BaseExtension {
using Address for address;
using PreciseUnitMath for uint256;
using SafeMath for uint256;
using SafeCast for int256;
using StringArrayUtils for string[];
enum ShouldRebalance {
NONE,
REBALANCE,
ITERATE_REBALANCE,
RIPCORD
}
struct ActionInfo {
uint256 collateralBalance;
uint256 borrowBalance;
uint256 collateralValue;
uint256 borrowValue;
uint256 collateralPrice;
uint256 borrowPrice;
uint256 setTotalSupply;
}
struct LeverageInfo {
ActionInfo action;
uint256 currentLeverageRatio;
uint256 slippageTolerance;
uint256 twapMaxTradeSize;
string exchangeName;
}
struct ContractSettings {
ISetToken setToken;
ILeverageModule leverageModule;
IProtocolDataProvider aaveProtocolDataProvider;
IChainlinkAggregatorV3 collateralPriceOracle;
IChainlinkAggregatorV3 borrowPriceOracle;
IERC20 targetCollateralAToken;
IERC20 targetBorrowDebtToken;
address collateralAsset;
address borrowAsset;
uint256 collateralDecimalAdjustment;
uint256 borrowDecimalAdjustment;
}
struct MethodologySettings {
uint256 targetLeverageRatio;
uint256 minLeverageRatio;
uint256 maxLeverageRatio;
uint256 recenteringSpeed;
uint256 rebalanceInterval;
}
struct ExecutionSettings {
uint256 unutilizedLeveragePercentage;
uint256 slippageTolerance;
uint256 twapCooldownPeriod;
}
struct ExchangeSettings {
uint256 twapMaxTradeSize;
uint256 exchangeLastTradeTimestamp;
uint256 incentivizedTwapMaxTradeSize;
bytes leverExchangeData;
bytes deleverExchangeData;
}
struct IncentiveSettings {
uint256 etherReward;
uint256 incentivizedLeverageRatio;
uint256 incentivizedSlippageTolerance;
uint256 incentivizedTwapCooldownPeriod;
}
event Engaged(uint256 _currentLeverageRatio, uint256 _newLeverageRatio, uint256 _chunkRebalanceNotional, uint256 _totalRebalanceNotional);
event Rebalanced(
uint256 _currentLeverageRatio,
uint256 _newLeverageRatio,
uint256 _chunkRebalanceNotional,
uint256 _totalRebalanceNotional
);
event RebalanceIterated(
uint256 _currentLeverageRatio,
uint256 _newLeverageRatio,
uint256 _chunkRebalanceNotional,
uint256 _totalRebalanceNotional
);
event RipcordCalled(
uint256 _currentLeverageRatio,
uint256 _newLeverageRatio,
uint256 _rebalanceNotional,
uint256 _etherIncentive
);
event Disengaged(uint256 _currentLeverageRatio, uint256 _newLeverageRatio, uint256 _chunkRebalanceNotional, uint256 _totalRebalanceNotional);
event MethodologySettingsUpdated(
uint256 _targetLeverageRatio,
uint256 _minLeverageRatio,
uint256 _maxLeverageRatio,
uint256 _recenteringSpeed,
uint256 _rebalanceInterval
);
event ExecutionSettingsUpdated(
uint256 _unutilizedLeveragePercentage,
uint256 _twapCooldownPeriod,
uint256 _slippageTolerance
);
event IncentiveSettingsUpdated(
uint256 _etherReward,
uint256 _incentivizedLeverageRatio,
uint256 _incentivizedSlippageTolerance,
uint256 _incentivizedTwapCooldownPeriod
);
event ExchangeUpdated(
string _exchangeName,
uint256 twapMaxTradeSize,
uint256 exchangeLastTradeTimestamp,
uint256 incentivizedTwapMaxTradeSize,
bytes leverExchangeData,
bytes deleverExchangeData
);
event ExchangeAdded(
string _exchangeName,
uint256 twapMaxTradeSize,
uint256 exchangeLastTradeTimestamp,
uint256 incentivizedTwapMaxTradeSize,
bytes leverExchangeData,
bytes deleverExchangeData
);
event ExchangeRemoved(
string _exchangeName
);
modifier noRebalanceInProgress() virtual {
require(twapLeverageRatio == 0, "Rebalance is currently in progress");
_;
}
ContractSettings internal strategy;
MethodologySettings internal methodology;
ExecutionSettings internal execution;
mapping(string => ExchangeSettings) internal exchangeSettings;
IncentiveSettings internal incentive;
string[] public enabledExchanges;
uint256 public twapLeverageRatio;
uint256 public globalLastTradeTimestamp;
constructor(
IBaseManager _manager,
ContractSettings memory _strategy,
MethodologySettings memory _methodology,
ExecutionSettings memory _execution,
IncentiveSettings memory _incentive,
string[] memory _exchangeNames,
ExchangeSettings[] memory _exchangeSettings
)
public
BaseExtension(_manager)
{
strategy = _strategy;
methodology = _methodology;
execution = _execution;
incentive = _incentive;
for (uint256 i = 0; i < _exchangeNames.length; i++) {
_validateExchangeSettings(_exchangeSettings[i]);
exchangeSettings[_exchangeNames[i]] = _exchangeSettings[i];
enabledExchanges.push(_exchangeNames[i]);
}
_validateNonExchangeSettings(methodology, execution, incentive);
}
function engage(string memory _exchangeName) external onlyOperator {
ActionInfo memory engageInfo = _createActionInfo();
require(engageInfo.setTotalSupply > 0, "SetToken must have > 0 supply");
require(engageInfo.collateralBalance > 0, "Collateral balance must be > 0");
require(engageInfo.borrowBalance == 0, "Debt must be 0");
LeverageInfo memory leverageInfo = LeverageInfo({
action: engageInfo,
currentLeverageRatio: PreciseUnitMath.preciseUnit(),
slippageTolerance: execution.slippageTolerance,
twapMaxTradeSize: exchangeSettings[_exchangeName].twapMaxTradeSize,
exchangeName: _exchangeName
});
(
uint256 chunkRebalanceNotional,
uint256 totalRebalanceNotional
) = _calculateChunkRebalanceNotional(leverageInfo, methodology.targetLeverageRatio, true);
_lever(leverageInfo, chunkRebalanceNotional);
_updateRebalanceState(
chunkRebalanceNotional,
totalRebalanceNotional,
methodology.targetLeverageRatio,
_exchangeName
);
emit Engaged(
leverageInfo.currentLeverageRatio,
methodology.targetLeverageRatio,
chunkRebalanceNotional,
totalRebalanceNotional
);
}
function rebalance(string memory _exchangeName) external onlyEOA onlyAllowedCaller(msg.sender) {
LeverageInfo memory leverageInfo = _getAndValidateLeveragedInfo(
execution.slippageTolerance,
exchangeSettings[_exchangeName].twapMaxTradeSize,
_exchangeName
);
_validateNormalRebalance(leverageInfo, methodology.rebalanceInterval, globalLastTradeTimestamp);
_validateNonTWAP();
uint256 newLeverageRatio = _calculateNewLeverageRatio(leverageInfo.currentLeverageRatio);
(
uint256 chunkRebalanceNotional,
uint256 totalRebalanceNotional
) = _handleRebalance(leverageInfo, newLeverageRatio);
_updateRebalanceState(chunkRebalanceNotional, totalRebalanceNotional, newLeverageRatio, _exchangeName);
emit Rebalanced(
leverageInfo.currentLeverageRatio,
newLeverageRatio,
chunkRebalanceNotional,
totalRebalanceNotional
);
}
function iterateRebalance(string memory _exchangeName) external onlyEOA onlyAllowedCaller(msg.sender) {
LeverageInfo memory leverageInfo = _getAndValidateLeveragedInfo(
execution.slippageTolerance,
exchangeSettings[_exchangeName].twapMaxTradeSize,
_exchangeName
);
_validateNormalRebalance(leverageInfo, execution.twapCooldownPeriod, exchangeSettings[_exchangeName].exchangeLastTradeTimestamp);
_validateTWAP();
uint256 chunkRebalanceNotional;
uint256 totalRebalanceNotional;
if (!_isAdvantageousTWAP(leverageInfo.currentLeverageRatio)) {
(chunkRebalanceNotional, totalRebalanceNotional) = _handleRebalance(leverageInfo, twapLeverageRatio);
}
_updateIterateState(chunkRebalanceNotional, totalRebalanceNotional, _exchangeName);
emit RebalanceIterated(
leverageInfo.currentLeverageRatio,
twapLeverageRatio,
chunkRebalanceNotional,
totalRebalanceNotional
);
}
function ripcord(string memory _exchangeName) external onlyEOA {
LeverageInfo memory leverageInfo = _getAndValidateLeveragedInfo(
incentive.incentivizedSlippageTolerance,
exchangeSettings[_exchangeName].incentivizedTwapMaxTradeSize,
_exchangeName
);
_validateRipcord(leverageInfo, exchangeSettings[_exchangeName].exchangeLastTradeTimestamp);
( uint256 chunkRebalanceNotional, ) = _calculateChunkRebalanceNotional(leverageInfo, methodology.maxLeverageRatio, false);
_delever(leverageInfo, chunkRebalanceNotional);
_updateRipcordState(_exchangeName);
uint256 etherTransferred = _transferEtherRewardToCaller(incentive.etherReward);
emit RipcordCalled(
leverageInfo.currentLeverageRatio,
methodology.maxLeverageRatio,
chunkRebalanceNotional,
etherTransferred
);
}
function disengage(string memory _exchangeName) external onlyOperator {
LeverageInfo memory leverageInfo = _getAndValidateLeveragedInfo(
execution.slippageTolerance,
exchangeSettings[_exchangeName].twapMaxTradeSize,
_exchangeName
);
uint256 newLeverageRatio = PreciseUnitMath.preciseUnit();
(
uint256 chunkRebalanceNotional,
uint256 totalRebalanceNotional
) = _calculateChunkRebalanceNotional(leverageInfo, newLeverageRatio, false);
if (totalRebalanceNotional > chunkRebalanceNotional) {
_delever(leverageInfo, chunkRebalanceNotional);
} else {
_deleverToZeroBorrowBalance(leverageInfo, totalRebalanceNotional);
}
emit Disengaged(
leverageInfo.currentLeverageRatio,
newLeverageRatio,
chunkRebalanceNotional,
totalRebalanceNotional
);
}
function setMethodologySettings(MethodologySettings memory _newMethodologySettings) external onlyOperator noRebalanceInProgress {
methodology = _newMethodologySettings;
_validateNonExchangeSettings(methodology, execution, incentive);
emit MethodologySettingsUpdated(
methodology.targetLeverageRatio,
methodology.minLeverageRatio,
methodology.maxLeverageRatio,
methodology.recenteringSpeed,
methodology.rebalanceInterval
);
}
function setExecutionSettings(ExecutionSettings memory _newExecutionSettings) external onlyOperator noRebalanceInProgress {
execution = _newExecutionSettings;
_validateNonExchangeSettings(methodology, execution, incentive);
emit ExecutionSettingsUpdated(
execution.unutilizedLeveragePercentage,
execution.twapCooldownPeriod,
execution.slippageTolerance
);
}
function setIncentiveSettings(IncentiveSettings memory _newIncentiveSettings) external onlyOperator noRebalanceInProgress {
incentive = _newIncentiveSettings;
_validateNonExchangeSettings(methodology, execution, incentive);
emit IncentiveSettingsUpdated(
incentive.etherReward,
incentive.incentivizedLeverageRatio,
incentive.incentivizedSlippageTolerance,
incentive.incentivizedTwapCooldownPeriod
);
}
function addEnabledExchange(
string memory _exchangeName,
ExchangeSettings memory _exchangeSettings
)
external
onlyOperator
{
require(exchangeSettings[_exchangeName].twapMaxTradeSize == 0, "Exchange already enabled");
_validateExchangeSettings(_exchangeSettings);
exchangeSettings[_exchangeName].twapMaxTradeSize = _exchangeSettings.twapMaxTradeSize;
exchangeSettings[_exchangeName].incentivizedTwapMaxTradeSize = _exchangeSettings.incentivizedTwapMaxTradeSize;
exchangeSettings[_exchangeName].leverExchangeData = _exchangeSettings.leverExchangeData;
exchangeSettings[_exchangeName].deleverExchangeData = _exchangeSettings.deleverExchangeData;
exchangeSettings[_exchangeName].exchangeLastTradeTimestamp = 0;
enabledExchanges.push(_exchangeName);
emit ExchangeAdded(
_exchangeName,
_exchangeSettings.twapMaxTradeSize,
_exchangeSettings.exchangeLastTradeTimestamp,
_exchangeSettings.incentivizedTwapMaxTradeSize,
_exchangeSettings.leverExchangeData,
_exchangeSettings.deleverExchangeData
);
}
function removeEnabledExchange(string memory _exchangeName) external onlyOperator {
require(exchangeSettings[_exchangeName].twapMaxTradeSize != 0, "Exchange not enabled");
delete exchangeSettings[_exchangeName];
enabledExchanges.removeStorage(_exchangeName);
emit ExchangeRemoved(_exchangeName);
}
function updateEnabledExchange(
string memory _exchangeName,
ExchangeSettings memory _exchangeSettings
)
external
onlyOperator
{
require(exchangeSettings[_exchangeName].twapMaxTradeSize != 0, "Exchange not enabled");
_validateExchangeSettings(_exchangeSettings);
exchangeSettings[_exchangeName].twapMaxTradeSize = _exchangeSettings.twapMaxTradeSize;
exchangeSettings[_exchangeName].incentivizedTwapMaxTradeSize = _exchangeSettings.incentivizedTwapMaxTradeSize;
exchangeSettings[_exchangeName].leverExchangeData = _exchangeSettings.leverExchangeData;
exchangeSettings[_exchangeName].deleverExchangeData = _exchangeSettings.deleverExchangeData;
emit ExchangeUpdated(
_exchangeName,
_exchangeSettings.twapMaxTradeSize,
_exchangeSettings.exchangeLastTradeTimestamp,
_exchangeSettings.incentivizedTwapMaxTradeSize,
_exchangeSettings.leverExchangeData,
_exchangeSettings.deleverExchangeData
);
}
function withdrawEtherBalance() external onlyOperator noRebalanceInProgress {
msg.sender.transfer(address(this).balance);
}
receive() external payable {}
function getCurrentLeverageRatio() public view returns(uint256) {
ActionInfo memory currentLeverageInfo = _createActionInfo();
return _calculateCurrentLeverageRatio(currentLeverageInfo.collateralValue, currentLeverageInfo.borrowValue);
}
function getChunkRebalanceNotional(
string[] calldata _exchangeNames
)
external
view
returns(uint256[] memory sizes, address sellAsset, address buyAsset)
{
uint256 newLeverageRatio;
uint256 currentLeverageRatio = getCurrentLeverageRatio();
bool isRipcord = false;
if (currentLeverageRatio > incentive.incentivizedLeverageRatio) {
newLeverageRatio = methodology.maxLeverageRatio;
isRipcord = true;
} else if (twapLeverageRatio > 0) {
newLeverageRatio = twapLeverageRatio;
} else {
newLeverageRatio = _calculateNewLeverageRatio(currentLeverageRatio);
}
ActionInfo memory actionInfo = _createActionInfo();
bool isLever = newLeverageRatio > currentLeverageRatio;
sizes = new uint256[](_exchangeNames.length);
for (uint256 i = 0; i < _exchangeNames.length; i++) {
LeverageInfo memory leverageInfo = LeverageInfo({
action: actionInfo,
currentLeverageRatio: currentLeverageRatio,
slippageTolerance: isRipcord ? incentive.incentivizedSlippageTolerance : execution.slippageTolerance,
twapMaxTradeSize: isRipcord ?
exchangeSettings[_exchangeNames[i]].incentivizedTwapMaxTradeSize :
exchangeSettings[_exchangeNames[i]].twapMaxTradeSize,
exchangeName: _exchangeNames[i]
});
(uint256 collateralNotional, ) = _calculateChunkRebalanceNotional(leverageInfo, newLeverageRatio, isLever);
sizes[i] = isLever ? _calculateBorrowUnits(collateralNotional, leverageInfo.action) : collateralNotional;
}
sellAsset = isLever ? strategy.borrowAsset : strategy.collateralAsset;
buyAsset = isLever ? strategy.collateralAsset : strategy.borrowAsset;
}
function getCurrentEtherIncentive() external view returns(uint256) {
uint256 currentLeverageRatio = getCurrentLeverageRatio();
if (currentLeverageRatio >= incentive.incentivizedLeverageRatio) {
return incentive.etherReward < address(this).balance ? incentive.etherReward : address(this).balance;
} else {
return 0;
}
}
function shouldRebalance() external view returns(string[] memory, ShouldRebalance[] memory) {
uint256 currentLeverageRatio = getCurrentLeverageRatio();
return _shouldRebalance(currentLeverageRatio, methodology.minLeverageRatio, methodology.maxLeverageRatio);
}
function shouldRebalanceWithBounds(
uint256 _customMinLeverageRatio,
uint256 _customMaxLeverageRatio
)
external
view
returns(string[] memory, ShouldRebalance[] memory)
{
require (
_customMinLeverageRatio <= methodology.minLeverageRatio && _customMaxLeverageRatio >= methodology.maxLeverageRatio,
"Custom bounds must be valid"
);
uint256 currentLeverageRatio = getCurrentLeverageRatio();
return _shouldRebalance(currentLeverageRatio, _customMinLeverageRatio, _customMaxLeverageRatio);
}
function getEnabledExchanges() external view returns (string[] memory) {
return enabledExchanges;
}
function getStrategy() external view returns (ContractSettings memory) { return strategy; }
function getMethodology() external view returns (MethodologySettings memory) { return methodology; }
function getExecution() external view returns (ExecutionSettings memory) { return execution; }
function getIncentive() external view returns (IncentiveSettings memory) { return incentive; }
function getExchangeSettings(string memory _exchangeName) external view returns (ExchangeSettings memory) {
return exchangeSettings[_exchangeName];
}
function _lever(
LeverageInfo memory _leverageInfo,
uint256 _chunkRebalanceNotional
)
internal
{
uint256 collateralRebalanceUnits = _chunkRebalanceNotional.preciseDiv(_leverageInfo.action.setTotalSupply);
uint256 borrowUnits = _calculateBorrowUnits(collateralRebalanceUnits, _leverageInfo.action);
uint256 minReceiveCollateralUnits = _calculateMinCollateralReceiveUnits(collateralRebalanceUnits, _leverageInfo.slippageTolerance);
bytes memory leverCallData = abi.encodeWithSignature(
"lever(address,address,address,uint256,uint256,string,bytes)",
address(strategy.setToken),
strategy.borrowAsset,
strategy.collateralAsset,
borrowUnits,
minReceiveCollateralUnits,
_leverageInfo.exchangeName,
exchangeSettings[_leverageInfo.exchangeName].leverExchangeData
);
invokeManager(address(strategy.leverageModule), leverCallData);
}
function _delever(
LeverageInfo memory _leverageInfo,
uint256 _chunkRebalanceNotional
)
internal
{
uint256 collateralRebalanceUnits = _chunkRebalanceNotional.preciseDiv(_leverageInfo.action.setTotalSupply);
uint256 minRepayUnits = _calculateMinRepayUnits(collateralRebalanceUnits, _leverageInfo.slippageTolerance, _leverageInfo.action);
bytes memory deleverCallData = abi.encodeWithSignature(
"delever(address,address,address,uint256,uint256,string,bytes)",
address(strategy.setToken),
strategy.collateralAsset,
strategy.borrowAsset,
collateralRebalanceUnits,
minRepayUnits,
_leverageInfo.exchangeName,
exchangeSettings[_leverageInfo.exchangeName].deleverExchangeData
);
invokeManager(address(strategy.leverageModule), deleverCallData);
}
function _deleverToZeroBorrowBalance(
LeverageInfo memory _leverageInfo,
uint256 _chunkRebalanceNotional
)
internal
{
uint256 maxCollateralRebalanceUnits = _chunkRebalanceNotional
.preciseMul(PreciseUnitMath.preciseUnit().add(execution.slippageTolerance))
.preciseDiv(_leverageInfo.action.setTotalSupply);
bytes memory deleverToZeroBorrowBalanceCallData = abi.encodeWithSignature(
"deleverToZeroBorrowBalance(address,address,address,uint256,string,bytes)",
address(strategy.setToken),
strategy.collateralAsset,
strategy.borrowAsset,
maxCollateralRebalanceUnits,
_leverageInfo.exchangeName,
exchangeSettings[_leverageInfo.exchangeName].deleverExchangeData
);
invokeManager(address(strategy.leverageModule), deleverToZeroBorrowBalanceCallData);
}
function _handleRebalance(LeverageInfo memory _leverageInfo, uint256 _newLeverageRatio) internal returns(uint256, uint256) {
uint256 chunkRebalanceNotional;
uint256 totalRebalanceNotional;
if (_newLeverageRatio < _leverageInfo.currentLeverageRatio) {
(
chunkRebalanceNotional,
totalRebalanceNotional
) = _calculateChunkRebalanceNotional(_leverageInfo, _newLeverageRatio, false);
_delever(_leverageInfo, chunkRebalanceNotional);
} else {
(
chunkRebalanceNotional,
totalRebalanceNotional
) = _calculateChunkRebalanceNotional(_leverageInfo, _newLeverageRatio, true);
_lever(_leverageInfo, chunkRebalanceNotional);
}
return (chunkRebalanceNotional, totalRebalanceNotional);
}
function _getAndValidateLeveragedInfo(uint256 _slippageTolerance, uint256 _maxTradeSize, string memory _exchangeName) internal view returns(LeverageInfo memory) {
require(_maxTradeSize > 0, "Must be valid exchange");
ActionInfo memory actionInfo = _createActionInfo();
require(actionInfo.setTotalSupply > 0, "SetToken must have > 0 supply");
require(actionInfo.collateralBalance > 0, "Collateral balance must be > 0");
require(actionInfo.borrowBalance > 0, "Borrow balance must exist");
uint256 currentLeverageRatio = _calculateCurrentLeverageRatio(
actionInfo.collateralValue,
actionInfo.borrowValue
);
return LeverageInfo({
action: actionInfo,
currentLeverageRatio: currentLeverageRatio,
slippageTolerance: _slippageTolerance,
twapMaxTradeSize: _maxTradeSize,
exchangeName: _exchangeName
});
}
function _createActionInfo() internal view virtual returns(ActionInfo memory) {
ActionInfo memory rebalanceInfo;
int256 rawCollateralPrice = strategy.collateralPriceOracle.latestAnswer();
rebalanceInfo.collateralPrice = rawCollateralPrice.toUint256().mul(10 ** strategy.collateralDecimalAdjustment);
int256 rawBorrowPrice = strategy.borrowPriceOracle.latestAnswer();
rebalanceInfo.borrowPrice = rawBorrowPrice.toUint256().mul(10 ** strategy.borrowDecimalAdjustment);
rebalanceInfo.collateralBalance = strategy.targetCollateralAToken.balanceOf(address(strategy.setToken));
rebalanceInfo.borrowBalance = strategy.targetBorrowDebtToken.balanceOf(address(strategy.setToken));
rebalanceInfo.collateralValue = rebalanceInfo.collateralPrice.preciseMul(rebalanceInfo.collateralBalance);
rebalanceInfo.borrowValue = rebalanceInfo.borrowPrice.preciseMul(rebalanceInfo.borrowBalance);
rebalanceInfo.setTotalSupply = strategy.setToken.totalSupply();
return rebalanceInfo;
}
function _validateNonExchangeSettings(
MethodologySettings memory _methodology,
ExecutionSettings memory _execution,
IncentiveSettings memory _incentive
)
internal
virtual
pure
{
require (
_methodology.minLeverageRatio <= _methodology.targetLeverageRatio && _methodology.minLeverageRatio > 0,
"Must be valid min leverage"
);
require (
_methodology.maxLeverageRatio >= _methodology.targetLeverageRatio,
"Must be valid max leverage"
);
require (
_methodology.recenteringSpeed <= PreciseUnitMath.preciseUnit() && _methodology.recenteringSpeed > 0,
"Must be valid recentering speed"
);
require (
_execution.unutilizedLeveragePercentage <= PreciseUnitMath.preciseUnit(),
"Unutilized leverage must be <100%"
);
require (
_execution.slippageTolerance <= PreciseUnitMath.preciseUnit(),
"Slippage tolerance must be <100%"
);
require (
_incentive.incentivizedSlippageTolerance <= PreciseUnitMath.preciseUnit(),
"Incentivized slippage tolerance must be <100%"
);
require (
_incentive.incentivizedLeverageRatio >= _methodology.maxLeverageRatio,
"Incentivized leverage ratio must be > max leverage ratio"
);
require (
_methodology.rebalanceInterval >= _execution.twapCooldownPeriod,
"Rebalance interval must be greater than TWAP cooldown period"
);
require (
_execution.twapCooldownPeriod >= _incentive.incentivizedTwapCooldownPeriod,
"TWAP cooldown must be greater than incentivized TWAP cooldown"
);
}
function _validateExchangeSettings(ExchangeSettings memory _settings) internal pure {
require(_settings.twapMaxTradeSize != 0, "Max TWAP trade size must not be 0");
}
function _validateNormalRebalance(LeverageInfo memory _leverageInfo, uint256 _coolDown, uint256 _lastTradeTimestamp) internal view {
require(_leverageInfo.currentLeverageRatio < incentive.incentivizedLeverageRatio, "Must be below incentivized leverage ratio");
require(
block.timestamp.sub(_lastTradeTimestamp) > _coolDown
|| _leverageInfo.currentLeverageRatio > methodology.maxLeverageRatio
|| _leverageInfo.currentLeverageRatio < methodology.minLeverageRatio,
"Cooldown not elapsed or not valid leverage ratio"
);
}
function _validateRipcord(LeverageInfo memory _leverageInfo, uint256 _lastTradeTimestamp) internal view {
require(_leverageInfo.currentLeverageRatio >= incentive.incentivizedLeverageRatio, "Must be above incentivized leverage ratio");
require(_lastTradeTimestamp.add(incentive.incentivizedTwapCooldownPeriod) < block.timestamp, "TWAP cooldown must have elapsed");
}
function _validateTWAP() internal view {
require(twapLeverageRatio > 0, "Not in TWAP state");
}
function _validateNonTWAP() internal view {
require(twapLeverageRatio == 0, "Must call iterate");
}
function _isAdvantageousTWAP(uint256 _currentLeverageRatio) internal view returns (bool) {
return (
(twapLeverageRatio < methodology.targetLeverageRatio && _currentLeverageRatio >= twapLeverageRatio)
|| (twapLeverageRatio > methodology.targetLeverageRatio && _currentLeverageRatio <= twapLeverageRatio)
);
}
function _calculateCurrentLeverageRatio(
uint256 _collateralValue,
uint256 _borrowValue
)
internal
pure
returns(uint256)
{
return _collateralValue.preciseDiv(_collateralValue.sub(_borrowValue));
}
function _calculateNewLeverageRatio(uint256 _currentLeverageRatio) internal view returns(uint256) {
uint256 a = methodology.targetLeverageRatio.preciseMul(methodology.recenteringSpeed);
uint256 b = PreciseUnitMath.preciseUnit().sub(methodology.recenteringSpeed).preciseMul(_currentLeverageRatio);
uint256 c = a.add(b);
uint256 d = Math.min(c, methodology.maxLeverageRatio);
return Math.max(methodology.minLeverageRatio, d);
}
function _calculateChunkRebalanceNotional(
LeverageInfo memory _leverageInfo,
uint256 _newLeverageRatio,
bool _isLever
)
internal
view
virtual
returns (uint256, uint256)
{
uint256 leverageRatioDifference = _isLever ? _newLeverageRatio.sub(_leverageInfo.currentLeverageRatio) : _leverageInfo.currentLeverageRatio.sub(_newLeverageRatio);
uint256 totalRebalanceNotional = leverageRatioDifference.preciseDiv(_leverageInfo.currentLeverageRatio).preciseMul(_leverageInfo.action.collateralBalance);
uint256 maxBorrow = _calculateMaxBorrowCollateral(_leverageInfo.action, _isLever);
uint256 chunkRebalanceNotional = Math.min(Math.min(maxBorrow, totalRebalanceNotional), _leverageInfo.twapMaxTradeSize);
return (chunkRebalanceNotional, totalRebalanceNotional);
}
function _calculateMaxBorrowCollateral(ActionInfo memory _actionInfo, bool _isLever) internal virtual view returns(uint256) {
( , uint256 maxLtvRaw, uint256 liquidationThresholdRaw, , , , , , ,) = strategy.aaveProtocolDataProvider.getReserveConfigurationData(address(strategy.collateralAsset));
if (_isLever) {
uint256 netBorrowLimit = _actionInfo.collateralValue
.preciseMul(maxLtvRaw.mul(10 ** 14))
.preciseMul(PreciseUnitMath.preciseUnit().sub(execution.unutilizedLeveragePercentage));
return netBorrowLimit
.sub(_actionInfo.borrowValue)
.preciseDiv(_actionInfo.collateralPrice);
} else {
uint256 netRepayLimit = _actionInfo.collateralValue
.preciseMul(liquidationThresholdRaw.mul(10 ** 14))
.preciseMul(PreciseUnitMath.preciseUnit().sub(execution.unutilizedLeveragePercentage));
return _actionInfo.collateralBalance
.preciseMul(netRepayLimit.sub(_actionInfo.borrowValue))
.preciseDiv(netRepayLimit);
}
}
function _calculateBorrowUnits(uint256 _collateralRebalanceUnits, ActionInfo memory _actionInfo) internal pure returns (uint256) {
return _collateralRebalanceUnits.preciseMul(_actionInfo.collateralPrice).preciseDiv(_actionInfo.borrowPrice);
}
function _calculateMinCollateralReceiveUnits(uint256 _collateralRebalanceUnits, uint256 _slippageTolerance) internal pure returns (uint256) {
return _collateralRebalanceUnits.preciseMul(PreciseUnitMath.preciseUnit().sub(_slippageTolerance));
}
function _calculateMinRepayUnits(uint256 _collateralRebalanceUnits, uint256 _slippageTolerance, ActionInfo memory _actionInfo) internal virtual pure returns (uint256) {
return _collateralRebalanceUnits
.preciseMul(_actionInfo.collateralPrice)
.preciseDiv(_actionInfo.borrowPrice)
.preciseMul(PreciseUnitMath.preciseUnit().sub(_slippageTolerance));
}
function _updateRebalanceState(
uint256 _chunkRebalanceNotional,
uint256 _totalRebalanceNotional,
uint256 _newLeverageRatio,
string memory _exchangeName
)
internal
{
_updateLastTradeTimestamp(_exchangeName);
if (_chunkRebalanceNotional < _totalRebalanceNotional) {
twapLeverageRatio = _newLeverageRatio;
}
}
function _updateIterateState(uint256 _chunkRebalanceNotional, uint256 _totalRebalanceNotional, string memory _exchangeName) internal {
_updateLastTradeTimestamp(_exchangeName);
if (_chunkRebalanceNotional == _totalRebalanceNotional) {
delete twapLeverageRatio;
}
}
function _updateRipcordState(string memory _exchangeName) internal {
_updateLastTradeTimestamp(_exchangeName);
if (twapLeverageRatio > 0) {
delete twapLeverageRatio;
}
}
function _updateLastTradeTimestamp(string memory _exchangeName) internal {
globalLastTradeTimestamp = block.timestamp;
exchangeSettings[_exchangeName].exchangeLastTradeTimestamp = block.timestamp;
}
function _transferEtherRewardToCaller(uint256 _etherReward) internal returns(uint256) {
uint256 etherToTransfer = _etherReward < address(this).balance ? _etherReward : address(this).balance;
msg.sender.transfer(etherToTransfer);
return etherToTransfer;
}
function _shouldRebalance(
uint256 _currentLeverageRatio,
uint256 _minLeverageRatio,
uint256 _maxLeverageRatio
)
internal
view
returns(string[] memory, ShouldRebalance[] memory)
{
ShouldRebalance[] memory shouldRebalanceEnums = new ShouldRebalance[](enabledExchanges.length);
for (uint256 i = 0; i < enabledExchanges.length; i++) {
shouldRebalanceEnums[i] = ShouldRebalance.NONE;
if (_currentLeverageRatio >= incentive.incentivizedLeverageRatio) {
if (exchangeSettings[enabledExchanges[i]].exchangeLastTradeTimestamp.add(incentive.incentivizedTwapCooldownPeriod) < block.timestamp) {
shouldRebalanceEnums[i] = ShouldRebalance.RIPCORD;
}
} else {
if (twapLeverageRatio > 0) {
if (exchangeSettings[enabledExchanges[i]].exchangeLastTradeTimestamp.add(execution.twapCooldownPeriod) < block.timestamp) {
shouldRebalanceEnums[i] = ShouldRebalance.ITERATE_REBALANCE;
}
} else {
if (
block.timestamp.sub(globalLastTradeTimestamp) > methodology.rebalanceInterval
|| _currentLeverageRatio > _maxLeverageRatio
|| _currentLeverageRatio < _minLeverageRatio
) {
shouldRebalanceEnums[i] = ShouldRebalance.REBALANCE;
}
}
}
}
return (enabledExchanges, shouldRebalanceEnums);
}
}
文件 2 的 21:AaveV3LeverageStrategyExtension.sol
pragma solidity 0.6.10;
pragma experimental ABIEncoderV2;
import { Math } from "@openzeppelin/contracts/math/Math.sol";
import { AaveLeverageStrategyExtension } from "./AaveLeverageStrategyExtension.sol";
import { IBaseManager } from "../interfaces/IBaseManager.sol";
import { IAaveOracle } from "../interfaces/IAaveOracle.sol";
import { IPool } from "../interfaces/IPool.sol";
import { IPoolAddressesProvider } from "../interfaces/IPoolAddressesProvider.sol";
import { DataTypes } from "../interfaces/Datatypes.sol";
import { PreciseUnitMath } from "../lib/PreciseUnitMath.sol";
contract AaveV3LeverageStrategyExtension is AaveLeverageStrategyExtension {
uint8 public currentEModeCategoryId;
IPoolAddressesProvider public lendingPoolAddressesProvider;
bool public overrideNoRebalanceInProgress;
constructor(
IBaseManager _manager,
ContractSettings memory _strategy,
MethodologySettings memory _methodology,
ExecutionSettings memory _execution,
IncentiveSettings memory _incentive,
string[] memory _exchangeNames,
ExchangeSettings[] memory _exchangeSettings,
IPoolAddressesProvider _lendingPoolAddressesProvider
)
public
AaveLeverageStrategyExtension(
_manager,
_strategy,
_methodology,
_execution,
_incentive,
_exchangeNames,
_exchangeSettings
)
{
lendingPoolAddressesProvider = _lendingPoolAddressesProvider;
}
modifier noRebalanceInProgress() override {
if(!overrideNoRebalanceInProgress) {
require(twapLeverageRatio == 0, "Rebalance is currently in progress");
}
_;
}
function setOverrideNoRebalanceInProgress(bool _overrideNoRebalanceInProgress) external onlyOperator {
overrideNoRebalanceInProgress = _overrideNoRebalanceInProgress;
}
function setEModeCategory(uint8 _categoryId) external onlyOperator {
currentEModeCategoryId = _categoryId;
_setEModeCategory(_categoryId);
}
function _setEModeCategory(uint8 _categoryId) internal {
bytes memory setEmodeCallData =
abi.encodeWithSignature("setEModeCategory(address,uint8)", address(strategy.setToken), _categoryId);
invokeManager(address(strategy.leverageModule), setEmodeCallData);
}
function _calculateMaxBorrowCollateral(ActionInfo memory _actionInfo, bool _isLever) internal override view returns(uint256) {
(uint256 maxLtvRaw, uint256 liquidationThresholdRaw) = _getLtvAndLiquidationThreshold();
if (_isLever) {
uint256 netBorrowLimit = _actionInfo.collateralValue
.preciseMul(maxLtvRaw.mul(10 ** 14))
.preciseMul(PreciseUnitMath.preciseUnit().sub(execution.unutilizedLeveragePercentage));
return netBorrowLimit
.sub(_actionInfo.borrowValue)
.preciseDiv(_actionInfo.collateralPrice);
} else {
uint256 netRepayLimit = _actionInfo.collateralValue
.preciseMul(liquidationThresholdRaw.mul(10 ** 14));
return _actionInfo.collateralBalance
.preciseMul(netRepayLimit.sub(_actionInfo.borrowValue))
.preciseDiv(netRepayLimit);
}
}
function _getLtvAndLiquidationThreshold() internal view returns(uint256, uint256) {
if(currentEModeCategoryId != 0 ) {
DataTypes.EModeCategory memory emodeData = IPool(lendingPoolAddressesProvider.getPool()).getEModeCategoryData(currentEModeCategoryId);
return (emodeData.ltv, emodeData.liquidationThreshold);
} else {
( , uint256 maxLtvRaw, uint256 liquidationThresholdRaw, , , , , , ,) = strategy.aaveProtocolDataProvider.getReserveConfigurationData(address(strategy.collateralAsset));
return (maxLtvRaw, liquidationThresholdRaw);
}
}
function _validateNonExchangeSettings(
MethodologySettings memory _methodology,
ExecutionSettings memory _execution,
IncentiveSettings memory _incentive
)
internal
override
pure
{
super._validateNonExchangeSettings(_methodology, _execution, _incentive);
require(_methodology.targetLeverageRatio >= 1 ether, "Target leverage ratio must be >= 1e18");
}
function _calculateMinRepayUnits(uint256 _collateralRebalanceUnits, uint256 _slippageTolerance, ActionInfo memory _actionInfo)
internal
override
pure
returns(uint256)
{
return _collateralRebalanceUnits
.preciseMul(_actionInfo.collateralPrice)
.preciseMul(PreciseUnitMath.preciseUnit().sub(_slippageTolerance))
.preciseDiv(_actionInfo.borrowPrice);
}
function _calculateChunkRebalanceNotional(
LeverageInfo memory _leverageInfo,
uint256 _newLeverageRatio,
bool _isLever
)
internal
view
override
returns (uint256, uint256)
{
uint256 leverageRatioDifference = _isLever ?
_newLeverageRatio.sub(_leverageInfo.currentLeverageRatio) :
_leverageInfo.currentLeverageRatio.sub(_newLeverageRatio);
uint256 totalRebalanceNotional = leverageRatioDifference
.preciseMul(_leverageInfo.action.collateralBalance)
.preciseDiv(_leverageInfo.currentLeverageRatio);
uint256 maxBorrow = _calculateMaxBorrowCollateral(_leverageInfo.action, _isLever);
uint256 chunkRebalanceNotional = Math.min(Math.min(maxBorrow, totalRebalanceNotional), _leverageInfo.twapMaxTradeSize);
return (chunkRebalanceNotional, totalRebalanceNotional);
}
function _createActionInfo() internal view override returns(ActionInfo memory) {
ActionInfo memory rebalanceInfo;
rebalanceInfo.collateralPrice = _getAssetPrice(strategy.collateralAsset, strategy.collateralDecimalAdjustment);
rebalanceInfo.borrowPrice = _getAssetPrice(strategy.borrowAsset, strategy.borrowDecimalAdjustment);
rebalanceInfo.collateralBalance = strategy.targetCollateralAToken.balanceOf(address(strategy.setToken));
rebalanceInfo.borrowBalance = strategy.targetBorrowDebtToken.balanceOf(address(strategy.setToken));
rebalanceInfo.collateralValue = rebalanceInfo.collateralPrice.preciseMul(rebalanceInfo.collateralBalance);
rebalanceInfo.borrowValue = rebalanceInfo.borrowPrice.preciseMul(rebalanceInfo.borrowBalance);
rebalanceInfo.setTotalSupply = strategy.setToken.totalSupply();
return rebalanceInfo;
}
function _getAssetPrice(address _asset, uint256 _decimalAdjustment) internal view returns (uint256) {
IAaveOracle aaveOracle = IAaveOracle(IPoolAddressesProvider(lendingPoolAddressesProvider).getPriceOracle());
uint256 rawPrice = aaveOracle.getAssetPrice(_asset);
return rawPrice.mul(10 ** _decimalAdjustment);
}
}
文件 3 的 21:Address.sol
pragma solidity >=0.6.2 <0.8.0;
library Address {
function isContract(address account) internal view returns (bool) {
uint256 size;
assembly { size := extcodesize(account) }
return size > 0;
}
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");
}
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
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");
}
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);
}
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
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);
}
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
(bool success, bytes memory returndata) = target.delegatecall(data);
return _verifyCallResult(success, returndata, errorMessage);
}
function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {
if (success) {
return returndata;
} else {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
文件 4 的 21:AddressArrayUtils.sol
pragma solidity 0.6.10;
library AddressArrayUtils {
function indexOf(address[] memory A, address a) internal pure returns (uint256, bool) {
uint256 length = A.length;
for (uint256 i = 0; i < length; i++) {
if (A[i] == a) {
return (i, true);
}
}
return (uint256(-1), false);
}
function contains(address[] memory A, address a) internal pure returns (bool) {
(, bool isIn) = indexOf(A, a);
return isIn;
}
function hasDuplicate(address[] memory A) internal pure returns(bool) {
require(A.length > 0, "A is empty");
for (uint256 i = 0; i < A.length - 1; i++) {
address current = A[i];
for (uint256 j = i + 1; j < A.length; j++) {
if (current == A[j]) {
return true;
}
}
}
return false;
}
function remove(address[] memory A, address a)
internal
pure
returns (address[] memory)
{
(uint256 index, bool isIn) = indexOf(A, a);
if (!isIn) {
revert("Address not in array.");
} else {
(address[] memory _A,) = pop(A, index);
return _A;
}
}
function removeStorage(address[] storage A, address a)
internal
{
(uint256 index, bool isIn) = indexOf(A, a);
if (!isIn) {
revert("Address not in array.");
} else {
uint256 lastIndex = A.length - 1;
if (index != lastIndex) { A[index] = A[lastIndex]; }
A.pop();
}
}
function pop(address[] memory A, uint256 index)
internal
pure
returns (address[] memory, address)
{
uint256 length = A.length;
require(index < A.length, "Index must be < A length");
address[] memory newAddresses = new address[](length - 1);
for (uint256 i = 0; i < index; i++) {
newAddresses[i] = A[i];
}
for (uint256 j = index + 1; j < length; j++) {
newAddresses[j - 1] = A[j];
}
return (newAddresses, A[index]);
}
function extend(address[] memory A, address[] memory B) internal pure returns (address[] memory) {
uint256 aLength = A.length;
uint256 bLength = B.length;
address[] memory newAddresses = new address[](aLength + bLength);
for (uint256 i = 0; i < aLength; i++) {
newAddresses[i] = A[i];
}
for (uint256 j = 0; j < bLength; j++) {
newAddresses[aLength + j] = B[j];
}
return newAddresses;
}
function validatePairsWithArray(address[] memory A, uint[] memory B) internal pure {
require(A.length == B.length, "Array length mismatch");
_validateLengthAndUniqueness(A);
}
function validatePairsWithArray(address[] memory A, bool[] memory B) internal pure {
require(A.length == B.length, "Array length mismatch");
_validateLengthAndUniqueness(A);
}
function validatePairsWithArray(address[] memory A, string[] memory B) internal pure {
require(A.length == B.length, "Array length mismatch");
_validateLengthAndUniqueness(A);
}
function validatePairsWithArray(address[] memory A, address[] memory B) internal pure {
require(A.length == B.length, "Array length mismatch");
_validateLengthAndUniqueness(A);
}
function validatePairsWithArray(address[] memory A, bytes[] memory B) internal pure {
require(A.length == B.length, "Array length mismatch");
_validateLengthAndUniqueness(A);
}
function _validateLengthAndUniqueness(address[] memory A) internal pure {
require(A.length > 0, "Array length must be > 0");
require(!hasDuplicate(A), "Cannot duplicate addresses");
}
}
文件 5 的 21:BaseExtension.sol
pragma solidity 0.6.10;
import { AddressArrayUtils } from "../lib/AddressArrayUtils.sol";
import { IBaseManager } from "../interfaces/IBaseManager.sol";
abstract contract BaseExtension {
using AddressArrayUtils for address[];
event CallerStatusUpdated(address indexed _caller, bool _status);
event AnyoneCallableUpdated(bool indexed _status);
modifier onlyOperator() {
require(msg.sender == manager.operator(), "Must be operator");
_;
}
modifier onlyMethodologist() {
require(msg.sender == manager.methodologist(), "Must be methodologist");
_;
}
modifier onlyEOA() {
require(msg.sender == tx.origin, "Caller must be EOA Address");
_;
}
modifier onlyAllowedCaller(address _caller) {
require(isAllowedCaller(_caller), "Address not permitted to call");
_;
}
IBaseManager public manager;
bool public anyoneCallable;
mapping(address => bool) public callAllowList;
constructor(IBaseManager _manager) public { manager = _manager; }
function updateCallerStatus(address[] calldata _callers, bool[] calldata _statuses) external onlyOperator {
require(_callers.length == _statuses.length, "Array length mismatch");
require(_callers.length > 0, "Array length must be > 0");
require(!_callers.hasDuplicate(), "Cannot duplicate callers");
for (uint256 i = 0; i < _callers.length; i++) {
address caller = _callers[i];
bool status = _statuses[i];
callAllowList[caller] = status;
emit CallerStatusUpdated(caller, status);
}
}
function updateAnyoneCallable(bool _status) external onlyOperator {
anyoneCallable = _status;
emit AnyoneCallableUpdated(_status);
}
function invokeManagerTransfer(address _token, address _destination, uint256 _amount) internal {
manager.transferTokens(_token, _destination, _amount);
}
function invokeManager(address _module, bytes memory _encoded) internal {
manager.interactManager(_module, _encoded);
}
function isAllowedCaller(address _caller) internal view virtual returns (bool) {
return anyoneCallable || callAllowList[_caller];
}
}
文件 6 的 21:Datatypes.sol
pragma solidity 0.6.10;
library DataTypes {
struct ReserveData {
ReserveConfigurationMap configuration;
uint128 liquidityIndex;
uint128 currentLiquidityRate;
uint128 variableBorrowIndex;
uint128 currentVariableBorrowRate;
uint128 currentStableBorrowRate;
uint40 lastUpdateTimestamp;
uint16 id;
address aTokenAddress;
address stableDebtTokenAddress;
address variableDebtTokenAddress;
address interestRateStrategyAddress;
uint128 accruedToTreasury;
uint128 unbacked;
uint128 isolationModeTotalDebt;
}
struct ReserveConfigurationMap {
uint256 data;
}
struct UserConfigurationMap {
uint256 data;
}
struct EModeCategory {
uint16 ltv;
uint16 liquidationThreshold;
uint16 liquidationBonus;
address priceSource;
string label;
}
enum InterestRateMode {
NONE,
STABLE,
VARIABLE
}
struct ReserveCache {
uint256 currScaledVariableDebt;
uint256 nextScaledVariableDebt;
uint256 currPrincipalStableDebt;
uint256 currAvgStableBorrowRate;
uint256 currTotalStableDebt;
uint256 nextAvgStableBorrowRate;
uint256 nextTotalStableDebt;
uint256 currLiquidityIndex;
uint256 nextLiquidityIndex;
uint256 currVariableBorrowIndex;
uint256 nextVariableBorrowIndex;
uint256 currLiquidityRate;
uint256 currVariableBorrowRate;
uint256 reserveFactor;
ReserveConfigurationMap reserveConfiguration;
address aTokenAddress;
address stableDebtTokenAddress;
address variableDebtTokenAddress;
uint40 reserveLastUpdateTimestamp;
uint40 stableDebtLastUpdateTimestamp;
}
struct ExecuteLiquidationCallParams {
uint256 reservesCount;
uint256 debtToCover;
address collateralAsset;
address debtAsset;
address user;
bool receiveAToken;
address priceOracle;
uint8 userEModeCategory;
address priceOracleSentinel;
}
struct ExecuteSupplyParams {
address asset;
uint256 amount;
address onBehalfOf;
uint16 referralCode;
}
struct ExecuteBorrowParams {
address asset;
address user;
address onBehalfOf;
uint256 amount;
InterestRateMode interestRateMode;
uint16 referralCode;
bool releaseUnderlying;
uint256 maxStableRateBorrowSizePercent;
uint256 reservesCount;
address oracle;
uint8 userEModeCategory;
address priceOracleSentinel;
}
struct ExecuteRepayParams {
address asset;
uint256 amount;
InterestRateMode interestRateMode;
address onBehalfOf;
bool useATokens;
}
struct ExecuteWithdrawParams {
address asset;
uint256 amount;
address to;
uint256 reservesCount;
address oracle;
uint8 userEModeCategory;
}
struct ExecuteSetUserEModeParams {
uint256 reservesCount;
address oracle;
uint8 categoryId;
}
struct FinalizeTransferParams {
address asset;
address from;
address to;
uint256 amount;
uint256 balanceFromBefore;
uint256 balanceToBefore;
uint256 reservesCount;
address oracle;
uint8 fromEModeCategory;
}
struct FlashloanParams {
address receiverAddress;
address[] assets;
uint256[] amounts;
uint256[] interestRateModes;
address onBehalfOf;
bytes params;
uint16 referralCode;
uint256 flashLoanPremiumToProtocol;
uint256 flashLoanPremiumTotal;
uint256 maxStableRateBorrowSizePercent;
uint256 reservesCount;
address addressesProvider;
uint8 userEModeCategory;
bool isAuthorizedFlashBorrower;
}
struct FlashloanSimpleParams {
address receiverAddress;
address asset;
uint256 amount;
bytes params;
uint16 referralCode;
uint256 flashLoanPremiumToProtocol;
uint256 flashLoanPremiumTotal;
}
struct FlashLoanRepaymentParams {
uint256 amount;
uint256 totalPremium;
uint256 flashLoanPremiumToProtocol;
address asset;
address receiverAddress;
uint16 referralCode;
}
struct CalculateUserAccountDataParams {
UserConfigurationMap userConfig;
uint256 reservesCount;
address user;
address oracle;
uint8 userEModeCategory;
}
struct ValidateBorrowParams {
ReserveCache reserveCache;
UserConfigurationMap userConfig;
address asset;
address userAddress;
uint256 amount;
InterestRateMode interestRateMode;
uint256 maxStableLoanPercent;
uint256 reservesCount;
address oracle;
uint8 userEModeCategory;
address priceOracleSentinel;
bool isolationModeActive;
address isolationModeCollateralAddress;
uint256 isolationModeDebtCeiling;
}
struct ValidateLiquidationCallParams {
ReserveCache debtReserveCache;
uint256 totalDebt;
uint256 healthFactor;
address priceOracleSentinel;
}
struct CalculateInterestRatesParams {
uint256 unbacked;
uint256 liquidityAdded;
uint256 liquidityTaken;
uint256 totalStableDebt;
uint256 totalVariableDebt;
uint256 averageStableBorrowRate;
uint256 reserveFactor;
address reserve;
address aToken;
}
struct InitReserveParams {
address asset;
address aTokenAddress;
address stableDebtAddress;
address variableDebtAddress;
address interestRateStrategyAddress;
uint16 reservesCount;
uint16 maxNumberReserves;
}
}
文件 7 的 21:IAaveOracle.sol
pragma solidity 0.6.10;
interface IAaveOracle {
event AssetSourceUpdated(address indexed asset, address indexed source);
event BaseCurrencySet(address indexed baseCurrency, uint256 baseCurrencyUnit);
event FallbackOracleUpdated(address indexed fallbackOracle);
function ADDRESSES_PROVIDER() external view returns (address);
function BASE_CURRENCY() external view returns (address);
function BASE_CURRENCY_UNIT() external view returns (uint256);
function getAssetPrice(address asset) external view returns (uint256);
function getAssetsPrices(address[] memory assets) external view returns (uint256[] memory);
function getFallbackOracle() external view returns (address);
function getSourceOfAsset(address asset) external view returns (address);
function setAssetSources(address[] memory assets, address[] memory sources) external;
function setFallbackOracle(address fallbackOracle) external;
}
文件 8 的 21:IBaseManager.sol
pragma solidity 0.6.10;
pragma experimental "ABIEncoderV2";
import { ISetToken } from "./ISetToken.sol";
interface IBaseManager {
function setToken() external returns(ISetToken);
function methodologist() external returns(address);
function operator() external returns(address);
function interactManager(address _module, bytes calldata _encoded) external;
function transferTokens(address _token, address _destination, uint256 _amount) external;
}
文件 9 的 21:IChainlinkAggregatorV3.sol
pragma solidity 0.6.10;
interface IChainlinkAggregatorV3 {
function latestAnswer() external view returns (int256);
function latestRoundData() external view returns (
uint80 roundId,
int256 answer,
uint256 startedAt,
uint256 updatedAt,
uint80 answeredInRound
);
}
文件 10 的 21:IERC20.sol
pragma solidity >=0.6.0 <0.8.0;
interface IERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
文件 11 的 21:ILeverageModule.sol
pragma solidity 0.6.10;
pragma experimental "ABIEncoderV2";
import { ISetToken } from "./ISetToken.sol";
interface ILeverageModule {
function sync(
ISetToken _setToken
) external;
function lever(
ISetToken _setToken,
address _borrowAsset,
address _collateralAsset,
uint256 _borrowQuantity,
uint256 _minReceiveQuantity,
string memory _tradeAdapterName,
bytes memory _tradeData
) external;
function delever(
ISetToken _setToken,
address _collateralAsset,
address _repayAsset,
uint256 _redeemQuantity,
uint256 _minRepayQuantity,
string memory _tradeAdapterName,
bytes memory _tradeData
) external;
function gulp(
ISetToken _setToken,
address _collateralAsset,
uint256 _minNotionalReceiveQuantity,
string memory _tradeAdapterName,
bytes memory _tradeData
) external;
}
文件 12 的 21:IPool.sol
pragma solidity 0.6.10;
pragma experimental ABIEncoderV2;
import { DataTypes } from "./Datatypes.sol";
interface IPool {
event BackUnbacked(address indexed reserve, address indexed backer, uint256 amount, uint256 fee);
event Borrow(
address indexed reserve,
address user,
address indexed onBehalfOf,
uint256 amount,
uint8 interestRateMode,
uint256 borrowRate,
uint16 indexed referralCode
);
event FlashLoan(
address indexed target,
address initiator,
address indexed asset,
uint256 amount,
uint8 interestRateMode,
uint256 premium,
uint16 indexed referralCode
);
event IsolationModeTotalDebtUpdated(address indexed asset, uint256 totalDebt);
event LiquidationCall(
address indexed collateralAsset,
address indexed debtAsset,
address indexed user,
uint256 debtToCover,
uint256 liquidatedCollateralAmount,
address liquidator,
bool receiveAToken
);
event MintUnbacked(
address indexed reserve, address user, address indexed onBehalfOf, uint256 amount, uint16 indexed referralCode
);
event MintedToTreasury(address indexed reserve, uint256 amountMinted);
event RebalanceStableBorrowRate(address indexed reserve, address indexed user);
event Repay(
address indexed reserve, address indexed user, address indexed repayer, uint256 amount, bool useATokens
);
event ReserveDataUpdated(
address indexed reserve,
uint256 liquidityRate,
uint256 stableBorrowRate,
uint256 variableBorrowRate,
uint256 liquidityIndex,
uint256 variableBorrowIndex
);
event ReserveUsedAsCollateralDisabled(address indexed reserve, address indexed user);
event ReserveUsedAsCollateralEnabled(address indexed reserve, address indexed user);
event Supply(
address indexed reserve, address user, address indexed onBehalfOf, uint256 amount, uint16 indexed referralCode
);
event SwapBorrowRateMode(address indexed reserve, address indexed user, uint8 interestRateMode);
event UserEModeSet(address indexed user, uint8 categoryId);
event Withdraw(address indexed reserve, address indexed user, address indexed to, uint256 amount);
struct EModeCategory {
uint16 ltv;
uint16 liquidationThreshold;
uint16 liquidationBonus;
address priceSource;
string label;
}
struct ReserveConfigurationMap {
uint256 data;
}
struct ReserveData {
ReserveConfigurationMap configuration;
uint128 liquidityIndex;
uint128 currentLiquidityRate;
uint128 variableBorrowIndex;
uint128 currentVariableBorrowRate;
uint128 currentStableBorrowRate;
uint40 lastUpdateTimestamp;
uint16 id;
address aTokenAddress;
address stableDebtTokenAddress;
address variableDebtTokenAddress;
address interestRateStrategyAddress;
uint128 accruedToTreasury;
uint128 unbacked;
uint128 isolationModeTotalDebt;
}
struct UserConfigurationMap {
uint256 data;
}
function ADDRESSES_PROVIDER() external view returns (address);
function BRIDGE_PROTOCOL_FEE() external view returns (uint256);
function FLASHLOAN_PREMIUM_TOTAL() external view returns (uint128);
function FLASHLOAN_PREMIUM_TO_PROTOCOL() external view returns (uint128);
function MAX_NUMBER_RESERVES() external view returns (uint16);
function MAX_STABLE_RATE_BORROW_SIZE_PERCENT() external view returns (uint256);
function POOL_REVISION() external view returns (uint256);
function backUnbacked(address asset, uint256 amount, uint256 fee) external returns (uint256);
function borrow(address asset, uint256 amount, uint256 interestRateMode, uint16 referralCode, address onBehalfOf)
external;
function configureEModeCategory(uint8 id, DataTypes.EModeCategory memory category) external;
function deposit(address asset, uint256 amount, address onBehalfOf, uint16 referralCode) external;
function dropReserve(address asset) external;
function finalizeTransfer(
address asset,
address from,
address to,
uint256 amount,
uint256 balanceFromBefore,
uint256 balanceToBefore
) external;
function flashLoan(
address receiverAddress,
address[] memory assets,
uint256[] memory amounts,
uint256[] memory interestRateModes,
address onBehalfOf,
bytes memory params,
uint16 referralCode
) external;
function flashLoanSimple(
address receiverAddress,
address asset,
uint256 amount,
bytes memory params,
uint16 referralCode
) external;
function getConfiguration(address asset) external view returns (DataTypes.ReserveConfigurationMap memory);
function getEModeCategoryData(uint8 id) external view returns (DataTypes.EModeCategory memory);
function getReserveAddressById(uint16 id) external view returns (address);
function getReserveData(address asset) external view returns (DataTypes.ReserveData memory);
function getReserveNormalizedIncome(address asset) external view returns (uint256);
function getReserveNormalizedVariableDebt(address asset) external view returns (uint256);
function getReservesList() external view returns (address[] memory);
function getUserAccountData(address user)
external
view
returns (
uint256 totalCollateralBase,
uint256 totalDebtBase,
uint256 availableBorrowsBase,
uint256 currentLiquidationThreshold,
uint256 ltv,
uint256 healthFactor
);
function getUserConfiguration(address user) external view returns (DataTypes.UserConfigurationMap memory);
function getUserEMode(address user) external view returns (uint256);
function initReserve(
address asset,
address aTokenAddress,
address stableDebtAddress,
address variableDebtAddress,
address interestRateStrategyAddress
) external;
function initialize(address provider) external;
function liquidationCall(
address collateralAsset,
address debtAsset,
address user,
uint256 debtToCover,
bool receiveAToken
) external;
function mintToTreasury(address[] memory assets) external;
function mintUnbacked(address asset, uint256 amount, address onBehalfOf, uint16 referralCode) external;
function rebalanceStableBorrowRate(address asset, address user) external;
function repay(address asset, uint256 amount, uint256 interestRateMode, address onBehalfOf)
external
returns (uint256);
function repayWithATokens(address asset, uint256 amount, uint256 interestRateMode) external returns (uint256);
function repayWithPermit(
address asset,
uint256 amount,
uint256 interestRateMode,
address onBehalfOf,
uint256 deadline,
uint8 permitV,
bytes32 permitR,
bytes32 permitS
) external returns (uint256);
function rescueTokens(address token, address to, uint256 amount) external;
function resetIsolationModeTotalDebt(address asset) external;
function setConfiguration(address asset, DataTypes.ReserveConfigurationMap memory configuration) external;
function setReserveInterestRateStrategyAddress(address asset, address rateStrategyAddress) external;
function setUserEMode(uint8 categoryId) external;
function setUserUseReserveAsCollateral(address asset, bool useAsCollateral) external;
function supply(address asset, uint256 amount, address onBehalfOf, uint16 referralCode) external;
function supplyWithPermit(
address asset,
uint256 amount,
address onBehalfOf,
uint16 referralCode,
uint256 deadline,
uint8 permitV,
bytes32 permitR,
bytes32 permitS
) external;
function swapBorrowRateMode(address asset, uint256 interestRateMode) external;
function updateBridgeProtocolFee(uint256 protocolFee) external;
function updateFlashloanPremiums(uint128 flashLoanPremiumTotal, uint128 flashLoanPremiumToProtocol) external;
function withdraw(address asset, uint256 amount, address to) external returns (uint256);
}
文件 13 的 21:IPoolAddressesProvider.sol
pragma solidity 0.6.10;
interface IPoolAddressesProvider {
event ACLAdminUpdated(address indexed oldAddress, address indexed newAddress);
event ACLManagerUpdated(address indexed oldAddress, address indexed newAddress);
event AddressSet(bytes32 indexed id, address indexed oldAddress, address indexed newAddress);
event AddressSetAsProxy(
bytes32 indexed id,
address indexed proxyAddress,
address oldImplementationAddress,
address indexed newImplementationAddress
);
event MarketIdSet(string indexed oldMarketId, string indexed newMarketId);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
event PoolConfiguratorUpdated(address indexed oldAddress, address indexed newAddress);
event PoolDataProviderUpdated(address indexed oldAddress, address indexed newAddress);
event PoolUpdated(address indexed oldAddress, address indexed newAddress);
event PriceOracleSentinelUpdated(address indexed oldAddress, address indexed newAddress);
event PriceOracleUpdated(address indexed oldAddress, address indexed newAddress);
event ProxyCreated(bytes32 indexed id, address indexed proxyAddress, address indexed implementationAddress);
function getACLAdmin() external view returns (address);
function getACLManager() external view returns (address);
function getAddress(bytes32 id) external view returns (address);
function getMarketId() external view returns (string memory);
function getPool() external view returns (address);
function getPoolConfigurator() external view returns (address);
function getPoolDataProvider() external view returns (address);
function getPriceOracle() external view returns (address);
function getPriceOracleSentinel() external view returns (address);
function owner() external view returns (address);
function renounceOwnership() external;
function setACLAdmin(address newAclAdmin) external;
function setACLManager(address newAclManager) external;
function setAddress(bytes32 id, address newAddress) external;
function setAddressAsProxy(bytes32 id, address newImplementationAddress) external;
function setMarketId(string memory newMarketId) external;
function setPoolConfiguratorImpl(address newPoolConfiguratorImpl) external;
function setPoolDataProvider(address newDataProvider) external;
function setPoolImpl(address newPoolImpl) external;
function setPriceOracle(address newPriceOracle) external;
function setPriceOracleSentinel(address newPriceOracleSentinel) external;
function transferOwnership(address newOwner) external;
}
文件 14 的 21:IProtocolDataProvider.sol
pragma solidity 0.6.10;
pragma experimental ABIEncoderV2;
interface IProtocolDataProvider {
struct TokenData {
string symbol;
address tokenAddress;
}
function ADDRESSES_PROVIDER() external view returns (address);
function getAllReservesTokens() external view returns (TokenData[] memory);
function getAllATokens() external view returns (TokenData[] memory);
function getReserveConfigurationData(address asset) external view returns (uint256 decimals, uint256 ltv, uint256 liquidationThreshold, uint256 liquidationBonus, uint256 reserveFactor, bool usageAsCollateralEnabled, bool borrowingEnabled, bool stableBorrowRateEnabled, bool isActive, bool isFrozen);
function getReserveData(address asset) external view returns (uint256 availableLiquidity, uint256 totalStableDebt, uint256 totalVariableDebt, uint256 liquidityRate, uint256 variableBorrowRate, uint256 stableBorrowRate, uint256 averageStableBorrowRate, uint256 liquidityIndex, uint256 variableBorrowIndex, uint40 lastUpdateTimestamp);
function getUserReserveData(address asset, address user) external view returns (uint256 currentATokenBalance, uint256 currentStableDebt, uint256 currentVariableDebt, uint256 principalStableDebt, uint256 scaledVariableDebt, uint256 stableBorrowRate, uint256 liquidityRate, uint40 stableRateLastUpdated, bool usageAsCollateralEnabled);
function getReserveTokensAddresses(address asset) external view returns (address aTokenAddress, address stableDebtTokenAddress, address variableDebtTokenAddress);
}
文件 15 的 21:ISetToken.sol
pragma solidity 0.6.10;
pragma experimental "ABIEncoderV2";
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
interface ISetToken is IERC20 {
enum ModuleState {
NONE,
PENDING,
INITIALIZED
}
struct Position {
address component;
address module;
int256 unit;
uint8 positionState;
bytes data;
}
struct ComponentPosition {
int256 virtualUnit;
address[] externalPositionModules;
mapping(address => ExternalPosition) externalPositions;
}
struct ExternalPosition {
int256 virtualUnit;
bytes data;
}
function addComponent(address _component) external;
function removeComponent(address _component) external;
function editDefaultPositionUnit(address _component, int256 _realUnit) external;
function addExternalPositionModule(address _component, address _positionModule) external;
function removeExternalPositionModule(address _component, address _positionModule) external;
function editExternalPositionUnit(address _component, address _positionModule, int256 _realUnit) external;
function editExternalPositionData(address _component, address _positionModule, bytes calldata _data) external;
function invoke(address _target, uint256 _value, bytes calldata _data) external returns(bytes memory);
function editPositionMultiplier(int256 _newMultiplier) external;
function mint(address _account, uint256 _quantity) external;
function burn(address _account, uint256 _quantity) external;
function lock() external;
function unlock() external;
function addModule(address _module) external;
function removeModule(address _module) external;
function initializeModule() external;
function setManager(address _manager) external;
function manager() external view returns (address);
function moduleStates(address _module) external view returns (ModuleState);
function getModules() external view returns (address[] memory);
function getDefaultPositionRealUnit(address _component) external view returns(int256);
function getExternalPositionRealUnit(address _component, address _positionModule) external view returns(int256);
function getComponents() external view returns(address[] memory);
function getExternalPositionModules(address _component) external view returns(address[] memory);
function getExternalPositionData(address _component, address _positionModule) external view returns(bytes memory);
function isExternalPositionModule(address _component, address _module) external view returns(bool);
function isComponent(address _component) external view returns(bool);
function positionMultiplier() external view returns (int256);
function getPositions() external view returns (Position[] memory);
function getTotalComponentRealUnits(address _component) external view returns(int256);
function isInitializedModule(address _module) external view returns(bool);
function isPendingModule(address _module) external view returns(bool);
function isLocked() external view returns (bool);
}
文件 16 的 21:Math.sol
pragma solidity >=0.6.0 <0.8.0;
library Math {
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a >= b ? a : b;
}
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
function average(uint256 a, uint256 b) internal pure returns (uint256) {
return (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2);
}
}
文件 17 的 21:PreciseUnitMath.sol
pragma solidity 0.6.10;
pragma experimental ABIEncoderV2;
import { SafeMath } from "@openzeppelin/contracts/math/SafeMath.sol";
import { SignedSafeMath } from "@openzeppelin/contracts/math/SignedSafeMath.sol";
library PreciseUnitMath {
using SafeMath for uint256;
using SignedSafeMath for int256;
uint256 constant internal PRECISE_UNIT = 10 ** 18;
int256 constant internal PRECISE_UNIT_INT = 10 ** 18;
uint256 constant internal MAX_UINT_256 = type(uint256).max;
int256 constant internal MAX_INT_256 = type(int256).max;
int256 constant internal MIN_INT_256 = type(int256).min;
function preciseUnit() internal pure returns (uint256) {
return PRECISE_UNIT;
}
function preciseUnitInt() internal pure returns (int256) {
return PRECISE_UNIT_INT;
}
function maxUint256() internal pure returns (uint256) {
return MAX_UINT_256;
}
function maxInt256() internal pure returns (int256) {
return MAX_INT_256;
}
function minInt256() internal pure returns (int256) {
return MIN_INT_256;
}
function preciseMul(uint256 a, uint256 b) internal pure returns (uint256) {
return a.mul(b).div(PRECISE_UNIT);
}
function preciseMul(int256 a, int256 b) internal pure returns (int256) {
return a.mul(b).div(PRECISE_UNIT_INT);
}
function preciseMulCeil(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0 || b == 0) {
return 0;
}
return a.mul(b).sub(1).div(PRECISE_UNIT).add(1);
}
function preciseDiv(uint256 a, uint256 b) internal pure returns (uint256) {
return a.mul(PRECISE_UNIT).div(b);
}
function preciseDiv(int256 a, int256 b) internal pure returns (int256) {
return a.mul(PRECISE_UNIT_INT).div(b);
}
function preciseDivCeil(uint256 a, uint256 b) internal pure returns (uint256) {
require(b != 0, "Cant divide by 0");
return a > 0 ? a.mul(PRECISE_UNIT).sub(1).div(b).add(1) : 0;
}
function divDown(int256 a, int256 b) internal pure returns (int256) {
require(b != 0, "Cant divide by 0");
require(a != MIN_INT_256 || b != -1, "Invalid input");
int256 result = a.div(b);
if (a ^ b < 0 && a % b != 0) {
result -= 1;
}
return result;
}
function conservativePreciseMul(int256 a, int256 b) internal pure returns (int256) {
return divDown(a.mul(b), PRECISE_UNIT_INT);
}
function conservativePreciseDiv(int256 a, int256 b) internal pure returns (int256) {
return divDown(a.mul(PRECISE_UNIT_INT), b);
}
function safePower(
uint256 a,
uint256 pow
)
internal
pure
returns (uint256)
{
require(a > 0, "Value must be positive");
uint256 result = 1;
for (uint256 i = 0; i < pow; i++){
uint256 previousResult = result;
result = previousResult.mul(a);
}
return result;
}
}
文件 18 的 21:SafeCast.sol
pragma solidity >=0.6.0 <0.8.0;
library SafeCast {
function toUint128(uint256 value) internal pure returns (uint128) {
require(value < 2**128, "SafeCast: value doesn\'t fit in 128 bits");
return uint128(value);
}
function toUint64(uint256 value) internal pure returns (uint64) {
require(value < 2**64, "SafeCast: value doesn\'t fit in 64 bits");
return uint64(value);
}
function toUint32(uint256 value) internal pure returns (uint32) {
require(value < 2**32, "SafeCast: value doesn\'t fit in 32 bits");
return uint32(value);
}
function toUint16(uint256 value) internal pure returns (uint16) {
require(value < 2**16, "SafeCast: value doesn\'t fit in 16 bits");
return uint16(value);
}
function toUint8(uint256 value) internal pure returns (uint8) {
require(value < 2**8, "SafeCast: value doesn\'t fit in 8 bits");
return uint8(value);
}
function toUint256(int256 value) internal pure returns (uint256) {
require(value >= 0, "SafeCast: value must be positive");
return uint256(value);
}
function toInt128(int256 value) internal pure returns (int128) {
require(value >= -2**127 && value < 2**127, "SafeCast: value doesn\'t fit in 128 bits");
return int128(value);
}
function toInt64(int256 value) internal pure returns (int64) {
require(value >= -2**63 && value < 2**63, "SafeCast: value doesn\'t fit in 64 bits");
return int64(value);
}
function toInt32(int256 value) internal pure returns (int32) {
require(value >= -2**31 && value < 2**31, "SafeCast: value doesn\'t fit in 32 bits");
return int32(value);
}
function toInt16(int256 value) internal pure returns (int16) {
require(value >= -2**15 && value < 2**15, "SafeCast: value doesn\'t fit in 16 bits");
return int16(value);
}
function toInt8(int256 value) internal pure returns (int8) {
require(value >= -2**7 && value < 2**7, "SafeCast: value doesn\'t fit in 8 bits");
return int8(value);
}
function toInt256(uint256 value) internal pure returns (int256) {
require(value < 2**255, "SafeCast: value doesn't fit in an int256");
return int256(value);
}
}
文件 19 的 21:SafeMath.sol
pragma solidity >=0.6.0 <0.8.0;
library SafeMath {
function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b > a) return (false, 0);
return (true, a - b);
}
function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (a == 0) return (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b == 0) return (false, 0);
return (true, a / b);
}
function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b == 0) return (false, 0);
return (true, a % b);
}
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
require(b <= a, "SafeMath: subtraction overflow");
return a - b;
}
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) return 0;
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0, "SafeMath: division by zero");
return a / b;
}
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0, "SafeMath: modulo by zero");
return a % b;
}
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
return a - b;
}
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
return a / b;
}
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
return a % b;
}
}
文件 20 的 21:SignedSafeMath.sol
pragma solidity >=0.6.0 <0.8.0;
library SignedSafeMath {
int256 constant private _INT256_MIN = -2**255;
function mul(int256 a, int256 b) internal pure returns (int256) {
if (a == 0) {
return 0;
}
require(!(a == -1 && b == _INT256_MIN), "SignedSafeMath: multiplication overflow");
int256 c = a * b;
require(c / a == b, "SignedSafeMath: multiplication overflow");
return c;
}
function div(int256 a, int256 b) internal pure returns (int256) {
require(b != 0, "SignedSafeMath: division by zero");
require(!(b == -1 && a == _INT256_MIN), "SignedSafeMath: division overflow");
int256 c = a / b;
return c;
}
function sub(int256 a, int256 b) internal pure returns (int256) {
int256 c = a - b;
require((b >= 0 && c <= a) || (b < 0 && c > a), "SignedSafeMath: subtraction overflow");
return c;
}
function add(int256 a, int256 b) internal pure returns (int256) {
int256 c = a + b;
require((b >= 0 && c >= a) || (b < 0 && c < a), "SignedSafeMath: addition overflow");
return c;
}
}
文件 21 的 21:StringArrayUtils.sol
pragma solidity 0.6.10;
library StringArrayUtils {
function indexOf(string[] memory A, string memory a) internal pure returns (uint256, bool) {
uint256 length = A.length;
for (uint256 i = 0; i < length; i++) {
if (keccak256(bytes(A[i])) == keccak256(bytes(a))) {
return (i, true);
}
}
return (uint256(-1), false);
}
function removeStorage(string[] storage A, string memory a)
internal
{
(uint256 index, bool isIn) = indexOf(A, a);
if (!isIn) {
revert("String not in array.");
} else {
uint256 lastIndex = A.length - 1;
if (index != lastIndex) { A[index] = A[lastIndex]; }
A.pop();
}
}
}
{
"compilationTarget": {
"contracts/adapters/AaveV3LeverageStrategyExtension.sol": "AaveV3LeverageStrategyExtension"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs",
"useLiteralContent": true
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"contract IBaseManager","name":"_manager","type":"address"},{"components":[{"internalType":"contract ISetToken","name":"setToken","type":"address"},{"internalType":"contract ILeverageModule","name":"leverageModule","type":"address"},{"internalType":"contract IProtocolDataProvider","name":"aaveProtocolDataProvider","type":"address"},{"internalType":"contract IChainlinkAggregatorV3","name":"collateralPriceOracle","type":"address"},{"internalType":"contract IChainlinkAggregatorV3","name":"borrowPriceOracle","type":"address"},{"internalType":"contract IERC20","name":"targetCollateralAToken","type":"address"},{"internalType":"contract IERC20","name":"targetBorrowDebtToken","type":"address"},{"internalType":"address","name":"collateralAsset","type":"address"},{"internalType":"address","name":"borrowAsset","type":"address"},{"internalType":"uint256","name":"collateralDecimalAdjustment","type":"uint256"},{"internalType":"uint256","name":"borrowDecimalAdjustment","type":"uint256"}],"internalType":"struct AaveLeverageStrategyExtension.ContractSettings","name":"_strategy","type":"tuple"},{"components":[{"internalType":"uint256","name":"targetLeverageRatio","type":"uint256"},{"internalType":"uint256","name":"minLeverageRatio","type":"uint256"},{"internalType":"uint256","name":"maxLeverageRatio","type":"uint256"},{"internalType":"uint256","name":"recenteringSpeed","type":"uint256"},{"internalType":"uint256","name":"rebalanceInterval","type":"uint256"}],"internalType":"struct AaveLeverageStrategyExtension.MethodologySettings","name":"_methodology","type":"tuple"},{"components":[{"internalType":"uint256","name":"unutilizedLeveragePercentage","type":"uint256"},{"internalType":"uint256","name":"slippageTolerance","type":"uint256"},{"internalType":"uint256","name":"twapCooldownPeriod","type":"uint256"}],"internalType":"struct AaveLeverageStrategyExtension.ExecutionSettings","name":"_execution","type":"tuple"},{"components":[{"internalType":"uint256","name":"etherReward","type":"uint256"},{"internalType":"uint256","name":"incentivizedLeverageRatio","type":"uint256"},{"internalType":"uint256","name":"incentivizedSlippageTolerance","type":"uint256"},{"internalType":"uint256","name":"incentivizedTwapCooldownPeriod","type":"uint256"}],"internalType":"struct AaveLeverageStrategyExtension.IncentiveSettings","name":"_incentive","type":"tuple"},{"internalType":"string[]","name":"_exchangeNames","type":"string[]"},{"components":[{"internalType":"uint256","name":"twapMaxTradeSize","type":"uint256"},{"internalType":"uint256","name":"exchangeLastTradeTimestamp","type":"uint256"},{"internalType":"uint256","name":"incentivizedTwapMaxTradeSize","type":"uint256"},{"internalType":"bytes","name":"leverExchangeData","type":"bytes"},{"internalType":"bytes","name":"deleverExchangeData","type":"bytes"}],"internalType":"struct AaveLeverageStrategyExtension.ExchangeSettings[]","name":"_exchangeSettings","type":"tuple[]"},{"internalType":"contract IPoolAddressesProvider","name":"_lendingPoolAddressesProvider","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bool","name":"_status","type":"bool"}],"name":"AnyoneCallableUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_caller","type":"address"},{"indexed":false,"internalType":"bool","name":"_status","type":"bool"}],"name":"CallerStatusUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_currentLeverageRatio","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_newLeverageRatio","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_chunkRebalanceNotional","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_totalRebalanceNotional","type":"uint256"}],"name":"Disengaged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_currentLeverageRatio","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_newLeverageRatio","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_chunkRebalanceNotional","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_totalRebalanceNotional","type":"uint256"}],"name":"Engaged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"_exchangeName","type":"string"},{"indexed":false,"internalType":"uint256","name":"twapMaxTradeSize","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"exchangeLastTradeTimestamp","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"incentivizedTwapMaxTradeSize","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"leverExchangeData","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"deleverExchangeData","type":"bytes"}],"name":"ExchangeAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"_exchangeName","type":"string"}],"name":"ExchangeRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"_exchangeName","type":"string"},{"indexed":false,"internalType":"uint256","name":"twapMaxTradeSize","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"exchangeLastTradeTimestamp","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"incentivizedTwapMaxTradeSize","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"leverExchangeData","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"deleverExchangeData","type":"bytes"}],"name":"ExchangeUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_unutilizedLeveragePercentage","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_twapCooldownPeriod","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_slippageTolerance","type":"uint256"}],"name":"ExecutionSettingsUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_etherReward","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_incentivizedLeverageRatio","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_incentivizedSlippageTolerance","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_incentivizedTwapCooldownPeriod","type":"uint256"}],"name":"IncentiveSettingsUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_targetLeverageRatio","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_minLeverageRatio","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_maxLeverageRatio","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_recenteringSpeed","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_rebalanceInterval","type":"uint256"}],"name":"MethodologySettingsUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_currentLeverageRatio","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_newLeverageRatio","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_chunkRebalanceNotional","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_totalRebalanceNotional","type":"uint256"}],"name":"RebalanceIterated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_currentLeverageRatio","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_newLeverageRatio","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_chunkRebalanceNotional","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_totalRebalanceNotional","type":"uint256"}],"name":"Rebalanced","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_currentLeverageRatio","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_newLeverageRatio","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_rebalanceNotional","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_etherIncentive","type":"uint256"}],"name":"RipcordCalled","type":"event"},{"inputs":[{"internalType":"string","name":"_exchangeName","type":"string"},{"components":[{"internalType":"uint256","name":"twapMaxTradeSize","type":"uint256"},{"internalType":"uint256","name":"exchangeLastTradeTimestamp","type":"uint256"},{"internalType":"uint256","name":"incentivizedTwapMaxTradeSize","type":"uint256"},{"internalType":"bytes","name":"leverExchangeData","type":"bytes"},{"internalType":"bytes","name":"deleverExchangeData","type":"bytes"}],"internalType":"struct AaveLeverageStrategyExtension.ExchangeSettings","name":"_exchangeSettings","type":"tuple"}],"name":"addEnabledExchange","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"anyoneCallable","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"callAllowList","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentEModeCategoryId","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_exchangeName","type":"string"}],"name":"disengage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"enabledExchanges","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_exchangeName","type":"string"}],"name":"engage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string[]","name":"_exchangeNames","type":"string[]"}],"name":"getChunkRebalanceNotional","outputs":[{"internalType":"uint256[]","name":"sizes","type":"uint256[]"},{"internalType":"address","name":"sellAsset","type":"address"},{"internalType":"address","name":"buyAsset","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentEtherIncentive","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentLeverageRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getEnabledExchanges","outputs":[{"internalType":"string[]","name":"","type":"string[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_exchangeName","type":"string"}],"name":"getExchangeSettings","outputs":[{"components":[{"internalType":"uint256","name":"twapMaxTradeSize","type":"uint256"},{"internalType":"uint256","name":"exchangeLastTradeTimestamp","type":"uint256"},{"internalType":"uint256","name":"incentivizedTwapMaxTradeSize","type":"uint256"},{"internalType":"bytes","name":"leverExchangeData","type":"bytes"},{"internalType":"bytes","name":"deleverExchangeData","type":"bytes"}],"internalType":"struct AaveLeverageStrategyExtension.ExchangeSettings","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getExecution","outputs":[{"components":[{"internalType":"uint256","name":"unutilizedLeveragePercentage","type":"uint256"},{"internalType":"uint256","name":"slippageTolerance","type":"uint256"},{"internalType":"uint256","name":"twapCooldownPeriod","type":"uint256"}],"internalType":"struct AaveLeverageStrategyExtension.ExecutionSettings","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getIncentive","outputs":[{"components":[{"internalType":"uint256","name":"etherReward","type":"uint256"},{"internalType":"uint256","name":"incentivizedLeverageRatio","type":"uint256"},{"internalType":"uint256","name":"incentivizedSlippageTolerance","type":"uint256"},{"internalType":"uint256","name":"incentivizedTwapCooldownPeriod","type":"uint256"}],"internalType":"struct AaveLeverageStrategyExtension.IncentiveSettings","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMethodology","outputs":[{"components":[{"internalType":"uint256","name":"targetLeverageRatio","type":"uint256"},{"internalType":"uint256","name":"minLeverageRatio","type":"uint256"},{"internalType":"uint256","name":"maxLeverageRatio","type":"uint256"},{"internalType":"uint256","name":"recenteringSpeed","type":"uint256"},{"internalType":"uint256","name":"rebalanceInterval","type":"uint256"}],"internalType":"struct AaveLeverageStrategyExtension.MethodologySettings","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStrategy","outputs":[{"components":[{"internalType":"contract ISetToken","name":"setToken","type":"address"},{"internalType":"contract ILeverageModule","name":"leverageModule","type":"address"},{"internalType":"contract IProtocolDataProvider","name":"aaveProtocolDataProvider","type":"address"},{"internalType":"contract IChainlinkAggregatorV3","name":"collateralPriceOracle","type":"address"},{"internalType":"contract IChainlinkAggregatorV3","name":"borrowPriceOracle","type":"address"},{"internalType":"contract IERC20","name":"targetCollateralAToken","type":"address"},{"internalType":"contract IERC20","name":"targetBorrowDebtToken","type":"address"},{"internalType":"address","name":"collateralAsset","type":"address"},{"internalType":"address","name":"borrowAsset","type":"address"},{"internalType":"uint256","name":"collateralDecimalAdjustment","type":"uint256"},{"internalType":"uint256","name":"borrowDecimalAdjustment","type":"uint256"}],"internalType":"struct AaveLeverageStrategyExtension.ContractSettings","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"globalLastTradeTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_exchangeName","type":"string"}],"name":"iterateRebalance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lendingPoolAddressesProvider","outputs":[{"internalType":"contract IPoolAddressesProvider","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"manager","outputs":[{"internalType":"contract IBaseManager","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"overrideNoRebalanceInProgress","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_exchangeName","type":"string"}],"name":"rebalance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_exchangeName","type":"string"}],"name":"removeEnabledExchange","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_exchangeName","type":"string"}],"name":"ripcord","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"_categoryId","type":"uint8"}],"name":"setEModeCategory","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"unutilizedLeveragePercentage","type":"uint256"},{"internalType":"uint256","name":"slippageTolerance","type":"uint256"},{"internalType":"uint256","name":"twapCooldownPeriod","type":"uint256"}],"internalType":"struct AaveLeverageStrategyExtension.ExecutionSettings","name":"_newExecutionSettings","type":"tuple"}],"name":"setExecutionSettings","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"etherReward","type":"uint256"},{"internalType":"uint256","name":"incentivizedLeverageRatio","type":"uint256"},{"internalType":"uint256","name":"incentivizedSlippageTolerance","type":"uint256"},{"internalType":"uint256","name":"incentivizedTwapCooldownPeriod","type":"uint256"}],"internalType":"struct AaveLeverageStrategyExtension.IncentiveSettings","name":"_newIncentiveSettings","type":"tuple"}],"name":"setIncentiveSettings","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"targetLeverageRatio","type":"uint256"},{"internalType":"uint256","name":"minLeverageRatio","type":"uint256"},{"internalType":"uint256","name":"maxLeverageRatio","type":"uint256"},{"internalType":"uint256","name":"recenteringSpeed","type":"uint256"},{"internalType":"uint256","name":"rebalanceInterval","type":"uint256"}],"internalType":"struct AaveLeverageStrategyExtension.MethodologySettings","name":"_newMethodologySettings","type":"tuple"}],"name":"setMethodologySettings","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_overrideNoRebalanceInProgress","type":"bool"}],"name":"setOverrideNoRebalanceInProgress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"shouldRebalance","outputs":[{"internalType":"string[]","name":"","type":"string[]"},{"internalType":"enum AaveLeverageStrategyExtension.ShouldRebalance[]","name":"","type":"uint8[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_customMinLeverageRatio","type":"uint256"},{"internalType":"uint256","name":"_customMaxLeverageRatio","type":"uint256"}],"name":"shouldRebalanceWithBounds","outputs":[{"internalType":"string[]","name":"","type":"string[]"},{"internalType":"enum AaveLeverageStrategyExtension.ShouldRebalance[]","name":"","type":"uint8[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"twapLeverageRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"_status","type":"bool"}],"name":"updateAnyoneCallable","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_callers","type":"address[]"},{"internalType":"bool[]","name":"_statuses","type":"bool[]"}],"name":"updateCallerStatus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_exchangeName","type":"string"},{"components":[{"internalType":"uint256","name":"twapMaxTradeSize","type":"uint256"},{"internalType":"uint256","name":"exchangeLastTradeTimestamp","type":"uint256"},{"internalType":"uint256","name":"incentivizedTwapMaxTradeSize","type":"uint256"},{"internalType":"bytes","name":"leverExchangeData","type":"bytes"},{"internalType":"bytes","name":"deleverExchangeData","type":"bytes"}],"internalType":"struct AaveLeverageStrategyExtension.ExchangeSettings","name":"_exchangeSettings","type":"tuple"}],"name":"updateEnabledExchange","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawEtherBalance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]