mirror of
https://github.com/Instadapp/aave-protocol-v2.git
synced 2024-07-29 21:47:30 +00:00
feat: Refactor LendingPool and LendingPoolConfigurator to go below 24K
This commit is contained in:
parent
72b5da643b
commit
e7d9fe8367
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
|
||||
|
|
606
contracts/protocol/libraries/logic/ConfiguratorLogic.sol
Normal file
606
contracts/protocol/libraries/logic/ConfiguratorLogic.sol
Normal 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);
|
||||
}
|
351
contracts/protocol/libraries/logic/LendingPoolBaseLogic.sol
Normal file
351
contracts/protocol/libraries/logic/LendingPoolBaseLogic.sol
Normal 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;
|
||||
}
|
||||
}
|
181
contracts/protocol/libraries/logic/LendingPoolOtherLogic.sol
Normal file
181
contracts/protocol/libraries/logic/LendingPoolOtherLogic.sol
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user