aave-protocol-v2/contracts/protocol/lendingpool/LendingPoolConfigurator.sol

485 lines
16 KiB
Solidity
Raw Normal View History

// SPDX-License-Identifier: agpl-3.0
2020-11-20 10:45:20 +00:00
pragma solidity 0.6.12;
2020-07-23 15:18:06 +00:00
pragma experimental ABIEncoderV2;
import {SafeMath} from '../../dependencies/openzeppelin/contracts/SafeMath.sol';
2020-10-15 13:16:05 +00:00
import {VersionedInitializable} from '../libraries/aave-upgradeability/VersionedInitializable.sol';
2020-08-20 07:51:21 +00:00
import {
2020-10-14 11:55:38 +00:00
InitializableImmutableAdminUpgradeabilityProxy
} from '../libraries/aave-upgradeability/InitializableImmutableAdminUpgradeabilityProxy.sol';
2020-08-20 07:51:21 +00:00
import {ReserveConfiguration} from '../libraries/configuration/ReserveConfiguration.sol';
import {ILendingPoolAddressesProvider} from '../../interfaces/ILendingPoolAddressesProvider.sol';
import {ILendingPool} from '../../interfaces/ILendingPool.sol';
import {IERC20Detailed} from '../../dependencies/openzeppelin/contracts/IERC20Detailed.sol';
import {Errors} from '../libraries/helpers/Errors.sol';
2020-09-28 17:33:39 +00:00
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 {ILendingPoolConfigurator} from '../../interfaces/ILendingPoolConfigurator.sol';
/**
2020-06-20 23:40:03 +00:00
* @title LendingPoolConfigurator contract
* @author Aave
2020-11-25 14:31:27 +00:00
* @dev Implements the configuration methods for the Aave protocol
2020-06-20 23:40:03 +00:00
**/
contract LendingPoolConfigurator is VersionedInitializable, ILendingPoolConfigurator {
2020-06-20 23:40:03 +00:00
using SafeMath for uint256;
using PercentageMath for uint256;
2020-11-24 15:17:27 +00:00
using ReserveConfiguration for DataTypes.ReserveConfigurationMap;
2020-06-20 23:40:03 +00:00
2020-08-21 12:03:17 +00:00
ILendingPoolAddressesProvider internal addressesProvider;
ILendingPool internal pool;
2020-07-23 15:18:06 +00:00
2020-11-05 11:35:50 +00:00
modifier onlyPoolAdmin {
require(addressesProvider.getPoolAdmin() == msg.sender, Errors.CALLER_NOT_POOL_ADMIN);
_;
}
modifier onlyEmergencyAdmin {
require(
addressesProvider.getEmergencyAdmin() == msg.sender,
Errors.LPC_CALLER_NOT_EMERGENCY_ADMIN
);
2020-06-20 23:40:03 +00:00
_;
}
2020-11-25 14:27:17 +00:00
uint256 internal constant CONFIGURATOR_REVISION = 0x1;
2020-06-20 23:40:03 +00:00
function getRevision() internal pure override returns (uint256) {
2020-06-20 23:40:03 +00:00
return CONFIGURATOR_REVISION;
}
2020-08-21 12:03:17 +00:00
function initialize(ILendingPoolAddressesProvider provider) public initializer {
addressesProvider = provider;
pool = ILendingPool(addressesProvider.getLendingPool());
2020-06-20 23:40:03 +00:00
}
/**
* @dev Initializes reserves in batch
2020-06-20 23:40:03 +00:00
**/
function batchInitReserve(InitReserveInput[] calldata inputParams) public onlyPoolAdmin {
ILendingPool cachedPool = pool;
for (uint256 i = 0; i < inputParams.length; i++) {
_initReserve(cachedPool, inputParams[i]);
}
}
2020-10-19 16:29:32 +00:00
function _initReserve(ILendingPool pool, InitReserveInput calldata inputParams) internal {
address aTokenProxyAddress =
_initTokenWithProxy(
inputParams.aTokenImpl,
abi.encodeWithSelector(
IInitializableAToken.initialize.selector,
pool,
inputParams.treasury,
inputParams.underlyingAsset,
IAaveIncentivesController(inputParams.incentivesController),
inputParams.underlyingAssetDecimals,
inputParams.aTokenName,
inputParams.aTokenSymbol
)
);
2020-06-30 12:09:28 +00:00
address stableDebtTokenProxyAddress =
_initTokenWithProxy(
inputParams.stableDebtTokenImpl,
abi.encodeWithSelector(
IInitializableDebtToken.initialize.selector,
pool,
inputParams.underlyingAsset,
IAaveIncentivesController(inputParams.incentivesController),
inputParams.underlyingAssetDecimals,
inputParams.stableDebtTokenName,
inputParams.stableDebtTokenSymbol
)
);
2020-08-17 19:28:50 +00:00
address variableDebtTokenProxyAddress =
_initTokenWithProxy(
inputParams.variableDebtTokenImpl,
abi.encodeWithSelector(
IInitializableDebtToken.initialize.selector,
pool,
inputParams.underlyingAsset,
IAaveIncentivesController(inputParams.incentivesController),
inputParams.underlyingAssetDecimals,
inputParams.variableDebtTokenName,
inputParams.variableDebtTokenSymbol
)
);
2020-08-07 16:23:52 +00:00
2020-07-23 15:18:06 +00:00
pool.initReserve(
inputParams.underlyingAsset,
2020-08-17 19:28:50 +00:00
aTokenProxyAddress,
stableDebtTokenProxyAddress,
variableDebtTokenProxyAddress,
inputParams.interestRateStrategyAddress
);
DataTypes.ReserveConfigurationMap memory currentConfig =
pool.getConfiguration(inputParams.underlyingAsset);
2020-07-23 15:18:06 +00:00
currentConfig.setDecimals(inputParams.underlyingAssetDecimals);
2020-07-23 15:18:06 +00:00
currentConfig.setActive(true);
currentConfig.setFrozen(false);
2020-07-23 15:18:06 +00:00
pool.setConfiguration(inputParams.underlyingAsset, currentConfig.data);
2020-07-23 15:18:06 +00:00
2020-08-17 19:28:50 +00:00
emit ReserveInitialized(
inputParams.underlyingAsset,
2020-08-17 19:28:50 +00:00
aTokenProxyAddress,
stableDebtTokenProxyAddress,
variableDebtTokenProxyAddress,
inputParams.interestRateStrategyAddress
2020-08-17 19:28:50 +00:00
);
2020-06-20 23:40:03 +00:00
}
2020-08-10 18:20:08 +00:00
/**
2020-11-25 14:27:17 +00:00
* @dev Updates the aToken implementation for the reserve
2020-08-10 18:20:08 +00:00
**/
function updateAToken(UpdateATokenInput calldata inputParams) external onlyPoolAdmin {
ILendingPool cachedPool = pool;
DataTypes.ReserveData memory reserveData = cachedPool.getReserveData(inputParams.asset);
DataTypes.ReserveConfigurationMap memory configuration =
cachedPool.getConfiguration(inputParams.asset);
(, , , uint256 decimals, ) = configuration.getParamsMemory();
_upgradeTokenImplementation(
reserveData.aTokenAddress,
inputParams.implementation,
abi.encodeWithSelector(
IInitializableAToken.initialize.selector,
cachedPool,
inputParams.treasury,
inputParams.asset,
inputParams.incentivesController,
decimals,
inputParams.name,
inputParams.symbol
)
);
emit ATokenUpgraded(inputParams.asset, reserveData.aTokenAddress, inputParams.implementation);
}
/**
2020-11-25 14:27:17 +00:00
* @dev Updates the stable debt token implementation for the reserve
**/
function updateStableDebtToken(UpdateDebtTokenInput calldata inputParams) external onlyPoolAdmin {
ILendingPool cachedPool = pool;
DataTypes.ReserveData memory reserveData = cachedPool.getReserveData(inputParams.asset);
DataTypes.ReserveConfigurationMap memory configuration =
cachedPool.getConfiguration(inputParams.asset);
(, , , uint256 decimals, ) = configuration.getParamsMemory();
_upgradeTokenImplementation(
reserveData.stableDebtTokenAddress,
inputParams.implementation,
abi.encodeWithSelector(
IInitializableDebtToken.initialize.selector,
cachedPool,
inputParams.asset,
inputParams.incentivesController,
decimals,
inputParams.name,
inputParams.symbol
)
);
emit StableDebtTokenUpgraded(
inputParams.asset,
reserveData.stableDebtTokenAddress,
inputParams.implementation
);
}
/**
2020-11-25 14:27:17 +00:00
* @dev Updates the variable debt token implementation for the asset
**/
function updateVariableDebtToken(UpdateDebtTokenInput calldata inputParams)
external
onlyPoolAdmin
{
ILendingPool cachedPool = pool;
DataTypes.ReserveData memory reserveData = cachedPool.getReserveData(inputParams.asset);
DataTypes.ReserveConfigurationMap memory configuration =
cachedPool.getConfiguration(inputParams.asset);
(, , , uint256 decimals, ) = configuration.getParamsMemory();
_upgradeTokenImplementation(
reserveData.variableDebtTokenAddress,
inputParams.implementation,
abi.encodeWithSelector(
IInitializableDebtToken.initialize.selector,
cachedPool,
inputParams.asset,
inputParams.incentivesController,
decimals,
inputParams.name,
inputParams.symbol
)
);
emit VariableDebtTokenUpgraded(
inputParams.asset,
reserveData.variableDebtTokenAddress,
inputParams.implementation
);
}
2020-06-20 23:40:03 +00:00
/**
2020-11-25 14:27:17 +00:00
* @dev Enables borrowing on a reserve
* @param asset The address of the underlying asset of the reserve
* @param stableBorrowRateEnabled True if stable borrow rate needs to be enabled by default on this reserve
2020-06-20 23:40:03 +00:00
**/
2020-08-21 12:03:17 +00:00
function enableBorrowingOnReserve(address asset, bool stableBorrowRateEnabled)
2020-06-20 23:40:03 +00:00
external
2020-11-05 11:35:50 +00:00
onlyPoolAdmin
2020-06-20 23:40:03 +00:00
{
2020-11-24 15:17:27 +00:00
DataTypes.ReserveConfigurationMap memory currentConfig = pool.getConfiguration(asset);
2020-07-23 15:18:06 +00:00
currentConfig.setBorrowingEnabled(true);
2020-08-21 12:03:17 +00:00
currentConfig.setStableRateBorrowingEnabled(stableBorrowRateEnabled);
2020-07-23 15:18:06 +00:00
2020-08-21 12:03:17 +00:00
pool.setConfiguration(asset, currentConfig.data);
2020-07-23 15:18:06 +00:00
2020-08-21 12:03:17 +00:00
emit BorrowingEnabledOnReserve(asset, stableBorrowRateEnabled);
2020-06-20 23:40:03 +00:00
}
/**
2020-11-25 14:27:17 +00:00
* @dev Disables borrowing on a reserve
* @param asset The address of the underlying asset of the reserve
2020-06-20 23:40:03 +00:00
**/
2020-11-05 11:35:50 +00:00
function disableBorrowingOnReserve(address asset) external onlyPoolAdmin {
2020-11-24 15:17:27 +00:00
DataTypes.ReserveConfigurationMap memory currentConfig = pool.getConfiguration(asset);
2020-07-23 15:18:06 +00:00
currentConfig.setBorrowingEnabled(false);
2020-08-21 12:03:17 +00:00
pool.setConfiguration(asset, currentConfig.data);
emit BorrowingDisabledOnReserve(asset);
2020-06-20 23:40:03 +00:00
}
/**
2020-11-25 14:27:17 +00:00
* @dev Configures the reserve collateralization parameters
* all the values are expressed in percentages with two decimals of precision. A valid value is 10000, which means 100.00%
2020-11-25 14:27:17 +00:00
* @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. The values is always above 100%. A value of 105%
* means the liquidator will receive a 5% bonus
2020-06-20 23:40:03 +00:00
**/
2020-09-28 17:33:39 +00:00
function configureReserveAsCollateral(
2020-08-21 12:03:17 +00:00
address asset,
uint256 ltv,
uint256 liquidationThreshold,
uint256 liquidationBonus
2020-11-05 11:35:50 +00:00
) external onlyPoolAdmin {
2020-11-24 15:17:27 +00:00
DataTypes.ReserveConfigurationMap memory currentConfig = pool.getConfiguration(asset);
2020-07-23 15:18:06 +00:00
2020-10-31 11:17:59 +00:00
//validation of the parameters: the LTV can
//only be lower or equal than the liquidation threshold
2020-09-28 17:33:39 +00:00
//(otherwise a loan against the asset would cause instantaneous liquidation)
2020-10-31 12:10:26 +00:00
require(ltv <= liquidationThreshold, Errors.LPC_INVALID_CONFIGURATION);
2020-07-23 15:18:06 +00:00
2020-10-31 11:33:26 +00:00
if (liquidationThreshold != 0) {
2020-10-31 11:17:59 +00:00
//liquidation bonus must be bigger than 100.00%, otherwise the liquidator would receive less
2020-11-25 14:27:17 +00:00
//collateral than needed to cover the debt
require(
liquidationBonus > PercentageMath.PERCENTAGE_FACTOR,
Errors.LPC_INVALID_CONFIGURATION
);
2020-11-10 17:16:27 +00:00
2020-11-25 14:27:17 +00:00
//if threshold * bonus is less than PERCENTAGE_FACTOR, it's guaranteed that at the moment
//a loan is taken there is enough collateral available to cover the liquidation bonus
require(
2020-11-25 14:27:17 +00:00
liquidationThreshold.percentMul(liquidationBonus) <= PercentageMath.PERCENTAGE_FACTOR,
Errors.LPC_INVALID_CONFIGURATION
);
2020-10-31 11:17:59 +00:00
} else {
2020-10-31 12:10:26 +00:00
require(liquidationBonus == 0, Errors.LPC_INVALID_CONFIGURATION);
2020-10-31 11:33:26 +00:00
//if the liquidation threshold is being set to 0,
// the reserve is being disabled as collateral. To do so,
//we need to ensure no liquidity is deposited
2020-09-28 17:33:39 +00:00
_checkNoLiquidity(asset);
}
2020-06-20 23:40:03 +00:00
2020-08-21 12:03:17 +00:00
currentConfig.setLtv(ltv);
currentConfig.setLiquidationThreshold(liquidationThreshold);
currentConfig.setLiquidationBonus(liquidationBonus);
2020-07-23 15:18:06 +00:00
2020-08-21 12:03:17 +00:00
pool.setConfiguration(asset, currentConfig.data);
2020-07-23 15:18:06 +00:00
2020-09-28 17:33:39 +00:00
emit CollateralConfigurationChanged(asset, ltv, liquidationThreshold, liquidationBonus);
2020-06-20 23:40:03 +00:00
}
/**
2020-11-25 14:27:17 +00:00
* @dev Enable stable rate borrowing on a reserve
* @param asset The address of the underlying asset of the reserve
2020-06-20 23:40:03 +00:00
**/
2020-11-05 11:35:50 +00:00
function enableReserveStableRate(address asset) external onlyPoolAdmin {
2020-11-24 15:17:27 +00:00
DataTypes.ReserveConfigurationMap memory currentConfig = pool.getConfiguration(asset);
2020-07-23 15:18:06 +00:00
currentConfig.setStableRateBorrowingEnabled(true);
2020-08-21 12:03:17 +00:00
pool.setConfiguration(asset, currentConfig.data);
2020-06-20 23:40:03 +00:00
2020-08-21 12:03:17 +00:00
emit StableRateEnabledOnReserve(asset);
2020-06-20 23:40:03 +00:00
}
/**
2020-11-25 14:27:17 +00:00
* @dev Disable stable rate borrowing on a reserve
* @param asset The address of the underlying asset of the reserve
2020-06-20 23:40:03 +00:00
**/
2020-11-05 11:35:50 +00:00
function disableReserveStableRate(address asset) external onlyPoolAdmin {
2020-11-24 15:17:27 +00:00
DataTypes.ReserveConfigurationMap memory currentConfig = pool.getConfiguration(asset);
2020-07-23 15:18:06 +00:00
currentConfig.setStableRateBorrowingEnabled(false);
2020-08-21 12:03:17 +00:00
pool.setConfiguration(asset, currentConfig.data);
2020-06-20 23:40:03 +00:00
2020-08-21 12:03:17 +00:00
emit StableRateDisabledOnReserve(asset);
2020-06-20 23:40:03 +00:00
}
/**
2020-11-25 14:27:17 +00:00
* @dev Activates a reserve
* @param asset The address of the underlying asset of the reserve
2020-06-20 23:40:03 +00:00
**/
2020-11-05 11:35:50 +00:00
function activateReserve(address asset) external onlyPoolAdmin {
2020-11-24 15:17:27 +00:00
DataTypes.ReserveConfigurationMap memory currentConfig = pool.getConfiguration(asset);
2020-07-23 15:18:06 +00:00
currentConfig.setActive(true);
2020-08-21 12:03:17 +00:00
pool.setConfiguration(asset, currentConfig.data);
2020-06-20 23:40:03 +00:00
2020-08-21 12:03:17 +00:00
emit ReserveActivated(asset);
2020-06-20 23:40:03 +00:00
}
/**
2020-11-25 14:27:17 +00:00
* @dev Deactivates a reserve
* @param asset The address of the underlying asset of the reserve
2020-06-20 23:40:03 +00:00
**/
2020-11-05 11:35:50 +00:00
function deactivateReserve(address asset) external onlyPoolAdmin {
2020-10-30 14:12:11 +00:00
_checkNoLiquidity(asset);
2020-07-23 15:18:06 +00:00
2020-11-24 15:17:27 +00:00
DataTypes.ReserveConfigurationMap memory currentConfig = pool.getConfiguration(asset);
2020-07-23 15:18:06 +00:00
currentConfig.setActive(false);
2020-08-21 12:03:17 +00:00
pool.setConfiguration(asset, currentConfig.data);
2020-06-20 23:40:03 +00:00
2020-08-21 12:03:17 +00:00
emit ReserveDeactivated(asset);
2020-06-20 23:40:03 +00:00
}
/**
2020-11-25 14:27:17 +00:00
* @dev Freezes a reserve. A frozen reserve doesn't allow any new deposit, borrow or rate swap
* but allows repayments, liquidations, rate rebalances and withdrawals
* @param asset The address of the underlying asset of the reserve
2020-06-20 23:40:03 +00:00
**/
2020-11-05 11:35:50 +00:00
function freezeReserve(address asset) external onlyPoolAdmin {
2020-11-24 15:17:27 +00:00
DataTypes.ReserveConfigurationMap memory currentConfig = pool.getConfiguration(asset);
2020-07-23 15:18:06 +00:00
currentConfig.setFrozen(true);
2020-07-23 15:18:06 +00:00
2020-08-21 12:03:17 +00:00
pool.setConfiguration(asset, currentConfig.data);
2020-06-20 23:40:03 +00:00
2020-10-31 12:47:16 +00:00
emit ReserveFrozen(asset);
2020-06-20 23:40:03 +00:00
}
/**
2020-11-25 14:27:17 +00:00
* @dev Unfreezes a reserve
* @param asset The address of the underlying asset of the reserve
2020-06-20 23:40:03 +00:00
**/
2020-11-05 11:35:50 +00:00
function unfreezeReserve(address asset) external onlyPoolAdmin {
2020-11-24 15:17:27 +00:00
DataTypes.ReserveConfigurationMap memory currentConfig = pool.getConfiguration(asset);
2020-07-23 15:18:06 +00:00
currentConfig.setFrozen(false);
2020-07-23 15:18:06 +00:00
2020-08-21 12:03:17 +00:00
pool.setConfiguration(asset, currentConfig.data);
2020-06-20 23:40:03 +00:00
2020-10-31 12:47:16 +00:00
emit ReserveUnfrozen(asset);
2020-06-20 23:40:03 +00:00
}
2020-10-08 13:41:48 +00:00
/**
2020-11-25 14:27:17 +00:00
* @dev Updates the reserve factor of a reserve
* @param asset The address of the underlying asset of the reserve
* @param reserveFactor The new reserve factor of the reserve
**/
2020-11-05 11:35:50 +00:00
function setReserveFactor(address asset, uint256 reserveFactor) external onlyPoolAdmin {
2020-11-24 15:17:27 +00:00
DataTypes.ReserveConfigurationMap memory currentConfig = pool.getConfiguration(asset);
currentConfig.setReserveFactor(reserveFactor);
pool.setConfiguration(asset, currentConfig.data);
emit ReserveFactorChanged(asset, reserveFactor);
}
2020-06-20 23:40:03 +00:00
/**
2020-11-25 14:27:17 +00:00
* @dev Sets the interest rate strategy of a reserve
* @param asset The address of the underlying asset of the reserve
* @param rateStrategyAddress The new address of the interest strategy contract
2020-06-20 23:40:03 +00:00
**/
2020-08-21 12:03:17 +00:00
function setReserveInterestRateStrategyAddress(address asset, address rateStrategyAddress)
2020-06-20 23:40:03 +00:00
external
2020-11-05 11:35:50 +00:00
onlyPoolAdmin
2020-06-20 23:40:03 +00:00
{
2020-08-21 12:03:17 +00:00
pool.setReserveInterestRateStrategyAddress(asset, rateStrategyAddress);
emit ReserveInterestRateStrategyChanged(asset, rateStrategyAddress);
2020-06-20 23:40:03 +00:00
}
2020-08-17 19:28:50 +00:00
/**
2020-11-25 14:27:17 +00:00
* @dev pauses or unpauses all the actions of the protocol, including aToken transfers
* @param val true if protocol needs to be paused, false otherwise
2020-08-17 19:28:50 +00:00
**/
2020-11-25 14:27:17 +00:00
function setPoolPause(bool val) external onlyEmergencyAdmin {
pool.setPause(val);
}
function _initTokenWithProxy(address implementation, bytes memory initParams)
internal
returns (address)
{
InitializableImmutableAdminUpgradeabilityProxy proxy =
new InitializableImmutableAdminUpgradeabilityProxy(address(this));
2020-10-13 11:21:11 +00:00
proxy.initialize(implementation, initParams);
2020-08-17 19:28:50 +00:00
return address(proxy);
}
2020-08-18 16:48:23 +00:00
function _upgradeTokenImplementation(
2020-08-21 12:03:17 +00:00
address proxyAddress,
address implementation,
bytes memory initParams
) internal {
InitializableImmutableAdminUpgradeabilityProxy proxy =
InitializableImmutableAdminUpgradeabilityProxy(payable(proxyAddress));
proxy.upgradeToAndCall(implementation, initParams);
}
2020-09-28 17:33:39 +00:00
function _checkNoLiquidity(address asset) internal view {
DataTypes.ReserveData memory reserveData = pool.getReserveData(asset);
2020-10-30 14:12:11 +00:00
uint256 availableLiquidity = IERC20Detailed(asset).balanceOf(reserveData.aTokenAddress);
2020-09-28 17:33:39 +00:00
require(
2020-10-30 14:12:11 +00:00
availableLiquidity == 0 && reserveData.currentLiquidityRate == 0,
2020-10-31 12:10:26 +00:00
Errors.LPC_RESERVE_LIQUIDITY_NOT_0
2020-09-28 17:33:39 +00:00
);
}
}