feat: Refactor LendingPool and LendingPoolConfigurator to go below 24K

This commit is contained in:
miguelmtzinf 2021-07-29 18:21:29 +02:00
parent 72b5da643b
commit e7d9fe8367
8 changed files with 1302 additions and 599 deletions

View File

@ -2,44 +2,9 @@
pragma solidity 0.6.12;
pragma experimental ABIEncoderV2;
import {ConfiguratorInputTypes} from '../protocol/libraries/types/ConfiguratorInputTypes.sol';
interface ILendingPoolConfigurator {
struct InitReserveInput {
address aTokenImpl;
address stableDebtTokenImpl;
address variableDebtTokenImpl;
uint8 underlyingAssetDecimals;
address interestRateStrategyAddress;
address underlyingAsset;
address treasury;
address incentivesController;
string underlyingAssetName;
string aTokenName;
string aTokenSymbol;
string variableDebtTokenName;
string variableDebtTokenSymbol;
string stableDebtTokenName;
string stableDebtTokenSymbol;
bytes params;
}
struct UpdateATokenInput {
address asset;
address treasury;
address incentivesController;
string name;
string symbol;
address implementation;
bytes params;
}
struct UpdateDebtTokenInput {
address asset;
address incentivesController;
string name;
string symbol;
address implementation;
bytes params;
}
/**
* @dev Emitted when a reserve is initialized.
@ -132,12 +97,6 @@ interface ILendingPoolConfigurator {
**/
event ReserveUnpaused(address indexed asset);
/**
* @dev Emitted when a reserve is dropped
* @param asset The address of the underlying asset of the reserve
**/
event ReserveDropped(address indexed asset);
/**
* @dev Emitted when a reserve factor is updated
* @param asset The address of the underlying asset of the reserve
@ -249,25 +208,25 @@ interface ILendingPoolConfigurator {
* @dev Initializes reserves in batch
* @param input The array of reserves initialization parameters
**/
function batchInitReserve(InitReserveInput[] calldata input) external;
function batchInitReserve(ConfiguratorInputTypes.InitReserveInput[] calldata input) external;
/**
* @dev Updates the aToken implementation for the reserve
* @param input The aToken update paramenters
**/
function updateAToken(UpdateATokenInput calldata input) external;
function updateAToken(ConfiguratorInputTypes.UpdateATokenInput calldata input) external;
/**
* @dev Updates the stable debt token implementation for the reserve
* @param input The stableDebtToken update parameters
**/
function updateStableDebtToken(UpdateDebtTokenInput calldata input) external;
function updateStableDebtToken(ConfiguratorInputTypes.UpdateDebtTokenInput calldata input) external;
/**
* @dev Updates the variable debt token implementation for the asset
* @param input The variableDebtToken update parameters
**/
function updateVariableDebtToken(UpdateDebtTokenInput calldata input) external;
function updateVariableDebtToken(ConfiguratorInputTypes.UpdateDebtTokenInput calldata input) external;
/**
* @dev Enables borrowing on a reserve

View File

@ -27,6 +27,9 @@ import {UserConfiguration} from '../libraries/configuration/UserConfiguration.so
import {DataTypes} from '../libraries/types/DataTypes.sol';
import {LendingPoolStorage} from './LendingPoolStorage.sol';
import {LendingPoolBaseLogic} from '../libraries/logic/LendingPoolBaseLogic.sol';
import {LendingPoolOtherLogic} from '../libraries/logic/LendingPoolOtherLogic.sol';
/**
* @title LendingPool contract
* @dev Main point of interaction with an Aave protocol's market
@ -135,7 +138,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
address onBehalfOf
) external override {
_executeBorrow(
ExecuteBorrowParams(
DataTypes.ExecuteBorrowParams(
asset,
msg.sender,
onBehalfOf,
@ -183,90 +186,29 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
///@inheritdoc ILendingPool
function swapBorrowRateMode(address asset, uint256 rateMode) external override {
DataTypes.ReserveData storage reserve = _reserves[asset];
DataTypes.ReserveCache memory reserveCache = reserve.cache();
(uint256 stableDebt, uint256 variableDebt) = Helpers.getUserCurrentDebt(msg.sender, reserve);
DataTypes.InterestRateMode interestRateMode = DataTypes.InterestRateMode(rateMode);
ValidationLogic.validateSwapRateMode(
reserve,
reserveCache,
_usersConfig[msg.sender],
stableDebt,
variableDebt,
interestRateMode
);
reserve.updateState(reserveCache);
if (interestRateMode == DataTypes.InterestRateMode.STABLE) {
IStableDebtToken(reserveCache.stableDebtTokenAddress).burn(msg.sender, stableDebt);
IVariableDebtToken(reserveCache.variableDebtTokenAddress).mint(
msg.sender,
msg.sender,
stableDebt,
reserveCache.nextVariableBorrowIndex
);
reserveCache.refreshDebt(0, stableDebt, stableDebt, 0);
} else {
IVariableDebtToken(reserveCache.variableDebtTokenAddress).burn(
msg.sender,
variableDebt,
reserveCache.nextVariableBorrowIndex
);
IStableDebtToken(reserveCache.stableDebtTokenAddress).mint(
msg.sender,
msg.sender,
variableDebt,
reserve.currentStableBorrowRate
);
reserveCache.refreshDebt(variableDebt, 0, 0, variableDebt);
}
reserve.updateInterestRates(reserveCache, asset, 0, 0);
emit Swap(asset, msg.sender, rateMode);
DataTypes.UserConfigurationMap storage userConfig = _usersConfig[msg.sender];
LendingPoolOtherLogic.swapBorrowRateMode(reserve, userConfig, asset, rateMode);
}
///@inheritdoc ILendingPool
function rebalanceStableBorrowRate(address asset, address user) external override {
DataTypes.ReserveData storage reserve = _reserves[asset];
DataTypes.ReserveCache memory reserveCache = reserve.cache();
IERC20 stableDebtToken = IERC20(reserveCache.stableDebtTokenAddress);
IERC20 variableDebtToken = IERC20(reserveCache.variableDebtTokenAddress);
uint256 stableDebt = IERC20(stableDebtToken).balanceOf(user);
ValidationLogic.validateRebalanceStableBorrowRate(
reserve,
reserveCache,
asset,
stableDebtToken,
variableDebtToken,
reserveCache.aTokenAddress
);
reserve.updateState(reserveCache);
IStableDebtToken(address(stableDebtToken)).burn(user, stableDebt);
IStableDebtToken(address(stableDebtToken)).mint(
user,
user,
stableDebt,
reserve.currentStableBorrowRate
);
reserveCache.refreshDebt(stableDebt, stableDebt, 0, 0);
reserve.updateInterestRates(reserveCache, asset, 0, 0);
emit RebalanceStableBorrowRate(asset, user);
LendingPoolOtherLogic.rebalanceStableBorrowRate(reserve, asset, user);
}
///@inheritdoc ILendingPool
function setUserUseReserveAsCollateral(address asset, bool useAsCollateral) external override {
DataTypes.ReserveData storage reserve = _reserves[asset];
DataTypes.UserConfigurationMap storage userConfig = _usersConfig[msg.sender];
LendingPoolOtherLogic.setUserUseReserveAsCollateral(
_reserves,
userConfig,
asset,
useAsCollateral,
_reservesList,
_reservesCount,
_addressesProvider.getPriceOracle()
);
/* DataTypes.ReserveData storage reserve = _reserves[asset];
DataTypes.ReserveCache memory reserveCache = reserve.cache();
uint256 userBalance = IERC20(reserveCache.aTokenAddress).balanceOf(msg.sender);
@ -289,7 +231,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
);
emit ReserveUsedAsCollateralDisabled(asset, msg.sender);
}
}*/
}
///@inheritdoc ILendingPool
@ -303,17 +245,16 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
address collateralManager = _addressesProvider.getLendingPoolCollateralManager();
//solium-disable-next-line
(bool success, bytes memory result) =
collateralManager.delegatecall(
abi.encodeWithSignature(
'liquidationCall(address,address,address,uint256,bool)',
collateralAsset,
debtAsset,
user,
debtToCover,
receiveAToken
)
);
(bool success, bytes memory result) = collateralManager.delegatecall(
abi.encodeWithSignature(
'liquidationCall(address,address,address,uint256,bool)',
collateralAsset,
debtAsset,
user,
debtToCover,
receiveAToken
)
);
require(success, Errors.LP_LIQUIDATION_CALL_FAILED);
@ -410,7 +351,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
// If the user chose to not return the funds, the system checks if there is enough collateral and
// eventually opens a debt position
_executeBorrow(
ExecuteBorrowParams(
DataTypes.ExecuteBorrowParams(
vars.currentAsset,
msg.sender,
onBehalfOf,
@ -714,23 +655,29 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
_flashLoanPremiumToProtocol = flashLoanPremiumToProtocol;
}
struct ExecuteBorrowParams {
address asset;
address user;
address onBehalfOf;
uint256 amount;
uint256 interestRateMode;
uint16 referralCode;
bool releaseUnderlying;
function _executeDeposit(
address asset,
uint256 amount,
address onBehalfOf,
uint16 referralCode
) internal {
DataTypes.ReserveData storage reserve = _reserves[asset];
LendingPoolBaseLogic._executeDeposit(
reserve,
_usersConfig[onBehalfOf],
asset,
amount,
onBehalfOf,
referralCode
);
}
function _executeBorrow(ExecuteBorrowParams memory vars) internal {
function _executeBorrow(DataTypes.ExecuteBorrowParams memory vars) internal {
DataTypes.ReserveData storage reserve = _reserves[vars.asset];
DataTypes.UserConfigurationMap storage userConfig = _usersConfig[vars.onBehalfOf];
DataTypes.ReserveCache memory reserveCache = reserve.cache();
DataTypes.UserConfigurationMap storage userConfig = _usersConfig[vars.onBehalfOf];
reserve.updateState(reserveCache);
ValidationLogic.validateBorrow(
reserveCache,
vars.asset,
@ -745,86 +692,10 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
_addressesProvider.getPriceOracle()
);
uint256 currentStableRate = 0;
bool isFirstBorrowing = false;
if (DataTypes.InterestRateMode(vars.interestRateMode) == DataTypes.InterestRateMode.STABLE) {
currentStableRate = reserve.currentStableBorrowRate;
isFirstBorrowing = IStableDebtToken(reserveCache.stableDebtTokenAddress).mint(
vars.user,
vars.onBehalfOf,
vars.amount,
currentStableRate
);
reserveCache.refreshDebt(vars.amount, 0, 0, 0);
} else {
isFirstBorrowing = IVariableDebtToken(reserveCache.variableDebtTokenAddress).mint(
vars.user,
vars.onBehalfOf,
vars.amount,
reserveCache.nextVariableBorrowIndex
);
reserveCache.refreshDebt(0, 0, vars.amount, 0);
}
if (isFirstBorrowing) {
userConfig.setBorrowing(reserve.id, true);
}
reserve.updateInterestRates(
reserveCache,
vars.asset,
0,
vars.releaseUnderlying ? vars.amount : 0
);
LendingPoolBaseLogic._executeBorrow(_reserves, reserveCache, userConfig, vars);
_lastBorrower = vars.user;
_lastBorrowTimestamp = uint40(block.timestamp);
if (vars.releaseUnderlying) {
IAToken(reserveCache.aTokenAddress).transferUnderlyingTo(vars.user, vars.amount);
}
emit Borrow(
vars.asset,
vars.user,
vars.onBehalfOf,
vars.amount,
vars.interestRateMode,
DataTypes.InterestRateMode(vars.interestRateMode) == DataTypes.InterestRateMode.STABLE
? currentStableRate
: reserve.currentVariableBorrowRate,
vars.referralCode
);
}
function _executeDeposit(
address asset,
uint256 amount,
address onBehalfOf,
uint16 referralCode
) internal {
DataTypes.ReserveData storage reserve = _reserves[asset];
DataTypes.ReserveCache memory reserveCache = reserve.cache();
reserve.updateState(reserveCache);
ValidationLogic.validateDeposit(reserveCache, amount);
reserve.updateInterestRates(reserveCache, asset, amount, 0);
IERC20(asset).safeTransferFrom(msg.sender, reserveCache.aTokenAddress, amount);
bool isFirstDeposit =
IAToken(reserveCache.aTokenAddress).mint(onBehalfOf, amount, reserveCache.nextLiquidityIndex);
if (isFirstDeposit) {
_usersConfig[onBehalfOf].setUsingAsCollateral(reserve.id, true);
emit ReserveUsedAsCollateralEnabled(asset, onBehalfOf);
}
emit Deposit(asset, msg.sender, onBehalfOf, amount, referralCode);
}
function _executeWithdraw(
@ -832,56 +703,18 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
uint256 amount,
address to
) internal returns (uint256) {
DataTypes.ReserveData storage reserve = _reserves[asset];
DataTypes.UserConfigurationMap storage userConfig = _usersConfig[msg.sender];
DataTypes.ReserveCache memory reserveCache = reserve.cache();
reserve.updateState(reserveCache);
uint256 userBalance =
IAToken(reserveCache.aTokenAddress).scaledBalanceOf(msg.sender).rayMul(
reserveCache.nextLiquidityIndex
return
LendingPoolBaseLogic._executeWithdraw(
_reserves,
userConfig,
asset,
amount,
to,
_reservesList,
_reservesCount,
_addressesProvider.getPriceOracle()
);
uint256 amountToWithdraw = amount;
if (amount == type(uint256).max) {
amountToWithdraw = userBalance;
}
ValidationLogic.validateWithdraw(reserveCache, amountToWithdraw, userBalance);
reserve.updateInterestRates(reserveCache, asset, 0, amountToWithdraw);
IAToken(reserveCache.aTokenAddress).burn(
msg.sender,
to,
amountToWithdraw,
reserveCache.nextLiquidityIndex
);
if (userConfig.isUsingAsCollateral(reserve.id)) {
if (userConfig.isBorrowingAny()) {
ValidationLogic.validateHFAndLtv(
asset,
msg.sender,
_reserves,
userConfig,
_reservesList,
_reservesCount,
_addressesProvider.getPriceOracle()
);
}
if (amountToWithdraw == userBalance) {
userConfig.setUsingAsCollateral(reserve.id, false);
emit ReserveUsedAsCollateralDisabled(asset, msg.sender);
}
}
emit Withdraw(asset, msg.sender, to, amountToWithdraw);
return amountToWithdraw;
}
function _executeRepay(
@ -891,57 +724,18 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
address onBehalfOf
) internal returns (uint256) {
DataTypes.ReserveData storage reserve = _reserves[asset];
DataTypes.ReserveCache memory reserveCache = reserve.cache();
(uint256 stableDebt, uint256 variableDebt) = Helpers.getUserCurrentDebt(onBehalfOf, reserve);
DataTypes.InterestRateMode interestRateMode = DataTypes.InterestRateMode(rateMode);
ValidationLogic.validateRepay(
_lastBorrower,
_lastBorrowTimestamp,
reserveCache,
amount,
interestRateMode,
onBehalfOf,
stableDebt,
variableDebt
);
uint256 paybackAmount =
interestRateMode == DataTypes.InterestRateMode.STABLE ? stableDebt : variableDebt;
if (amount < paybackAmount) {
paybackAmount = amount;
}
reserve.updateState(reserveCache);
if (interestRateMode == DataTypes.InterestRateMode.STABLE) {
IStableDebtToken(reserveCache.stableDebtTokenAddress).burn(onBehalfOf, paybackAmount);
reserveCache.refreshDebt(0, paybackAmount, 0, 0);
} else {
IVariableDebtToken(reserveCache.variableDebtTokenAddress).burn(
DataTypes.UserConfigurationMap storage userConfig = _usersConfig[msg.sender];
return
LendingPoolBaseLogic._executeRepay(
reserve,
userConfig,
asset,
amount,
rateMode,
onBehalfOf,
paybackAmount,
reserveCache.nextVariableBorrowIndex
_lastBorrower,
_lastBorrowTimestamp
);
reserveCache.refreshDebt(0, 0, 0, paybackAmount);
}
reserve.updateInterestRates(reserveCache, asset, paybackAmount, 0);
if (stableDebt.add(variableDebt).sub(paybackAmount) == 0) {
_usersConfig[onBehalfOf].setBorrowing(reserve.id, false);
}
IERC20(asset).safeTransferFrom(msg.sender, reserveCache.aTokenAddress, paybackAmount);
IAToken(reserveCache.aTokenAddress).handleRepayment(msg.sender, paybackAmount);
emit Repay(asset, onBehalfOf, msg.sender, paybackAmount);
return paybackAmount;
}
function _addReserveToList(address asset) internal returns (uint8) {
@ -966,4 +760,4 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
function _removeReserveFromList(address asset) internal {
_reservesList[_reserves[asset].id] = address(0);
}
}
}

View File

@ -4,9 +4,6 @@ pragma experimental ABIEncoderV2;
import {SafeMath} from '../../dependencies/openzeppelin/contracts/SafeMath.sol';
import {VersionedInitializable} from '../libraries/aave-upgradeability/VersionedInitializable.sol';
import {
InitializableImmutableAdminUpgradeabilityProxy
} from '../libraries/aave-upgradeability/InitializableImmutableAdminUpgradeabilityProxy.sol';
import {ReserveConfiguration} from '../libraries/configuration/ReserveConfiguration.sol';
import {ILendingPoolAddressesProvider} from '../../interfaces/ILendingPoolAddressesProvider.sol';
import {ILendingPool} from '../../interfaces/ILendingPool.sol';
@ -14,10 +11,9 @@ import {IERC20Detailed} from '../../dependencies/openzeppelin/contracts/IERC20De
import {Errors} from '../libraries/helpers/Errors.sol';
import {PercentageMath} from '../libraries/math/PercentageMath.sol';
import {DataTypes} from '../libraries/types/DataTypes.sol';
import {IInitializableDebtToken} from '../../interfaces/IInitializableDebtToken.sol';
import {IInitializableAToken} from '../../interfaces/IInitializableAToken.sol';
import {IAaveIncentivesController} from '../../interfaces/IAaveIncentivesController.sol';
import {ConfiguratorInputTypes} from '../libraries/types/ConfiguratorInputTypes.sol';
import {ILendingPoolConfigurator} from '../../interfaces/ILendingPoolConfigurator.sol';
import {ConfiguratorLogic} from '../libraries/logic/ConfiguratorLogic.sol';
/**
* @title LendingPoolConfigurator contract
@ -29,6 +25,7 @@ contract LendingPoolConfigurator is VersionedInitializable, ILendingPoolConfigur
using SafeMath for uint256;
using PercentageMath for uint256;
using ReserveConfiguration for DataTypes.ReserveConfigurationMap;
using ConfiguratorLogic for DataTypes.ReserveConfigurationMap;
ILendingPoolAddressesProvider internal _addressesProvider;
ILendingPool internal _pool;
@ -77,191 +74,47 @@ contract LendingPoolConfigurator is VersionedInitializable, ILendingPoolConfigur
}
/// @inheritdoc ILendingPoolConfigurator
function batchInitReserve(InitReserveInput[] calldata input) external override onlyPoolAdmin {
function batchInitReserve(ConfiguratorInputTypes.InitReserveInput[] calldata input)
external
override
onlyPoolAdmin
{
ILendingPool cachedPool = _pool;
for (uint256 i = 0; i < input.length; i++) {
_initReserve(cachedPool, input[i]);
ConfiguratorLogic._initReserve(cachedPool, input[i]);
}
}
function _initReserve(ILendingPool pool, InitReserveInput calldata input) internal {
address aTokenProxyAddress =
_initTokenWithProxy(
input.aTokenImpl,
abi.encodeWithSelector(
IInitializableAToken.initialize.selector,
pool,
input.treasury,
input.underlyingAsset,
IAaveIncentivesController(input.incentivesController),
input.underlyingAssetDecimals,
input.aTokenName,
input.aTokenSymbol,
input.params
)
);
address stableDebtTokenProxyAddress =
_initTokenWithProxy(
input.stableDebtTokenImpl,
abi.encodeWithSelector(
IInitializableDebtToken.initialize.selector,
pool,
input.underlyingAsset,
IAaveIncentivesController(input.incentivesController),
input.underlyingAssetDecimals,
input.stableDebtTokenName,
input.stableDebtTokenSymbol,
input.params
)
);
address variableDebtTokenProxyAddress =
_initTokenWithProxy(
input.variableDebtTokenImpl,
abi.encodeWithSelector(
IInitializableDebtToken.initialize.selector,
pool,
input.underlyingAsset,
IAaveIncentivesController(input.incentivesController),
input.underlyingAssetDecimals,
input.variableDebtTokenName,
input.variableDebtTokenSymbol,
input.params
)
);
pool.initReserve(
input.underlyingAsset,
aTokenProxyAddress,
stableDebtTokenProxyAddress,
variableDebtTokenProxyAddress,
input.interestRateStrategyAddress
);
DataTypes.ReserveConfigurationMap memory currentConfig =
pool.getConfiguration(input.underlyingAsset);
currentConfig.setDecimals(input.underlyingAssetDecimals);
currentConfig.setActive(true);
currentConfig.setPaused(false);
currentConfig.setFrozen(false);
pool.setConfiguration(input.underlyingAsset, currentConfig.data);
emit ReserveInitialized(
input.underlyingAsset,
aTokenProxyAddress,
stableDebtTokenProxyAddress,
variableDebtTokenProxyAddress,
input.interestRateStrategyAddress
);
}
/// @inheritdoc ILendingPoolConfigurator
function dropReserve(address asset) external override onlyPoolAdmin {
_pool.dropReserve(asset);
emit ReserveDropped(asset);
ConfiguratorLogic.dropReserve(_pool, asset);
}
/// @inheritdoc ILendingPoolConfigurator
function updateAToken(UpdateATokenInput calldata input) external override onlyPoolAdmin {
ILendingPool cachedPool = _pool;
DataTypes.ReserveData memory reserveData = cachedPool.getReserveData(input.asset);
(, , , uint256 decimals, ) = cachedPool.getConfiguration(input.asset).getParamsMemory();
bytes memory encodedCall =
abi.encodeWithSelector(
IInitializableAToken.initialize.selector,
cachedPool,
input.treasury,
input.asset,
input.incentivesController,
decimals,
input.name,
input.symbol,
input.params
);
_upgradeTokenImplementation(reserveData.aTokenAddress, input.implementation, encodedCall);
emit ATokenUpgraded(input.asset, reserveData.aTokenAddress, input.implementation);
}
/// @inheritdoc ILendingPoolConfigurator
function updateStableDebtToken(UpdateDebtTokenInput calldata input)
function updateAToken(ConfiguratorInputTypes.UpdateATokenInput calldata input)
external
override
onlyPoolAdmin
{
ILendingPool cachedPool = _pool;
DataTypes.ReserveData memory reserveData = cachedPool.getReserveData(input.asset);
(, , , uint256 decimals, ) = cachedPool.getConfiguration(input.asset).getParamsMemory();
bytes memory encodedCall =
abi.encodeWithSelector(
IInitializableDebtToken.initialize.selector,
cachedPool,
input.asset,
input.incentivesController,
decimals,
input.name,
input.symbol,
input.params
);
_upgradeTokenImplementation(
reserveData.stableDebtTokenAddress,
input.implementation,
encodedCall
);
emit StableDebtTokenUpgraded(
input.asset,
reserveData.stableDebtTokenAddress,
input.implementation
);
ConfiguratorLogic.updateAToken(_pool, input);
}
/// @inheritdoc ILendingPoolConfigurator
function updateVariableDebtToken(UpdateDebtTokenInput calldata input)
function updateStableDebtToken(ConfiguratorInputTypes.UpdateDebtTokenInput calldata input)
external
override
onlyPoolAdmin
{
ILendingPool cachedPool = _pool;
DataTypes.ReserveData memory reserveData = cachedPool.getReserveData(input.asset);
ConfiguratorLogic.updateStableDebtToken(_pool, input);
}
(, , , uint256 decimals, ) = cachedPool.getConfiguration(input.asset).getParamsMemory();
bytes memory encodedCall =
abi.encodeWithSelector(
IInitializableDebtToken.initialize.selector,
cachedPool,
input.asset,
input.incentivesController,
decimals,
input.name,
input.symbol,
input.params
);
_upgradeTokenImplementation(
reserveData.variableDebtTokenAddress,
input.implementation,
encodedCall
);
emit VariableDebtTokenUpgraded(
input.asset,
reserveData.variableDebtTokenAddress,
input.implementation
);
/// @inheritdoc ILendingPoolConfigurator
function updateVariableDebtToken(ConfiguratorInputTypes.UpdateDebtTokenInput calldata input)
external
override
onlyPoolAdmin
{
ConfiguratorLogic.updateStableDebtToken(_pool, input);
}
/// @inheritdoc ILendingPoolConfigurator
@ -271,24 +124,13 @@ contract LendingPoolConfigurator is VersionedInitializable, ILendingPoolConfigur
bool stableBorrowRateEnabled
) external override onlyRiskOrPoolAdmins {
DataTypes.ReserveConfigurationMap memory currentConfig = _pool.getConfiguration(asset);
currentConfig.setBorrowingEnabled(true);
currentConfig.setBorrowCap(borrowCap);
currentConfig.setStableRateBorrowingEnabled(stableBorrowRateEnabled);
_pool.setConfiguration(asset, currentConfig.data);
emit BorrowingEnabledOnReserve(asset, stableBorrowRateEnabled);
currentConfig.enableBorrowingOnReserve(_pool, asset, borrowCap, stableBorrowRateEnabled);
}
/// @inheritdoc ILendingPoolConfigurator
function disableBorrowingOnReserve(address asset) external override onlyRiskOrPoolAdmins {
DataTypes.ReserveConfigurationMap memory currentConfig = _pool.getConfiguration(asset);
currentConfig.setBorrowingEnabled(false);
_pool.setConfiguration(asset, currentConfig.data);
emit BorrowingDisabledOnReserve(asset);
currentConfig.disableBorrowingOnReserve(_pool, asset);
}
/// @inheritdoc ILendingPoolConfigurator
@ -327,46 +169,25 @@ contract LendingPoolConfigurator is VersionedInitializable, ILendingPoolConfigur
_checkNoLiquidity(asset);
}
currentConfig.setLtv(ltv);
currentConfig.setLiquidationThreshold(liquidationThreshold);
currentConfig.setLiquidationBonus(liquidationBonus);
_pool.setConfiguration(asset, currentConfig.data);
emit CollateralConfigurationChanged(asset, ltv, liquidationThreshold, liquidationBonus);
currentConfig.configureReserveAsCollateral(_pool, asset, ltv, liquidationThreshold, liquidationBonus);
}
/// @inheritdoc ILendingPoolConfigurator
function enableReserveStableRate(address asset) external override onlyRiskOrPoolAdmins {
DataTypes.ReserveConfigurationMap memory currentConfig = _pool.getConfiguration(asset);
currentConfig.setStableRateBorrowingEnabled(true);
_pool.setConfiguration(asset, currentConfig.data);
emit StableRateEnabledOnReserve(asset);
currentConfig.enableReserveStableRate(_pool, asset);
}
/// @inheritdoc ILendingPoolConfigurator
function disableReserveStableRate(address asset) external override onlyRiskOrPoolAdmins {
DataTypes.ReserveConfigurationMap memory currentConfig = _pool.getConfiguration(asset);
currentConfig.setStableRateBorrowingEnabled(false);
_pool.setConfiguration(asset, currentConfig.data);
emit StableRateDisabledOnReserve(asset);
currentConfig.disableReserveStableRate(_pool, asset);
}
/// @inheritdoc ILendingPoolConfigurator
function activateReserve(address asset) external override onlyPoolAdmin {
DataTypes.ReserveConfigurationMap memory currentConfig = _pool.getConfiguration(asset);
currentConfig.setActive(true);
_pool.setConfiguration(asset, currentConfig.data);
emit ReserveActivated(asset);
currentConfig.activateReserve(_pool, asset);
}
/// @inheritdoc ILendingPoolConfigurator
@ -374,49 +195,25 @@ contract LendingPoolConfigurator is VersionedInitializable, ILendingPoolConfigur
_checkNoLiquidity(asset);
DataTypes.ReserveConfigurationMap memory currentConfig = _pool.getConfiguration(asset);
currentConfig.setActive(false);
_pool.setConfiguration(asset, currentConfig.data);
emit ReserveDeactivated(asset);
currentConfig.deactivateReserve(_pool, asset);
}
/// @inheritdoc ILendingPoolConfigurator
function freezeReserve(address asset) external override onlyRiskOrPoolAdmins {
DataTypes.ReserveConfigurationMap memory currentConfig = _pool.getConfiguration(asset);
currentConfig.setFrozen(true);
_pool.setConfiguration(asset, currentConfig.data);
emit ReserveFrozen(asset);
currentConfig.freezeReserve(_pool, asset);
}
/// @inheritdoc ILendingPoolConfigurator
function unfreezeReserve(address asset) external override onlyRiskOrPoolAdmins {
DataTypes.ReserveConfigurationMap memory currentConfig = _pool.getConfiguration(asset);
currentConfig.setFrozen(false);
_pool.setConfiguration(asset, currentConfig.data);
emit ReserveUnfrozen(asset);
currentConfig.unfreezeReserve(_pool, asset);
}
/// @inheritdoc ILendingPoolConfigurator
function setReservePause(address asset, bool paused) public override onlyEmergencyOrPoolAdmin {
DataTypes.ReserveConfigurationMap memory currentConfig = _pool.getConfiguration(asset);
currentConfig.setPaused(paused);
_pool.setConfiguration(asset, currentConfig.data);
if (paused) {
emit ReservePaused(asset);
} else {
emit ReserveUnpaused(asset);
}
currentConfig.setReservePause(_pool, asset, paused);
}
/// @inheritdoc ILendingPoolConfigurator
@ -426,34 +223,19 @@ contract LendingPoolConfigurator is VersionedInitializable, ILendingPoolConfigur
onlyRiskOrPoolAdmins
{
DataTypes.ReserveConfigurationMap memory currentConfig = _pool.getConfiguration(asset);
currentConfig.setReserveFactor(reserveFactor);
_pool.setConfiguration(asset, currentConfig.data);
emit ReserveFactorChanged(asset, reserveFactor);
currentConfig.setReserveFactor(_pool, asset, reserveFactor);
}
///@inheritdoc ILendingPoolConfigurator
function setBorrowCap(address asset, uint256 borrowCap) external override onlyRiskOrPoolAdmins {
DataTypes.ReserveConfigurationMap memory currentConfig = _pool.getConfiguration(asset);
currentConfig.setBorrowCap(borrowCap);
_pool.setConfiguration(asset, currentConfig.data);
emit BorrowCapChanged(asset, borrowCap);
currentConfig.setBorrowCap(_pool, asset, borrowCap);
}
///@inheritdoc ILendingPoolConfigurator
function setSupplyCap(address asset, uint256 supplyCap) external override onlyRiskOrPoolAdmins {
DataTypes.ReserveConfigurationMap memory currentConfig = _pool.getConfiguration(asset);
currentConfig.setSupplyCap(supplyCap);
_pool.setConfiguration(asset, currentConfig.data);
emit SupplyCapChanged(asset, supplyCap);
currentConfig.setSupplyCap(_pool, asset, supplyCap);
}
///@inheritdoc ILendingPoolConfigurator
@ -471,7 +253,8 @@ contract LendingPoolConfigurator is VersionedInitializable, ILendingPoolConfigur
address[] memory reserves = _pool.getReservesList();
for (uint256 i = 0; i < reserves.length; i++) {
if (reserves[i] != address(0)) { //might happen is a reserve was dropped
if (reserves[i] != address(0)) {
//might happen is a reserve was dropped
setReservePause(reserves[i], paused);
}
}
@ -542,29 +325,6 @@ contract LendingPoolConfigurator is VersionedInitializable, ILendingPoolConfigur
emit FlashloanPremiumToProcolUpdated(flashloanPremiumToProtocol);
}
function _initTokenWithProxy(address implementation, bytes memory initParams)
internal
returns (address)
{
InitializableImmutableAdminUpgradeabilityProxy proxy =
new InitializableImmutableAdminUpgradeabilityProxy(address(this));
proxy.initialize(implementation, initParams);
return address(proxy);
}
function _upgradeTokenImplementation(
address proxyAddress,
address implementation,
bytes memory initParams
) internal {
InitializableImmutableAdminUpgradeabilityProxy proxy =
InitializableImmutableAdminUpgradeabilityProxy(payable(proxyAddress));
proxy.upgradeToAndCall(implementation, initParams);
}
function _checkNoLiquidity(address asset) internal view {
DataTypes.ReserveData memory reserveData = _pool.getReserveData(asset);

View File

@ -0,0 +1,606 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity 0.6.12;
pragma experimental ABIEncoderV2;
import {ILendingPool} from '../../../interfaces/ILendingPool.sol';
import {ReserveConfiguration} from '../configuration/ReserveConfiguration.sol';
import {DataTypes} from '../types/DataTypes.sol';
import {ConfiguratorInputTypes} from '../types/ConfiguratorInputTypes.sol';
import {IInitializableAToken} from '../../../interfaces/IInitializableAToken.sol';
import {IInitializableDebtToken} from '../../../interfaces/IInitializableDebtToken.sol';
import {IAaveIncentivesController} from '../../../interfaces/IAaveIncentivesController.sol';
import {InitializableImmutableAdminUpgradeabilityProxy} from '../aave-upgradeability/InitializableImmutableAdminUpgradeabilityProxy.sol';
/**
* @title ConfiguratorLogic library
* @author Aave
* @notice Implements the logic for CONFIGURATOR
*/
library ConfiguratorLogic {
using ReserveConfiguration for DataTypes.ReserveConfigurationMap;
function _initReserve(ILendingPool pool, ConfiguratorInputTypes.InitReserveInput calldata input)
public
{
address aTokenProxyAddress = _initTokenWithProxy(
input.aTokenImpl,
abi.encodeWithSelector(
IInitializableAToken.initialize.selector,
pool,
input.treasury,
input.underlyingAsset,
IAaveIncentivesController(input.incentivesController),
input.underlyingAssetDecimals,
input.aTokenName,
input.aTokenSymbol,
input.params
)
);
address stableDebtTokenProxyAddress = _initTokenWithProxy(
input.stableDebtTokenImpl,
abi.encodeWithSelector(
IInitializableDebtToken.initialize.selector,
pool,
input.underlyingAsset,
IAaveIncentivesController(input.incentivesController),
input.underlyingAssetDecimals,
input.stableDebtTokenName,
input.stableDebtTokenSymbol,
input.params
)
);
address variableDebtTokenProxyAddress = _initTokenWithProxy(
input.variableDebtTokenImpl,
abi.encodeWithSelector(
IInitializableDebtToken.initialize.selector,
pool,
input.underlyingAsset,
IAaveIncentivesController(input.incentivesController),
input.underlyingAssetDecimals,
input.variableDebtTokenName,
input.variableDebtTokenSymbol,
input.params
)
);
pool.initReserve(
input.underlyingAsset,
aTokenProxyAddress,
stableDebtTokenProxyAddress,
variableDebtTokenProxyAddress,
input.interestRateStrategyAddress
);
DataTypes.ReserveConfigurationMap memory currentConfig = pool.getConfiguration(
input.underlyingAsset
);
currentConfig.setDecimals(input.underlyingAssetDecimals);
currentConfig.setActive(true);
currentConfig.setPaused(false);
currentConfig.setFrozen(false);
pool.setConfiguration(input.underlyingAsset, currentConfig.data);
emit ReserveInitialized(
input.underlyingAsset,
aTokenProxyAddress,
stableDebtTokenProxyAddress,
variableDebtTokenProxyAddress,
input.interestRateStrategyAddress
);
}
function dropReserve(ILendingPool pool, address asset) external {
pool.dropReserve(asset);
emit ReserveDropped(asset);
}
/**
* @dev Updates the aToken implementation for the reserve
**/
function updateAToken(
ILendingPool cachedPool,
ConfiguratorInputTypes.UpdateATokenInput calldata input
) public {
DataTypes.ReserveData memory reserveData = cachedPool.getReserveData(input.asset);
(, , , uint256 decimals, ) = cachedPool.getConfiguration(input.asset).getParamsMemory();
bytes memory encodedCall = abi.encodeWithSelector(
IInitializableAToken.initialize.selector,
cachedPool,
input.treasury,
input.asset,
input.incentivesController,
decimals,
input.name,
input.symbol,
input.params
);
_upgradeTokenImplementation(reserveData.aTokenAddress, input.implementation, encodedCall);
emit ATokenUpgraded(input.asset, reserveData.aTokenAddress, input.implementation);
}
/**
* @dev Updates the stable debt token implementation for the reserve
**/
function updateStableDebtToken(
ILendingPool cachedPool,
ConfiguratorInputTypes.UpdateDebtTokenInput calldata input
) public {
DataTypes.ReserveData memory reserveData = cachedPool.getReserveData(input.asset);
(, , , uint256 decimals, ) = cachedPool.getConfiguration(input.asset).getParamsMemory();
bytes memory encodedCall = abi.encodeWithSelector(
IInitializableDebtToken.initialize.selector,
cachedPool,
input.asset,
input.incentivesController,
decimals,
input.name,
input.symbol,
input.params
);
_upgradeTokenImplementation(
reserveData.stableDebtTokenAddress,
input.implementation,
encodedCall
);
emit StableDebtTokenUpgraded(
input.asset,
reserveData.stableDebtTokenAddress,
input.implementation
);
}
/**
* @dev Updates the variable debt token implementation for the asset
**/
function updateVariableDebtToken(
ILendingPool cachedPool,
ConfiguratorInputTypes.UpdateDebtTokenInput calldata input
) public {
DataTypes.ReserveData memory reserveData = cachedPool.getReserveData(input.asset);
(, , , uint256 decimals, ) = cachedPool.getConfiguration(input.asset).getParamsMemory();
bytes memory encodedCall = abi.encodeWithSelector(
IInitializableDebtToken.initialize.selector,
cachedPool,
input.asset,
input.incentivesController,
decimals,
input.name,
input.symbol,
input.params
);
_upgradeTokenImplementation(
reserveData.variableDebtTokenAddress,
input.implementation,
encodedCall
);
emit VariableDebtTokenUpgraded(
input.asset,
reserveData.variableDebtTokenAddress,
input.implementation
);
}
function _initTokenWithProxy(address implementation, bytes memory initParams)
internal
returns (address)
{
InitializableImmutableAdminUpgradeabilityProxy proxy
= new InitializableImmutableAdminUpgradeabilityProxy(address(this));
proxy.initialize(implementation, initParams);
return address(proxy);
}
function _upgradeTokenImplementation(
address proxyAddress,
address implementation,
bytes memory initParams
) internal {
InitializableImmutableAdminUpgradeabilityProxy proxy
= InitializableImmutableAdminUpgradeabilityProxy(payable(proxyAddress));
proxy.upgradeToAndCall(implementation, initParams);
}
// Reserve
function enableBorrowingOnReserve(
DataTypes.ReserveConfigurationMap memory currentConfig,
ILendingPool pool,
address asset,
uint256 borrowCap,
bool stableBorrowRateEnabled
) external {
currentConfig.setBorrowingEnabled(true);
currentConfig.setBorrowCap(borrowCap);
currentConfig.setStableRateBorrowingEnabled(stableBorrowRateEnabled);
pool.setConfiguration(asset, currentConfig.data);
emit BorrowingEnabledOnReserve(asset, stableBorrowRateEnabled);
}
function disableBorrowingOnReserve(
DataTypes.ReserveConfigurationMap memory currentConfig,
ILendingPool pool,
address asset
) external {
currentConfig.setBorrowingEnabled(false);
pool.setConfiguration(asset, currentConfig.data);
emit BorrowingDisabledOnReserve(asset);
}
function configureReserveAsCollateral(
DataTypes.ReserveConfigurationMap memory currentConfig,
ILendingPool pool,
address asset,
uint256 ltv,
uint256 liquidationThreshold,
uint256 liquidationBonus
) external {
currentConfig.setLtv(ltv);
currentConfig.setLiquidationThreshold(liquidationThreshold);
currentConfig.setLiquidationBonus(liquidationBonus);
pool.setConfiguration(asset, currentConfig.data);
emit CollateralConfigurationChanged(asset, ltv, liquidationThreshold, liquidationBonus);
}
function enableReserveStableRate(
DataTypes.ReserveConfigurationMap memory currentConfig,
ILendingPool pool,
address asset
) external {
currentConfig.setStableRateBorrowingEnabled(true);
pool.setConfiguration(asset, currentConfig.data);
emit StableRateEnabledOnReserve(asset);
}
function disableReserveStableRate(
DataTypes.ReserveConfigurationMap memory currentConfig,
ILendingPool pool,
address asset
) external {
currentConfig.setStableRateBorrowingEnabled(false);
pool.setConfiguration(asset, currentConfig.data);
emit StableRateDisabledOnReserve(asset);
}
function activateReserve(
DataTypes.ReserveConfigurationMap memory currentConfig,
ILendingPool pool,
address asset
) external {
currentConfig.setActive(true);
pool.setConfiguration(asset, currentConfig.data);
emit ReserveActivated(asset);
}
function deactivateReserve(
DataTypes.ReserveConfigurationMap memory currentConfig,
ILendingPool pool,
address asset
) external {
currentConfig.setActive(false);
pool.setConfiguration(asset, currentConfig.data);
emit ReserveDeactivated(asset);
}
function freezeReserve(
DataTypes.ReserveConfigurationMap memory currentConfig,
ILendingPool pool,
address asset
) external {
currentConfig.setFrozen(true);
pool.setConfiguration(asset, currentConfig.data);
emit ReserveFrozen(asset);
}
function unfreezeReserve(
DataTypes.ReserveConfigurationMap memory currentConfig,
ILendingPool pool,
address asset
) external {
currentConfig.setFrozen(false);
pool.setConfiguration(asset, currentConfig.data);
emit ReserveUnfrozen(asset);
}
function setReservePause(
DataTypes.ReserveConfigurationMap memory currentConfig,
ILendingPool pool,
address asset,
bool paused
) public {
DataTypes.ReserveConfigurationMap memory currentConfig = pool.getConfiguration(asset);
currentConfig.setPaused(paused);
pool.setConfiguration(asset, currentConfig.data);
if (paused) {
emit ReservePaused(asset);
} else {
emit ReserveUnpaused(asset);
}
}
function setReserveFactor(
DataTypes.ReserveConfigurationMap memory currentConfig,
ILendingPool pool,
address asset,
uint256 reserveFactor
) external {
currentConfig.setReserveFactor(reserveFactor);
pool.setConfiguration(asset, currentConfig.data);
emit ReserveFactorChanged(asset, reserveFactor);
}
function setBorrowCap(
DataTypes.ReserveConfigurationMap memory currentConfig,
ILendingPool pool,
address asset,
uint256 borrowCap
) external {
currentConfig.setBorrowCap(borrowCap);
pool.setConfiguration(asset, currentConfig.data);
emit BorrowCapChanged(asset, borrowCap);
}
function setSupplyCap(
DataTypes.ReserveConfigurationMap memory currentConfig,
ILendingPool pool,
address asset,
uint256 supplyCap
) external {
currentConfig.setSupplyCap(supplyCap);
pool.setConfiguration(asset, currentConfig.data);
emit SupplyCapChanged(asset, supplyCap);
}
///
/**
* @dev Emitted when a reserve is initialized.
* @param asset The address of the underlying asset of the reserve
* @param aToken The address of the associated aToken contract
* @param stableDebtToken The address of the associated stable rate debt token
* @param variableDebtToken The address of the associated variable rate debt token
* @param interestRateStrategyAddress The address of the interest rate strategy for the reserve
**/
event ReserveInitialized(
address indexed asset,
address indexed aToken,
address stableDebtToken,
address variableDebtToken,
address interestRateStrategyAddress
);
/**
* @dev Emitted when borrowing is enabled on a reserve
* @param asset The address of the underlying asset of the reserve
* @param stableRateEnabled True if stable rate borrowing is enabled, false otherwise
**/
event BorrowingEnabledOnReserve(address indexed asset, bool stableRateEnabled);
/**
* @dev Emitted when borrowing is disabled on a reserve
* @param asset The address of the underlying asset of the reserve
**/
event BorrowingDisabledOnReserve(address indexed asset);
/**
* @dev Emitted when the collateralization risk parameters for the specified asset are updated.
* @param asset The address of the underlying asset of the reserve
* @param ltv The loan to value of the asset when used as collateral
* @param liquidationThreshold The threshold at which loans using this asset as collateral will be considered undercollateralized
* @param liquidationBonus The bonus liquidators receive to liquidate this asset
**/
event CollateralConfigurationChanged(
address indexed asset,
uint256 ltv,
uint256 liquidationThreshold,
uint256 liquidationBonus
);
/**
* @dev Emitted when stable rate borrowing is enabled on a reserve
* @param asset The address of the underlying asset of the reserve
**/
event StableRateEnabledOnReserve(address indexed asset);
/**
* @dev Emitted when stable rate borrowing is disabled on a reserve
* @param asset The address of the underlying asset of the reserve
**/
event StableRateDisabledOnReserve(address indexed asset);
/**
* @dev Emitted when a reserve is activated
* @param asset The address of the underlying asset of the reserve
**/
event ReserveActivated(address indexed asset);
/**
* @dev Emitted when a reserve is deactivated
* @param asset The address of the underlying asset of the reserve
**/
event ReserveDeactivated(address indexed asset);
/**
* @dev Emitted when a reserve is frozen
* @param asset The address of the underlying asset of the reserve
**/
event ReserveFrozen(address indexed asset);
/**
* @dev Emitted when a reserve is unfrozen
* @param asset The address of the underlying asset of the reserve
**/
event ReserveUnfrozen(address indexed asset);
/**
* @dev Emitted when a reserve is paused
* @param asset The address of the underlying asset of the reserve
**/
event ReservePaused(address indexed asset);
/**
* @dev Emitted when a reserve is unpaused
* @param asset The address of the underlying asset of the reserve
**/
event ReserveUnpaused(address indexed asset);
/**
* @dev Emitted when a reserve is dropped
* @param asset The address of the underlying asset of the reserve
**/
event ReserveDropped(address indexed asset);
/**
* @dev Emitted when a reserve factor is updated
* @param asset The address of the underlying asset of the reserve
* @param factor The new reserve factor
**/
event ReserveFactorChanged(address indexed asset, uint256 factor);
/**
* @dev Emitted when the borrow cap of a reserve is updated
* @param asset The address of the underlying asset of the reserve
* @param borrowCap The new borrow cap
**/
event BorrowCapChanged(address indexed asset, uint256 borrowCap);
/**
* @dev Emitted when the supply cap of a reserve is updated
* @param asset The address of the underlying asset of the reserve
* @param supplyCap The new supply cap
**/
event SupplyCapChanged(address indexed asset, uint256 supplyCap);
/**
* @dev Emitted when the reserve decimals are updated
* @param asset The address of the underlying asset of the reserve
* @param decimals The new decimals
**/
event ReserveDecimalsChanged(address indexed asset, uint256 decimals);
/**
* @dev Emitted when a reserve interest strategy contract is updated
* @param asset The address of the underlying asset of the reserve
* @param strategy The new address of the interest strategy contract
**/
event ReserveInterestRateStrategyChanged(address indexed asset, address strategy);
/**
* @dev Emitted when an aToken implementation is upgraded
* @param asset The address of the underlying asset of the reserve
* @param proxy The aToken proxy address
* @param implementation The new aToken implementation
**/
event ATokenUpgraded(
address indexed asset,
address indexed proxy,
address indexed implementation
);
/**
* @dev Emitted when the implementation of a stable debt token is upgraded
* @param asset The address of the underlying asset of the reserve
* @param proxy The stable debt token proxy address
* @param implementation The new aToken implementation
**/
event StableDebtTokenUpgraded(
address indexed asset,
address indexed proxy,
address indexed implementation
);
/**
* @dev Emitted when the implementation of a variable debt token is upgraded
* @param asset The address of the underlying asset of the reserve
* @param proxy The variable debt token proxy address
* @param implementation The new aToken implementation
**/
event VariableDebtTokenUpgraded(
address indexed asset,
address indexed proxy,
address indexed implementation
);
/**
* @dev Emitted when a new borrower is authorized (fees = 0)
* @param flashBorrower The address of the authorized borrower
**/
event FlashBorrowerAuthorized(address indexed flashBorrower);
/**
* @dev Emitted when a borrower is unauthorized
* @param flashBorrower The address of the unauthorized borrower
**/
event FlashBorrowerUnauthorized(address indexed flashBorrower);
/**
* @dev Emitted when a new risk admin is registered
* @param admin the newly registered admin
**/
event RiskAdminRegistered(address indexed admin);
/**
* @dev Emitted when a risk admin is unregistered
* @param admin the unregistered admin
**/
event RiskAdminUnregistered(address indexed admin);
/**
* @dev Emitted when a the total premium on flashloans is updated
* @param flashloanPremiumTotal the new premium
**/
event FlashloanPremiumTotalUpdated(uint256 flashloanPremiumTotal);
/**
* @dev Emitted when a the part of the premium that goes to protoco lis updated
* @param flashloanPremiumToProtocol the new premium
**/
event FlashloanPremiumToProcolUpdated(uint256 flashloanPremiumToProtocol);
}

View File

@ -0,0 +1,351 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity 0.6.12;
pragma experimental ABIEncoderV2;
import {IERC20} from '../../../dependencies/openzeppelin/contracts/IERC20.sol';
import {SafeMath} from '../../../dependencies/openzeppelin/contracts/SafeMath.sol';
import {SafeERC20} from '../../../dependencies/openzeppelin/contracts/SafeERC20.sol';
import {IAToken} from '../../../interfaces/IAToken.sol';
import {Helpers} from '../helpers/Helpers.sol';
import {ValidationLogic} from './ValidationLogic.sol';
import {ReserveLogic} from './ReserveLogic.sol';
import {DataTypes} from './../types/DataTypes.sol';
import {IStableDebtToken} from '../../../interfaces/IStableDebtToken.sol';
import {IVariableDebtToken} from '../../../interfaces/IVariableDebtToken.sol';
import {UserConfiguration} from './../configuration/UserConfiguration.sol';
import {WadRayMath} from '../math/WadRayMath.sol';
/**
* @title LendingPoolBaseLogic Library
* @author Aave
* @title Implements lendingpool basic logic to perform actions to limit the contract size.
*/
library LendingPoolBaseLogic {
using ReserveLogic for DataTypes.ReserveCache;
using ReserveLogic for DataTypes.ReserveData;
using UserConfiguration for DataTypes.UserConfigurationMap;
using SafeMath for uint256;
using SafeERC20 for IERC20;
using WadRayMath for uint256;
/**
* @dev Emitted on deposit()
* @param reserve The address of the underlying asset of the reserve
* @param user The address initiating the deposit
* @param onBehalfOf The beneficiary of the deposit, receiving the aTokens
* @param amount The amount deposited
* @param referral The referral code used
**/
event Deposit(
address indexed reserve,
address user,
address indexed onBehalfOf,
uint256 amount,
uint16 indexed referral
);
/**
* @dev Emitted on withdraw()
* @param reserve The address of the underlyng asset being withdrawn
* @param user The address initiating the withdrawal, owner of aTokens
* @param to Address that will receive the underlying
* @param amount The amount to be withdrawn
**/
event Withdraw(address indexed reserve, address indexed user, address indexed to, uint256 amount);
/**
* @dev Emitted on borrow() and flashLoan() when debt needs to be opened
* @param reserve The address of the underlying asset being borrowed
* @param user The address of the user initiating the borrow(), receiving the funds on borrow() or just
* initiator of the transaction on flashLoan()
* @param onBehalfOf The address that will be getting the debt
* @param amount The amount borrowed out
* @param borrowRateMode The rate mode: 1 for Stable, 2 for Variable
* @param borrowRate The numeric rate at which the user has borrowed
* @param referral The referral code used
**/
event Borrow(
address indexed reserve,
address user,
address indexed onBehalfOf,
uint256 amount,
uint256 borrowRateMode,
uint256 borrowRate,
uint16 indexed referral
);
/**
* @dev Emitted on repay()
* @param reserve The address of the underlying asset of the reserve
* @param user The beneficiary of the repayment, getting his debt reduced
* @param repayer The address of the user initiating the repay(), providing the funds
* @param amount The amount repaid
**/
event Repay(
address indexed reserve,
address indexed user,
address indexed repayer,
uint256 amount
);
/**
* @dev Emitted on setUserUseReserveAsCollateral()
* @param reserve The address of the underlying asset of the reserve
* @param user The address of the user enabling the usage as collateral
**/
event ReserveUsedAsCollateralEnabled(address indexed reserve, address indexed user);
/**
* @dev Emitted on setUserUseReserveAsCollateral()
* @param reserve The address of the underlying asset of the reserve
* @param user The address of the user enabling the usage as collateral
**/
event ReserveUsedAsCollateralDisabled(address indexed reserve, address indexed user);
function _executeDeposit(
DataTypes.ReserveData storage reserve,
DataTypes.UserConfigurationMap storage userConfig,
address asset,
uint256 amount,
address onBehalfOf,
uint16 referralCode
) public {
DataTypes.ReserveCache memory reserveCache = reserve.cache();
reserve.updateState(reserveCache);
ValidationLogic.validateDeposit(reserveCache, amount);
reserve.updateInterestRates(reserveCache, asset, amount, 0);
IERC20(asset).safeTransferFrom(msg.sender, reserveCache.aTokenAddress, amount);
bool isFirstDeposit =
IAToken(reserveCache.aTokenAddress).mint(onBehalfOf, amount, reserveCache.nextLiquidityIndex);
if (isFirstDeposit) {
userConfig.setUsingAsCollateral(reserve.id, true);
emit ReserveUsedAsCollateralEnabled(asset, onBehalfOf);
}
emit Deposit(asset, msg.sender, onBehalfOf, amount, referralCode);
}
function _executeWithdraw(
mapping(address => DataTypes.ReserveData) storage reserves,
DataTypes.UserConfigurationMap storage userConfig,
address asset,
uint256 amount,
address to,
mapping(uint256 => address) storage reservesList,
uint256 reservesCount,
address priceOracle
) public returns (uint256) {
DataTypes.ReserveData storage reserve = reserves[asset];
DataTypes.ReserveCache memory reserveCache = reserve.cache();
reserve.updateState(reserveCache);
uint256 userBalance =
IAToken(reserveCache.aTokenAddress).scaledBalanceOf(msg.sender).rayMul(
reserveCache.nextLiquidityIndex
);
uint256 amountToWithdraw = amount;
if (amount == type(uint256).max) {
amountToWithdraw = userBalance;
}
ValidationLogic.validateWithdraw(reserveCache, amountToWithdraw, userBalance);
reserve.updateInterestRates(reserveCache, asset, 0, amountToWithdraw);
IAToken(reserveCache.aTokenAddress).burn(
msg.sender,
to,
amountToWithdraw,
reserveCache.nextLiquidityIndex
);
if (userConfig.isUsingAsCollateral(reserve.id)) {
if (userConfig.isBorrowingAny()) {
_validateHFAndLtv(asset, reserves, userConfig, reservesList, reservesCount, priceOracle);
}
if (amountToWithdraw == userBalance) {
userConfig.setUsingAsCollateral(reserve.id, false);
emit ReserveUsedAsCollateralDisabled(asset, msg.sender);
}
}
emit Withdraw(asset, msg.sender, to, amountToWithdraw);
return amountToWithdraw;
}
function _validateHFAndLtv(
address asset,
mapping(address => DataTypes.ReserveData) storage reserves,
DataTypes.UserConfigurationMap storage userConfig,
mapping(uint256 => address) storage reservesList,
uint256 reservesCount,
address priceOracle
) public {
ValidationLogic.validateHFAndLtv(
asset,
msg.sender,
reserves,
userConfig,
reservesList,
reservesCount,
priceOracle
);
}
function _executeBorrow(
mapping(address => DataTypes.ReserveData) storage reserves,
DataTypes.ReserveCache memory reserveCache,
DataTypes.UserConfigurationMap storage userConfig,
DataTypes.ExecuteBorrowParams memory vars
) public {
DataTypes.ReserveData storage reserve = reserves[vars.asset];
uint256 currentStableRate = 0;
bool isFirstBorrowing = false;
if (DataTypes.InterestRateMode(vars.interestRateMode) == DataTypes.InterestRateMode.STABLE) {
currentStableRate = reserve.currentStableBorrowRate;
isFirstBorrowing = IStableDebtToken(reserveCache.stableDebtTokenAddress).mint(
vars.user,
vars.onBehalfOf,
vars.amount,
currentStableRate
);
reserveCache.refreshDebt(vars.amount, 0, 0, 0);
} else {
isFirstBorrowing = IVariableDebtToken(reserveCache.variableDebtTokenAddress).mint(
vars.user,
vars.onBehalfOf,
vars.amount,
reserveCache.nextVariableBorrowIndex
);
reserveCache.refreshDebt(0, 0, vars.amount, 0);
}
if (isFirstBorrowing) {
userConfig.setBorrowing(reserve.id, true);
}
reserve.updateInterestRates(
reserveCache,
vars.asset,
0,
vars.releaseUnderlying ? vars.amount : 0
);
if (vars.releaseUnderlying) {
IAToken(reserveCache.aTokenAddress).transferUnderlyingTo(vars.user, vars.amount);
}
emit Borrow(
vars.asset,
vars.user,
vars.onBehalfOf,
vars.amount,
vars.interestRateMode,
DataTypes.InterestRateMode(vars.interestRateMode) == DataTypes.InterestRateMode.STABLE
? currentStableRate
: reserve.currentVariableBorrowRate,
vars.referralCode
);
}
function _executeRepay(
DataTypes.ReserveData storage reserve,
DataTypes.UserConfigurationMap storage userConfig,
address asset,
uint256 amount,
uint256 rateMode,
address onBehalfOf,
address lastBorrower,
uint40 lastBorrowTimestamp
) public returns (uint256) {
DataTypes.ReserveCache memory reserveCache = reserve.cache();
(uint256 stableDebt, uint256 variableDebt) = Helpers.getUserCurrentDebt(onBehalfOf, reserve);
DataTypes.InterestRateMode interestRateMode = DataTypes.InterestRateMode(rateMode);
ValidationLogic.validateRepay(
lastBorrower,
lastBorrowTimestamp,
reserveCache,
amount,
interestRateMode,
onBehalfOf,
stableDebt,
variableDebt
);
uint256 paybackAmount =
interestRateMode == DataTypes.InterestRateMode.STABLE ? stableDebt : variableDebt;
if (amount < paybackAmount) {
paybackAmount = amount;
}
reserve.updateState(reserveCache);
if (interestRateMode == DataTypes.InterestRateMode.STABLE) {
IStableDebtToken(reserveCache.stableDebtTokenAddress).burn(onBehalfOf, paybackAmount);
reserveCache.refreshDebt(0, paybackAmount, 0, 0);
} else {
IVariableDebtToken(reserveCache.variableDebtTokenAddress).burn(
onBehalfOf,
paybackAmount,
reserveCache.nextVariableBorrowIndex
);
reserveCache.refreshDebt(0, 0, 0, paybackAmount);
}
return
_executeRepayHelper(
reserve,
reserveCache,
userConfig,
asset,
onBehalfOf,
paybackAmount,
variableDebt,
stableDebt
);
}
function _executeRepayHelper(
DataTypes.ReserveData storage reserve,
DataTypes.ReserveCache memory reserveCache,
DataTypes.UserConfigurationMap storage userConfig,
address asset,
address onBehalfOf,
uint256 paybackAmount,
uint256 variableDebt,
uint256 stableDebt
) public returns (uint256) {
reserve.updateInterestRates(reserveCache, asset, paybackAmount, 0);
if (stableDebt.add(variableDebt).sub(paybackAmount) == 0) {
userConfig.setBorrowing(reserve.id, false);
}
IERC20(asset).safeTransferFrom(msg.sender, reserveCache.aTokenAddress, paybackAmount);
IAToken(reserveCache.aTokenAddress).handleRepayment(msg.sender, paybackAmount);
emit Repay(asset, onBehalfOf, msg.sender, paybackAmount);
return paybackAmount;
}
}

View File

@ -0,0 +1,181 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity 0.6.12;
pragma experimental ABIEncoderV2;
import {IERC20} from '../../../dependencies/openzeppelin/contracts/IERC20.sol';
import {SafeMath} from '../../../dependencies/openzeppelin/contracts/SafeMath.sol';
import {SafeERC20} from '../../../dependencies/openzeppelin/contracts/SafeERC20.sol';
import {IAToken} from '../../../interfaces/IAToken.sol';
import {Helpers} from '../helpers/Helpers.sol';
import {ValidationLogic} from './ValidationLogic.sol';
import {ReserveLogic} from './ReserveLogic.sol';
import {DataTypes} from './../types/DataTypes.sol';
import {IStableDebtToken} from '../../../interfaces/IStableDebtToken.sol';
import {IVariableDebtToken} from '../../../interfaces/IVariableDebtToken.sol';
import {UserConfiguration} from './../configuration/UserConfiguration.sol';
import {WadRayMath} from '../math/WadRayMath.sol';
library LendingPoolOtherLogic {
using ReserveLogic for DataTypes.ReserveCache;
using ReserveLogic for DataTypes.ReserveData;
using UserConfiguration for DataTypes.UserConfigurationMap;
using SafeMath for uint256;
using SafeERC20 for IERC20;
using WadRayMath for uint256;
/**
* @dev Emitted on setUserUseReserveAsCollateral()
* @param reserve The address of the underlying asset of the reserve
* @param user The address of the user enabling the usage as collateral
**/
event ReserveUsedAsCollateralEnabled(address indexed reserve, address indexed user);
/**
* @dev Emitted on setUserUseReserveAsCollateral()
* @param reserve The address of the underlying asset of the reserve
* @param user The address of the user enabling the usage as collateral
**/
event ReserveUsedAsCollateralDisabled(address indexed reserve, address indexed user);
/**
* @dev Emitted on rebalanceStableBorrowRate()
* @param reserve The address of the underlying asset of the reserve
* @param user The address of the user for which the rebalance has been executed
**/
event RebalanceStableBorrowRate(address indexed reserve, address indexed user);
/**
* @dev Emitted on swapBorrowRateMode()
* @param reserve The address of the underlying asset of the reserve
* @param user The address of the user swapping his rate mode
* @param rateMode The rate mode that the user wants to swap to
**/
event Swap(address indexed reserve, address indexed user, uint256 rateMode);
function rebalanceStableBorrowRate(
DataTypes.ReserveData storage reserve,
address asset,
address user
) public {
DataTypes.ReserveCache memory reserveCache = reserve.cache();
IERC20 stableDebtToken = IERC20(reserveCache.stableDebtTokenAddress);
IERC20 variableDebtToken = IERC20(reserveCache.variableDebtTokenAddress);
uint256 stableDebt = IERC20(stableDebtToken).balanceOf(user);
ValidationLogic.validateRebalanceStableBorrowRate(
reserve,
reserveCache,
asset,
stableDebtToken,
variableDebtToken,
reserveCache.aTokenAddress
);
reserve.updateState(reserveCache);
IStableDebtToken(address(stableDebtToken)).burn(user, stableDebt);
IStableDebtToken(address(stableDebtToken)).mint(
user,
user,
stableDebt,
reserve.currentStableBorrowRate
);
reserveCache.refreshDebt(stableDebt, stableDebt, 0, 0);
reserve.updateInterestRates(reserveCache, asset, 0, 0);
emit RebalanceStableBorrowRate(asset, user);
}
function swapBorrowRateMode(
DataTypes.ReserveData storage reserve,
DataTypes.UserConfigurationMap storage userConfig,
address asset,
uint256 rateMode
) public {
DataTypes.ReserveCache memory reserveCache = reserve.cache();
(uint256 stableDebt, uint256 variableDebt) = Helpers.getUserCurrentDebt(msg.sender, reserve);
DataTypes.InterestRateMode interestRateMode = DataTypes.InterestRateMode(rateMode);
ValidationLogic.validateSwapRateMode(
reserve,
reserveCache,
userConfig,
stableDebt,
variableDebt,
interestRateMode
);
reserve.updateState(reserveCache);
if (interestRateMode == DataTypes.InterestRateMode.STABLE) {
IStableDebtToken(reserveCache.stableDebtTokenAddress).burn(msg.sender, stableDebt);
IVariableDebtToken(reserveCache.variableDebtTokenAddress).mint(
msg.sender,
msg.sender,
stableDebt,
reserveCache.nextVariableBorrowIndex
);
reserveCache.refreshDebt(0, stableDebt, stableDebt, 0);
} else {
IVariableDebtToken(reserveCache.variableDebtTokenAddress).burn(
msg.sender,
variableDebt,
reserveCache.nextVariableBorrowIndex
);
IStableDebtToken(reserveCache.stableDebtTokenAddress).mint(
msg.sender,
msg.sender,
variableDebt,
reserve.currentStableBorrowRate
);
reserveCache.refreshDebt(variableDebt, 0, 0, variableDebt);
}
reserve.updateInterestRates(reserveCache, asset, 0, 0);
emit Swap(asset, msg.sender, rateMode);
}
function setUserUseReserveAsCollateral(
mapping(address => DataTypes.ReserveData) storage reserves,
DataTypes.UserConfigurationMap storage userConfig,
address asset,
bool useAsCollateral,
mapping(uint256 => address) storage reservesList,
uint256 reservesCount,
address priceOracle
) public {
DataTypes.ReserveData storage reserve = reserves[asset];
DataTypes.ReserveCache memory reserveCache = reserve.cache();
uint256 userBalance = IERC20(reserveCache.aTokenAddress).balanceOf(msg.sender);
ValidationLogic.validateSetUseReserveAsCollateral(reserveCache, userBalance);
userConfig.setUsingAsCollateral(reserve.id, useAsCollateral);
if (useAsCollateral) {
emit ReserveUsedAsCollateralEnabled(asset, msg.sender);
} else {
ValidationLogic.validateHFAndLtv(
asset,
msg.sender,
reserves,
userConfig,
reservesList,
reservesCount,
priceOracle
);
emit ReserveUsedAsCollateralDisabled(asset, msg.sender);
}
}
}

View File

@ -0,0 +1,42 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity 0.6.12;
library ConfiguratorInputTypes {
struct InitReserveInput {
address aTokenImpl;
address stableDebtTokenImpl;
address variableDebtTokenImpl;
uint8 underlyingAssetDecimals;
address interestRateStrategyAddress;
address underlyingAsset;
address treasury;
address incentivesController;
string underlyingAssetName;
string aTokenName;
string aTokenSymbol;
string variableDebtTokenName;
string variableDebtTokenSymbol;
string stableDebtTokenName;
string stableDebtTokenSymbol;
bytes params;
}
struct UpdateATokenInput {
address asset;
address treasury;
address incentivesController;
string name;
string symbol;
address implementation;
bytes params;
}
struct UpdateDebtTokenInput {
address asset;
address incentivesController;
string name;
string symbol;
address implementation;
bytes params;
}
}

View File

@ -73,4 +73,14 @@ library DataTypes {
uint40 reserveLastUpdateTimestamp;
uint40 stableDebtLastUpdateTimestamp;
}
struct ExecuteBorrowParams {
address asset;
address user;
address onBehalfOf;
uint256 amount;
uint256 interestRateMode;
uint16 referralCode;
bool releaseUnderlying;
}
}