Cleanup LendingPool

This commit is contained in:
The3D 2020-08-21 13:15:29 +02:00
parent b93937f4fd
commit 05fac16063

View File

@ -46,127 +46,103 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable, ILendingPool {
LendingPoolAddressesProvider public addressesProvider; LendingPoolAddressesProvider public addressesProvider;
using SafeERC20 for IERC20; using SafeERC20 for IERC20;
mapping(address => ReserveLogic.ReserveData) internal reserves; mapping(address => ReserveLogic.ReserveData) internal _reserves;
mapping(address => UserConfiguration.Map) internal usersConfig; mapping(address => UserConfiguration.Map) internal _usersConfig;
address[] public reservesList; address[] public reservesList;
/** /**
* @dev emitted on deposit * @dev emitted on deposit
* @param _reserve the address of the reserve * @param reserve the address of the reserve
* @param _user the address of the user * @param user the address of the user
* @param _amount the amount to be deposited * @param amount the amount to be deposited
* @param _referral the referral number of the action * @param referral the referral number of the action
* @param _timestamp the timestamp of the action
**/ **/
event Deposit( event Deposit(
address indexed _reserve, address indexed reserve,
address indexed _user, address indexed user,
uint256 _amount, uint256 amount,
uint16 indexed _referral, uint16 indexed referral
uint256 _timestamp
); );
/** /**
* @dev emitted during a withdraw action. * @dev emitted during a withdraw action.
* @param _reserve the address of the reserve * @param reserve the address of the reserve
* @param _user the address of the user * @param user the address of the user
* @param _amount the amount to be withdrawn * @param amount the amount to be withdrawn
* @param _timestamp the timestamp of the action
**/ **/
event Withdraw( event Withdraw(address indexed reserve, address indexed user, uint256 amount);
address indexed _reserve,
address indexed _user,
uint256 _amount,
uint256 _timestamp
);
/** /**
* @dev emitted on borrow * @dev emitted on borrow
* @param _reserve the address of the reserve * @param reserve the address of the reserve
* @param _user the address of the user * @param user the address of the user
* @param _amount the amount to be deposited * @param amount the amount to be deposited
* @param _borrowRateMode the rate mode, can be either 1-stable or 2-variable * @param borrowRateMode the rate mode, can be either 1-stable or 2-variable
* @param _borrowRate the rate at which the user has borrowed * @param borrowRate the rate at which the user has borrowed
* @param _referral the referral number of the action * @param referral the referral number of the action
* @param _timestamp the timestamp of the action
**/ **/
event Borrow( event Borrow(
address indexed _reserve, address indexed reserve,
address indexed _user, address indexed user,
uint256 _amount, uint256 amount,
uint256 _borrowRateMode, uint256 borrowRateMode,
uint256 _borrowRate, uint256 borrowRate,
uint16 indexed _referral, uint16 indexed referral
uint256 _timestamp
); );
/** /**
* @dev emitted on repay * @dev emitted on repay
* @param _reserve the address of the reserve * @param reserve the address of the reserve
* @param _user the address of the user for which the repay has been executed * @param user the address of the user for which the repay has been executed
* @param _repayer the address of the user that has performed the repay action * @param repayer the address of the user that has performed the repay action
* @param _amount the amount repaid * @param amount the amount repaid
* @param _timestamp the timestamp of the action
**/ **/
event Repay( event Repay(
address indexed _reserve, address indexed reserve,
address indexed _user, address indexed user,
address indexed _repayer, address indexed repayer,
uint256 _amount, uint256 amount
uint256 _timestamp
); );
/** /**
* @dev emitted when a user performs a rate swap * @dev emitted when a user performs a rate swap
* @param _reserve the address of the reserve * @param reserve the address of the reserve
* @param _user the address of the user executing the swap * @param user the address of the user executing the swap
* @param _timestamp the timestamp of the action
**/ **/
event Swap(address indexed _reserve, address indexed _user, uint256 _timestamp); event Swap(address indexed reserve, address indexed user, uint256 timestamp);
/** /**
* @dev emitted when a user enables a reserve as collateral * @dev emitted when a user enables a reserve as collateral
* @param _reserve the address of the reserve * @param reserve the address of the reserve
* @param _user the address of the user * @param user the address of the user
**/ **/
event ReserveUsedAsCollateralEnabled(address indexed _reserve, address indexed _user); event ReserveUsedAsCollateralEnabled(address indexed reserve, address indexed user);
/** /**
* @dev emitted when a user disables a reserve as collateral * @dev emitted when a user disables a reserve as collateral
* @param _reserve the address of the reserve * @param reserve the address of the reserve
* @param _user the address of the user * @param user the address of the user
**/ **/
event ReserveUsedAsCollateralDisabled(address indexed _reserve, address indexed _user); event ReserveUsedAsCollateralDisabled(address indexed reserve, address indexed user);
/** /**
* @dev emitted when the stable rate of a user gets rebalanced * @dev emitted when the stable rate of a user gets rebalanced
* @param _reserve the address of the reserve * @param reserve the address of the reserve
* @param _user the address of the user for which the rebalance has been executed * @param user the address of the user for which the rebalance has been executed
* @param _timestamp the timestamp of the action
**/ **/
event RebalanceStableBorrowRate( event RebalanceStableBorrowRate(address indexed reserve, address indexed user);
address indexed _reserve,
address indexed _user,
uint256 _timestamp
);
/** /**
* @dev emitted when a flashloan is executed * @dev emitted when a flashloan is executed
* @param _target the address of the flashLoanReceiver * @param target the address of the flashLoanReceiver
* @param _reserve the address of the reserve * @param reserve the address of the reserve
* @param _amount the amount requested * @param amount the amount requested
* @param _totalFee the total fee on the amount * @param totalFee the total fee on the amount
* @param _timestamp the timestamp of the action
**/ **/
event FlashLoan( event FlashLoan(
address indexed _target, address indexed target,
address indexed _reserve, address indexed reserve,
uint256 _amount, uint256 amount,
uint256 _totalFee, uint256 totalFee
uint256 _timestamp
); );
/** /**
* @dev these events are not emitted directly by the LendingPool * @dev these events are not emitted directly by the LendingPool
* but they are declared here as the LendingPoolLiquidationManager * but they are declared here as the LendingPoolLiquidationManager
@ -176,46 +152,40 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable, ILendingPool {
/** /**
* @dev emitted when a borrow fee is liquidated * @dev emitted when a borrow fee is liquidated
* @param _collateral the address of the collateral being liquidated * @param collateral the address of the collateral being liquidated
* @param _reserve the address of the reserve * @param reserve the address of the reserve
* @param _user the address of the user being liquidated * @param user the address of the user being liquidated
* @param _feeLiquidated the total fee liquidated * @param feeLiquidated the total fee liquidated
* @param _liquidatedCollateralForFee the amount of collateral received by the protocol in exchange for the fee * @param liquidatedCollateralForFee the amount of collateral received by the protocol in exchange for the fee
* @param _timestamp the timestamp of the action
**/ **/
event OriginationFeeLiquidated( event OriginationFeeLiquidated(
address indexed _collateral, address indexed collateral,
address indexed _reserve, address indexed reserve,
address indexed _user, address indexed user,
uint256 _feeLiquidated, uint256 feeLiquidated,
uint256 _liquidatedCollateralForFee, uint256 liquidatedCollateralForFee
uint256 _timestamp
); );
/** /**
* @dev emitted when a borrower is liquidated * @dev emitted when a borrower is liquidated
* @param _collateral the address of the collateral being liquidated * @param collateral the address of the collateral being liquidated
* @param _reserve the address of the reserve * @param reserve the address of the reserve
* @param _user the address of the user being liquidated * @param user the address of the user being liquidated
* @param _purchaseAmount the total amount liquidated * @param purchaseAmount the total amount liquidated
* @param _liquidatedCollateralAmount the amount of collateral being liquidated * @param liquidatedCollateralAmount the amount of collateral being liquidated
* @param _accruedBorrowInterest the amount of interest accrued by the borrower since the last action * @param accruedBorrowInterest the amount of interest accrued by the borrower since the last action
* @param _liquidator the address of the liquidator * @param liquidator the address of the liquidator
* @param _receiveAToken true if the liquidator wants to receive aTokens, false otherwise * @param receiveAToken true if the liquidator wants to receive aTokens, false otherwise
* @param _timestamp the timestamp of the action
**/ **/
event LiquidationCall( event LiquidationCall(
address indexed _collateral, address indexed collateral,
address indexed _reserve, address indexed reserve,
address indexed _user, address indexed user,
uint256 _purchaseAmount, uint256 purchaseAmount,
uint256 _liquidatedCollateralAmount, uint256 liquidatedCollateralAmount,
uint256 _accruedBorrowInterest, uint256 accruedBorrowInterest,
address _liquidator, address liquidator,
bool _receiveAToken, bool receiveAToken
uint256 _timestamp
); );
/** /**
* @dev only lending pools configurator can use functions affected by this modifier * @dev only lending pools configurator can use functions affected by this modifier
**/ **/
@ -235,123 +205,123 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable, ILendingPool {
/** /**
* @dev this function is invoked by the proxy contract when the LendingPool contract is added to the * @dev this function is invoked by the proxy contract when the LendingPool contract is added to the
* AddressesProvider. * AddressesProvider.
* @param _addressesProvider the address of the LendingPoolAddressesProvider registry * @param provider the address of the LendingPoolAddressesProvider registry
**/ **/
function initialize(LendingPoolAddressesProvider _addressesProvider) public initializer { function initialize(LendingPoolAddressesProvider provider) public initializer {
addressesProvider = _addressesProvider; addressesProvider = provider;
} }
/** /**
* @dev deposits The underlying asset into the reserve. A corresponding amount of the overlying asset (aTokens) * @dev deposits The underlying asset into the reserve. A corresponding amount of the overlying asset (aTokens)
* is minted. * is minted.
* @param _reserve the address of the reserve * @param asset the address of the reserve
* @param _amount the amount to be deposited * @param amount the amount to be deposited
* @param _referralCode integrators are assigned a referral code and can potentially receive rewards. * @param referralCode integrators are assigned a referral code and can potentially receive rewards.
**/ **/
function deposit( function deposit(
address _reserve, address asset,
uint256 _amount, uint256 amount,
uint16 _referralCode uint16 referralCode
) external override nonReentrant { ) external override nonReentrant {
ReserveLogic.ReserveData storage reserve = reserves[_reserve]; ReserveLogic.ReserveData storage reserve = _reserves[asset];
ValidationLogic.validateDeposit(reserve, _amount); ValidationLogic.validateDeposit(reserve, amount);
IAToken aToken = IAToken(reserve.aTokenAddress); IAToken aToken = IAToken(reserve.aTokenAddress);
bool isFirstDeposit = aToken.balanceOf(msg.sender) == 0; bool isFirstDeposit = aToken.balanceOf(msg.sender) == 0;
reserve.updateCumulativeIndexesAndTimestamp(); reserve.updateCumulativeIndexesAndTimestamp();
reserve.updateInterestRates(_reserve, _amount, 0); reserve.updateInterestRates(asset, amount, 0);
if (isFirstDeposit) { if (isFirstDeposit) {
usersConfig[msg.sender].setUsingAsCollateral(reserve.index, true); _usersConfig[msg.sender].setUsingAsCollateral(reserve.index, true);
} }
//minting AToken to user 1:1 with the specific exchange rate //minting AToken to user 1:1 with the specific exchange rate
aToken.mint(msg.sender, _amount); aToken.mint(msg.sender, amount);
//transfer to the aToken contract //transfer to the aToken contract
IERC20(_reserve).safeTransferFrom(msg.sender, address(aToken), _amount); IERC20(asset).safeTransferFrom(msg.sender, address(aToken), amount);
//solium-disable-next-line //solium-disable-next-line
emit Deposit(_reserve, msg.sender, _amount, _referralCode, block.timestamp); emit Deposit(asset, msg.sender, amount, referralCode);
} }
/** /**
* @dev withdraws the assets of _user. * @dev withdraws the _reserves of _user.
* @param _reserve the address of the reserve * @param asset the address of the reserve
* @param _amount the underlying amount to be redeemed * @param amount the underlying amount to be redeemed
**/ **/
function withdraw(address _reserve, uint256 _amount) external override nonReentrant { function withdraw(address asset, uint256 amount) external override nonReentrant {
ReserveLogic.ReserveData storage reserve = reserves[_reserve]; ReserveLogic.ReserveData storage reserve = _reserves[asset];
IAToken aToken = IAToken(reserve.aTokenAddress); IAToken aToken = IAToken(reserve.aTokenAddress);
uint256 userBalance = aToken.balanceOf(msg.sender); uint256 userBalance = aToken.balanceOf(msg.sender);
uint256 amountToWithdraw = _amount; uint256 amountToWithdraw = amount;
//if amount is equal to uint(-1), the user wants to redeem everything //if amount is equal to uint(-1), the user wants to redeem everything
if (_amount == UINT_MAX_VALUE) { if (amount == UINT_MAX_VALUE) {
amountToWithdraw = userBalance; amountToWithdraw = userBalance;
} }
ValidationLogic.validateWithdraw( ValidationLogic.validateWithdraw(
_reserve, asset,
address(aToken), address(aToken),
amountToWithdraw, amountToWithdraw,
userBalance, userBalance,
reserves, _reserves,
usersConfig[msg.sender], _usersConfig[msg.sender],
reservesList, reservesList,
addressesProvider.getPriceOracle() addressesProvider.getPriceOracle()
); );
reserve.updateCumulativeIndexesAndTimestamp(); reserve.updateCumulativeIndexesAndTimestamp();
reserve.updateInterestRates(_reserve, 0, amountToWithdraw); reserve.updateInterestRates(asset, 0, amountToWithdraw);
if (amountToWithdraw == userBalance) { if (amountToWithdraw == userBalance) {
usersConfig[msg.sender].setUsingAsCollateral(reserve.index, false); _usersConfig[msg.sender].setUsingAsCollateral(reserve.index, false);
} }
aToken.burn(msg.sender, msg.sender, amountToWithdraw); aToken.burn(msg.sender, msg.sender, amountToWithdraw);
//solium-disable-next-line //solium-disable-next-line
emit Withdraw(_reserve, msg.sender, _amount, block.timestamp); emit Withdraw(asset, msg.sender, amount);
} }
/** /**
* @dev Allows users to borrow a specific amount of the reserve currency, provided that the borrower * @dev Allows users to borrow a specific amount of the reserve currency, provided that the borrower
* already deposited enough collateral. * already deposited enough collateral.
* @param _reserve the address of the reserve * @param asset the address of the reserve
* @param _amount the amount to be borrowed * @param amount the amount to be borrowed
* @param _interestRateMode the interest rate mode at which the user wants to borrow. Can be 0 (STABLE) or 1 (VARIABLE) * @param interestRateMode the interest rate mode at which the user wants to borrow. Can be 0 (STABLE) or 1 (VARIABLE)
**/ **/
function borrow( function borrow(
address _reserve, address asset,
uint256 _amount, uint256 amount,
uint256 _interestRateMode, uint256 interestRateMode,
uint16 _referralCode uint16 referralCode
) external override nonReentrant { ) external override nonReentrant {
ReserveLogic.ReserveData storage reserve = reserves[_reserve]; ReserveLogic.ReserveData storage reserve = _reserves[asset];
UserConfiguration.Map storage userConfig = usersConfig[msg.sender]; UserConfiguration.Map storage userConfig = _usersConfig[msg.sender];
uint256 amountInETH = IPriceOracleGetter(addressesProvider.getPriceOracle()) uint256 amountInETH = IPriceOracleGetter(addressesProvider.getPriceOracle())
.getAssetPrice(_reserve) .getAssetPrice(asset)
.mul(_amount) .mul(amount)
.div(10**reserve.configuration.getDecimals()); //price is in ether .div(10**reserve.configuration.getDecimals()); //price is in ether
ValidationLogic.validateBorrow( ValidationLogic.validateBorrow(
reserve, reserve,
_reserve, asset,
_amount, amount,
amountInETH, amountInETH,
_interestRateMode, interestRateMode,
MAX_STABLE_RATE_BORROW_SIZE_PERCENT, MAX_STABLE_RATE_BORROW_SIZE_PERCENT,
reserves, _reserves,
usersConfig[msg.sender], _usersConfig[msg.sender],
reservesList, reservesList,
addressesProvider.getPriceOracle() addressesProvider.getPriceOracle()
); );
@ -361,34 +331,30 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable, ILendingPool {
reserve.updateCumulativeIndexesAndTimestamp(); reserve.updateCumulativeIndexesAndTimestamp();
if (ReserveLogic.InterestRateMode(_interestRateMode) == ReserveLogic.InterestRateMode.STABLE) { if (ReserveLogic.InterestRateMode(interestRateMode) == ReserveLogic.InterestRateMode.STABLE) {
IStableDebtToken(reserve.stableDebtTokenAddress).mint(msg.sender, _amount, userStableRate); IStableDebtToken(reserve.stableDebtTokenAddress).mint(msg.sender, amount, userStableRate);
uint40 stableRateLastUpdated = IStableDebtToken(reserve.stableDebtTokenAddress)
.getUserLastUpdated(msg.sender);
} else { } else {
IVariableDebtToken(reserve.variableDebtTokenAddress).mint(msg.sender, _amount); IVariableDebtToken(reserve.variableDebtTokenAddress).mint(msg.sender, amount);
} }
reserve.updateInterestRates(_reserve, 0, _amount); reserve.updateInterestRates(asset, 0, amount);
if (!userConfig.isBorrowing(reserve.index)) { if (!userConfig.isBorrowing(reserve.index)) {
userConfig.setBorrowing(reserve.index, true); userConfig.setBorrowing(reserve.index, true);
} }
//if we reached this point, we can transfer //if we reached this point, we can transfer
IAToken(reserve.aTokenAddress).transferUnderlyingTo(msg.sender, _amount); IAToken(reserve.aTokenAddress).transferUnderlyingTo(msg.sender, amount);
emit Borrow( emit Borrow(
_reserve, asset,
msg.sender, msg.sender,
_amount, amount,
_interestRateMode, interestRateMode,
ReserveLogic.InterestRateMode(_interestRateMode) == ReserveLogic.InterestRateMode.STABLE ReserveLogic.InterestRateMode(interestRateMode) == ReserveLogic.InterestRateMode.STABLE
? userStableRate ? userStableRate
: reserve.currentVariableBorrowRate, : reserve.currentVariableBorrowRate,
_referralCode, referralCode
//solium-disable-next-line
block.timestamp
); );
} }
@ -396,17 +362,17 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable, ILendingPool {
* @notice repays a borrow on the specific reserve, for the specified amount (or for the whole amount, if uint256(-1) is specified). * @notice repays a borrow on the specific reserve, for the specified amount (or for the whole amount, if uint256(-1) is specified).
* @dev the target user is defined by _onBehalfOf. If there is no repayment on behalf of another account, * @dev the target user is defined by _onBehalfOf. If there is no repayment on behalf of another account,
* _onBehalfOf must be equal to msg.sender. * _onBehalfOf must be equal to msg.sender.
* @param _reserve the address of the reserve on which the user borrowed * @param asset the address of the reserve on which the user borrowed
* @param _amount the amount to repay, or uint256(-1) if the user wants to repay everything * @param amount the amount to repay, or uint256(-1) if the user wants to repay everything
* @param _onBehalfOf the address for which msg.sender is repaying. * @param _onBehalfOf the address for which msg.sender is repaying.
**/ **/
function repay( function repay(
address _reserve, address asset,
uint256 _amount, uint256 amount,
uint256 _rateMode, uint256 _rateMode,
address _onBehalfOf address _onBehalfOf
) external override nonReentrant { ) external override nonReentrant {
ReserveLogic.ReserveData storage reserve = reserves[_reserve]; ReserveLogic.ReserveData storage reserve = _reserves[asset];
(uint256 stableDebt, uint256 variableDebt) = Helpers.getUserCurrentDebt(_onBehalfOf, reserve); (uint256 stableDebt, uint256 variableDebt) = Helpers.getUserCurrentDebt(_onBehalfOf, reserve);
@ -417,14 +383,14 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable, ILendingPool {
? stableDebt ? stableDebt
: variableDebt; : variableDebt;
if (_amount != UINT_MAX_VALUE && _amount < paybackAmount) { if (amount != UINT_MAX_VALUE && amount < paybackAmount) {
paybackAmount = _amount; paybackAmount = amount;
} }
ValidationLogic.validateRepay( ValidationLogic.validateRepay(
reserve, reserve,
_reserve, asset,
_amount, amount,
rateMode, rateMode,
_onBehalfOf, _onBehalfOf,
stableDebt, stableDebt,
@ -441,31 +407,29 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable, ILendingPool {
IVariableDebtToken(reserve.variableDebtTokenAddress).burn(_onBehalfOf, paybackAmount); IVariableDebtToken(reserve.variableDebtTokenAddress).burn(_onBehalfOf, paybackAmount);
} }
reserve.updateInterestRates(_reserve, paybackAmount, 0); reserve.updateInterestRates(asset, paybackAmount, 0);
if (stableDebt.add(variableDebt).sub(paybackAmount) == 0) { if (stableDebt.add(variableDebt).sub(paybackAmount) == 0) {
usersConfig[_onBehalfOf].setBorrowing(reserve.index, false); _usersConfig[_onBehalfOf].setBorrowing(reserve.index, false);
} }
IERC20(_reserve).safeTransferFrom(msg.sender, reserve.aTokenAddress, paybackAmount); IERC20(asset).safeTransferFrom(msg.sender, reserve.aTokenAddress, paybackAmount);
emit Repay( emit Repay(
_reserve, asset,
_onBehalfOf, _onBehalfOf,
msg.sender, msg.sender,
paybackAmount, paybackAmount
//solium-disable-next-line
block.timestamp
); );
} }
/** /**
* @dev borrowers can user this function to swap between stable and variable borrow rate modes. * @dev borrowers can user this function to swap between stable and variable borrow rate modes.
* @param _reserve the address of the reserve on which the user borrowed * @param asset the address of the reserve on which the user borrowed
* @param _rateMode the rate mode that the user wants to swap * @param _rateMode the rate mode that the user wants to swap
**/ **/
function swapBorrowRateMode(address _reserve, uint256 _rateMode) external override nonReentrant { function swapBorrowRateMode(address asset, uint256 _rateMode) external override nonReentrant {
ReserveLogic.ReserveData storage reserve = reserves[_reserve]; ReserveLogic.ReserveData storage reserve = _reserves[asset];
(uint256 stableDebt, uint256 variableDebt) = Helpers.getUserCurrentDebt(msg.sender, reserve); (uint256 stableDebt, uint256 variableDebt) = Helpers.getUserCurrentDebt(msg.sender, reserve);
@ -473,7 +437,7 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable, ILendingPool {
ValidationLogic.validateSwapRateMode( ValidationLogic.validateSwapRateMode(
reserve, reserve,
usersConfig[msg.sender], _usersConfig[msg.sender],
stableDebt, stableDebt,
variableDebt, variableDebt,
rateMode rateMode
@ -495,10 +459,10 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable, ILendingPool {
); );
} }
reserve.updateInterestRates(_reserve, 0, 0); reserve.updateInterestRates(asset, 0, 0);
emit Swap( emit Swap(
_reserve, asset,
msg.sender, msg.sender,
//solium-disable-next-line //solium-disable-next-line
block.timestamp block.timestamp
@ -509,21 +473,17 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable, ILendingPool {
* @dev rebalances the stable interest rate of a user if current liquidity rate > user stable rate. * @dev rebalances the stable interest rate of a user if current liquidity rate > user stable rate.
* this is regulated by Aave to ensure that the protocol is not abused, and the user is paying a fair * this is regulated by Aave to ensure that the protocol is not abused, and the user is paying a fair
* rate. Anyone can call this function. * rate. Anyone can call this function.
* @param _reserve the address of the reserve * @param asset the address of the reserve
* @param _user the address of the user to be rebalanced * @param _user the address of the user to be rebalanced
**/ **/
function rebalanceStableBorrowRate(address _reserve, address _user) function rebalanceStableBorrowRate(address asset, address _user) external override nonReentrant {
external ReserveLogic.ReserveData storage reserve = _reserves[asset];
override
nonReentrant
{
ReserveLogic.ReserveData storage reserve = reserves[_reserve];
IStableDebtToken stableDebtToken = IStableDebtToken(reserve.stableDebtTokenAddress); IStableDebtToken stableDebtToken = IStableDebtToken(reserve.stableDebtTokenAddress);
uint256 stableBorrowBalance = IERC20(address(stableDebtToken)).balanceOf(_user); uint256 stableBorrowBalance = IERC20(address(stableDebtToken)).balanceOf(_user);
// user must be borrowing on _reserve at a stable rate // user must be borrowing on asset at a stable rate
require(stableBorrowBalance > 0, 'User does not have any stable rate loan for this reserve'); require(stableBorrowBalance > 0, 'User does not have any stable rate loan for this reserve');
uint256 rebalanceDownRateThreshold = reserve.currentStableBorrowRate.rayMul( uint256 rebalanceDownRateThreshold = reserve.currentStableBorrowRate.rayMul(
@ -549,13 +509,11 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable, ILendingPool {
stableDebtToken.burn(_user, stableBorrowBalance); stableDebtToken.burn(_user, stableBorrowBalance);
stableDebtToken.mint(_user, stableBorrowBalance, reserve.currentStableBorrowRate); stableDebtToken.mint(_user, stableBorrowBalance, reserve.currentStableBorrowRate);
reserve.updateInterestRates(_reserve, 0, 0); reserve.updateInterestRates(asset, 0, 0);
emit RebalanceStableBorrowRate( emit RebalanceStableBorrowRate(
_reserve, asset,
_user, _user
//solium-disable-next-line
block.timestamp
); );
return; return;
@ -563,38 +521,38 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable, ILendingPool {
/** /**
* @dev allows depositors to enable or disable a specific deposit as collateral. * @dev allows depositors to enable or disable a specific deposit as collateral.
* @param _reserve the address of the reserve * @param asset the address of the reserve
* @param _useAsCollateral true if the user wants to user the deposit as collateral, false otherwise. * @param _useAsCollateral true if the user wants to user the deposit as collateral, false otherwise.
**/ **/
function setUserUseReserveAsCollateral(address _reserve, bool _useAsCollateral) function setUserUseReserveAsCollateral(address asset, bool _useAsCollateral)
external external
override override
nonReentrant nonReentrant
{ {
ReserveLogic.ReserveData storage reserve = reserves[_reserve]; ReserveLogic.ReserveData storage reserve = _reserves[asset];
ValidationLogic.validateSetUseReserveAsCollateral( ValidationLogic.validateSetUseReserveAsCollateral(
reserve, reserve,
_reserve, asset,
reserves, _reserves,
usersConfig[msg.sender], _usersConfig[msg.sender],
reservesList, reservesList,
addressesProvider.getPriceOracle() addressesProvider.getPriceOracle()
); );
usersConfig[msg.sender].setUsingAsCollateral(reserve.index, _useAsCollateral); _usersConfig[msg.sender].setUsingAsCollateral(reserve.index, _useAsCollateral);
if (_useAsCollateral) { if (_useAsCollateral) {
emit ReserveUsedAsCollateralEnabled(_reserve, msg.sender); emit ReserveUsedAsCollateralEnabled(asset, msg.sender);
} else { } else {
emit ReserveUsedAsCollateralDisabled(_reserve, msg.sender); emit ReserveUsedAsCollateralDisabled(asset, msg.sender);
} }
} }
/** /**
* @dev users can invoke this function to liquidate an undercollateralized position. * @dev users can invoke this function to liquidate an undercollateralized position.
* @param _reserve the address of the collateral to liquidated * @param asset the address of the collateral to liquidated
* @param _reserve the address of the principal reserve * @param asset the address of the principal reserve
* @param _user the address of the borrower * @param _user the address of the borrower
* @param _purchaseAmount the amount of principal that the liquidator wants to repay * @param _purchaseAmount the amount of principal that the liquidator wants to repay
* @param _receiveAToken true if the liquidators wants to receive the aTokens, false if * @param _receiveAToken true if the liquidators wants to receive the aTokens, false if
@ -602,7 +560,7 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable, ILendingPool {
**/ **/
function liquidationCall( function liquidationCall(
address _collateral, address _collateral,
address _reserve, address asset,
address _user, address _user,
uint256 _purchaseAmount, uint256 _purchaseAmount,
bool _receiveAToken bool _receiveAToken
@ -614,7 +572,7 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable, ILendingPool {
abi.encodeWithSignature( abi.encodeWithSignature(
'liquidationCall(address,address,address,uint256,bool)', 'liquidationCall(address,address,address,uint256,bool)',
_collateral, _collateral,
_reserve, asset,
_user, _user,
_purchaseAmount, _purchaseAmount,
_receiveAToken _receiveAToken
@ -634,60 +592,60 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable, ILendingPool {
* @dev allows smartcontracts to access the liquidity of the pool within one transaction, * @dev allows smartcontracts to access the liquidity of the pool within one transaction,
* as long as the amount taken plus a fee is returned. NOTE There are security concerns for developers of flashloan receiver contracts * as long as the amount taken plus a fee is returned. NOTE There are security concerns for developers of flashloan receiver contracts
* that must be kept into consideration. For further details please visit https://developers.aave.com * that must be kept into consideration. For further details please visit https://developers.aave.com
* @param _receiver The address of the contract receiving the funds. The receiver should implement the IFlashLoanReceiver interface. * @param receiverAddress The address of the contract receiving the funds. The receiver should implement the IFlashLoanReceiver interface.
* @param _reserve the address of the principal reserve * @param asset the address of the principal reserve
* @param _amount the amount requested for this flashloan * @param amount the amount requested for this flashloan
**/ **/
function flashLoan( function flashLoan(
address _receiver, address receiverAddress,
address _reserve, address asset,
uint256 _amount, uint256 amount,
bytes calldata _params bytes calldata params
) external override nonReentrant { ) external override nonReentrant {
ReserveLogic.ReserveData storage reserve = reserves[_reserve]; ReserveLogic.ReserveData storage reserve = _reserves[asset];
address aTokenAddress = reserve.aTokenAddress; address aTokenAddress = reserve.aTokenAddress;
//check that the reserve has enough available liquidity //check that the reserve has enough available liquidity
uint256 availableLiquidityBefore = IERC20(_reserve).balanceOf(aTokenAddress); uint256 availableLiquidityBefore = IERC20(asset).balanceOf(aTokenAddress);
//calculate amount fee //calculate amount fee
uint256 amountFee = _amount.mul(FLASHLOAN_FEE_TOTAL).div(10000); uint256 amountFee = amount.mul(FLASHLOAN_FEE_TOTAL).div(10000);
require( require(
availableLiquidityBefore >= _amount, availableLiquidityBefore >= amount,
'There is not enough liquidity available to borrow' 'There is not enough liquidity available to borrow'
); );
require(amountFee > 0, 'The requested amount is too small for a FlashLoan.'); require(amountFee > 0, 'The requested amount is too small for a FlashLoan.');
//get the FlashLoanReceiver instance //get the FlashLoanReceiver instance
IFlashLoanReceiver receiver = IFlashLoanReceiver(_receiver); IFlashLoanReceiver receiver = IFlashLoanReceiver(receiverAddress);
//transfer funds to the receiver //transfer funds to the receiver
IAToken(aTokenAddress).transferUnderlyingTo(_receiver, _amount); IAToken(aTokenAddress).transferUnderlyingTo(receiverAddress, amount);
//execute action of the receiver //execute action of the receiver
receiver.executeOperation(_reserve, aTokenAddress, _amount, amountFee, _params); receiver.executeOperation(asset, aTokenAddress, amount, amountFee, params);
//check that the actual balance of the core contract includes the returned amount //check that the actual balance of the core contract includes the returned amount
uint256 availableLiquidityAfter = IERC20(_reserve).balanceOf(aTokenAddress); uint256 availableLiquidityAfter = IERC20(asset).balanceOf(aTokenAddress);
require( require(
availableLiquidityAfter == availableLiquidityBefore.add(amountFee), availableLiquidityAfter == availableLiquidityBefore.add(amountFee),
'The actual balance of the protocol is inconsistent' 'The actual balance of the protocol is inconsistent'
); );
reserve.updateStateOnFlashLoan(_reserve, availableLiquidityBefore, amountFee); reserve.updateStateOnFlashLoan(asset, availableLiquidityBefore, amountFee);
//solium-disable-next-line //solium-disable-next-line
emit FlashLoan(_receiver, _reserve, _amount, amountFee, block.timestamp); emit FlashLoan(receiverAddress, asset, amount, amountFee);
} }
/** /**
* @dev accessory functions to fetch data from the core contract * @dev accessory functions to fetch data from the core contract
**/ **/
function getReserveConfigurationData(address _reserve) function getReserveConfigurationData(address asset)
external external
override override
view view
@ -704,7 +662,7 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable, ILendingPool {
bool isFreezed bool isFreezed
) )
{ {
ReserveLogic.ReserveData storage reserve = reserves[_reserve]; ReserveLogic.ReserveData storage reserve = _reserves[asset];
return ( return (
reserve.configuration.getDecimals(), reserve.configuration.getDecimals(),
@ -720,7 +678,7 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable, ILendingPool {
); );
} }
function getReserveTokensAddresses(address _reserve) function getReserveTokensAddresses(address asset)
external external
override override
view view
@ -730,7 +688,7 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable, ILendingPool {
address variableDebtTokenAddress address variableDebtTokenAddress
) )
{ {
ReserveLogic.ReserveData storage reserve = reserves[_reserve]; ReserveLogic.ReserveData storage reserve = _reserves[asset];
return ( return (
reserve.aTokenAddress, reserve.aTokenAddress,
@ -739,7 +697,7 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable, ILendingPool {
); );
} }
function getReserveData(address _reserve) function getReserveData(address asset)
external external
override override
view view
@ -756,9 +714,9 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable, ILendingPool {
uint40 lastUpdateTimestamp uint40 lastUpdateTimestamp
) )
{ {
ReserveLogic.ReserveData memory reserve = reserves[_reserve]; ReserveLogic.ReserveData memory reserve = _reserves[asset];
return ( return (
IERC20(_reserve).balanceOf(reserve.aTokenAddress), IERC20(asset).balanceOf(reserve.aTokenAddress),
IERC20(reserve.stableDebtTokenAddress).totalSupply(), IERC20(reserve.stableDebtTokenAddress).totalSupply(),
IERC20(reserve.variableDebtTokenAddress).totalSupply(), IERC20(reserve.variableDebtTokenAddress).totalSupply(),
reserve.currentLiquidityRate, reserve.currentLiquidityRate,
@ -792,8 +750,8 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable, ILendingPool {
healthFactor healthFactor
) = GenericLogic.calculateUserAccountData( ) = GenericLogic.calculateUserAccountData(
_user, _user,
reserves, _reserves,
usersConfig[_user], _usersConfig[_user],
reservesList, reservesList,
addressesProvider.getPriceOracle() addressesProvider.getPriceOracle()
); );
@ -805,7 +763,7 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable, ILendingPool {
); );
} }
function getUserReserveData(address _reserve, address _user) function getUserReserveData(address asset, address _user)
external external
override override
view view
@ -822,7 +780,7 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable, ILendingPool {
bool usageAsCollateralEnabled bool usageAsCollateralEnabled
) )
{ {
ReserveLogic.ReserveData storage reserve = reserves[_reserve]; ReserveLogic.ReserveData storage reserve = _reserves[asset];
currentATokenBalance = IERC20(reserve.aTokenAddress).balanceOf(_user); currentATokenBalance = IERC20(reserve.aTokenAddress).balanceOf(_user);
(currentStableDebt, currentVariableDebt) = Helpers.getUserCurrentDebt(_user, reserve); (currentStableDebt, currentVariableDebt) = Helpers.getUserCurrentDebt(_user, reserve);
@ -832,7 +790,7 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable, ILendingPool {
stableRateLastUpdated = IStableDebtToken(reserve.stableDebtTokenAddress).getUserLastUpdated( stableRateLastUpdated = IStableDebtToken(reserve.stableDebtTokenAddress).getUserLastUpdated(
_user _user
); );
usageAsCollateralEnabled = usersConfig[_user].isUsingAsCollateral(reserve.index); usageAsCollateralEnabled = _usersConfig[_user].isUsingAsCollateral(reserve.index);
variableBorrowIndex = IVariableDebtToken(reserve.variableDebtTokenAddress).getUserIndex(_user); variableBorrowIndex = IVariableDebtToken(reserve.variableDebtTokenAddress).getUserIndex(_user);
} }
@ -846,55 +804,55 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable, ILendingPool {
/** /**
* @dev initializes a reserve * @dev initializes a reserve
* @param _reserve the address of the reserve * @param asset the address of the reserve
* @param _aTokenAddress the address of the overlying aToken contract * @param _aTokenAddress the address of the overlying aToken contract
* @param _interestRateStrategyAddress the address of the interest rate strategy contract * @param _interestRateStrategyAddress the address of the interest rate strategy contract
**/ **/
function initReserve( function initReserve(
address _reserve, address asset,
address _aTokenAddress, address _aTokenAddress,
address _stableDebtAddress, address _stableDebtAddress,
address _variableDebtAddress, address _variableDebtAddress,
address _interestRateStrategyAddress address _interestRateStrategyAddress
) external override onlyLendingPoolConfigurator { ) external override onlyLendingPoolConfigurator {
reserves[_reserve].init( _reserves[asset].init(
_aTokenAddress, _aTokenAddress,
_stableDebtAddress, _stableDebtAddress,
_variableDebtAddress, _variableDebtAddress,
_interestRateStrategyAddress _interestRateStrategyAddress
); );
addReserveToListInternal(_reserve); addReserveToListInternal(asset);
} }
/** /**
* @dev updates the address of the interest rate strategy contract * @dev updates the address of the interest rate strategy contract
* @param _reserve the address of the reserve * @param asset the address of the reserve
* @param _rateStrategyAddress the address of the interest rate strategy contract * @param _rateStrategyAddress the address of the interest rate strategy contract
**/ **/
function setReserveInterestRateStrategyAddress(address _reserve, address _rateStrategyAddress) function setReserveInterestRateStrategyAddress(address asset, address _rateStrategyAddress)
external external
override override
onlyLendingPoolConfigurator onlyLendingPoolConfigurator
{ {
reserves[_reserve].interestRateStrategyAddress = _rateStrategyAddress; _reserves[asset].interestRateStrategyAddress = _rateStrategyAddress;
} }
function setConfiguration(address _reserve, uint256 _configuration) function setConfiguration(address asset, uint256 _configuration)
external external
override override
onlyLendingPoolConfigurator onlyLendingPoolConfigurator
{ {
reserves[_reserve].configuration.data = _configuration; _reserves[asset].configuration.data = _configuration;
} }
function getConfiguration(address _reserve) function getConfiguration(address asset)
external external
override override
view view
returns (ReserveConfiguration.Map memory) returns (ReserveConfiguration.Map memory)
{ {
return reserves[_reserve].configuration; return _reserves[asset].configuration;
} }
/** /**
@ -902,45 +860,45 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable, ILendingPool {
**/ **/
/** /**
* @dev adds a reserve to the array of the reserves address * @dev adds a reserve to the array of the _reserves address
**/ **/
function addReserveToListInternal(address _reserve) internal { function addReserveToListInternal(address asset) internal {
bool reserveAlreadyAdded = false; bool reserveAlreadyAdded = false;
for (uint256 i = 0; i < reservesList.length; i++) for (uint256 i = 0; i < reservesList.length; i++)
if (reservesList[i] == _reserve) { if (reservesList[i] == asset) {
reserveAlreadyAdded = true; reserveAlreadyAdded = true;
} }
if (!reserveAlreadyAdded) { if (!reserveAlreadyAdded) {
reserves[_reserve].index = uint8(reservesList.length); _reserves[asset].index = uint8(reservesList.length);
reservesList.push(_reserve); reservesList.push(asset);
} }
} }
function getReserveNormalizedIncome(address _reserve) external override view returns (uint256) { function getReserveNormalizedIncome(address asset) external override view returns (uint256) {
return reserves[_reserve].getNormalizedIncome(); return _reserves[asset].getNormalizedIncome();
} }
function getReserveNormalizedVariableDebt(address _reserve) function getReserveNormalizedVariableDebt(address asset)
external external
override override
view view
returns (uint256) returns (uint256)
{ {
return reserves[_reserve].getNormalizedDebt(); return _reserves[asset].getNormalizedDebt();
} }
function balanceDecreaseAllowed( function balanceDecreaseAllowed(
address _reserve, address asset,
address _user, address _user,
uint256 _amount uint256 amount
) external override view returns (bool) { ) external override view returns (bool) {
return return
GenericLogic.balanceDecreaseAllowed( GenericLogic.balanceDecreaseAllowed(
_reserve, asset,
_user, _user,
_amount, amount,
reserves, _reserves,
usersConfig[_user], _usersConfig[_user],
reservesList, reservesList,
addressesProvider.getPriceOracle() addressesProvider.getPriceOracle()
); );