diff --git a/contracts/interfaces/IReserveInterestRateStrategy.sol b/contracts/interfaces/IReserveInterestRateStrategy.sol index 5d41c100..48311e70 100644 --- a/contracts/interfaces/IReserveInterestRateStrategy.sol +++ b/contracts/interfaces/IReserveInterestRateStrategy.sol @@ -11,7 +11,7 @@ interface IReserveInterestRateStrategy { * @dev returns the base variable borrow rate, in rays */ - function getBaseVariableBorrowRate() external view returns (uint256); + function baseVariableBorrowRate() external view returns (uint256); /** * @dev calculates the liquidity, stable, and variable rates depending on the current utilization rate diff --git a/contracts/lendingpool/DefaultReserveInterestRateStrategy.sol b/contracts/lendingpool/DefaultReserveInterestRateStrategy.sol index 5059b7eb..c2303254 100644 --- a/contracts/lendingpool/DefaultReserveInterestRateStrategy.sol +++ b/contracts/lendingpool/DefaultReserveInterestRateStrategy.sol @@ -69,23 +69,23 @@ contract DefaultReserveInterestRateStrategy is IReserveInterestRateStrategy { * @dev accessors */ - function getVariableRateSlope1() external view returns (uint256) { + function variableRateSlope1() external view returns (uint256) { return _variableRateSlope1; } - function getVariableRateSlope2() external view returns (uint256) { + function variableRateSlope2() external view returns (uint256) { return _variableRateSlope2; } - function getStableRateSlope1() external view returns (uint256) { + function stableRateSlope1() external view returns (uint256) { return _stableRateSlope1; } - function getStableRateSlope2() external view returns (uint256) { + function stableRateSlope2() external view returns (uint256) { return _stableRateSlope2; } - function getBaseVariableBorrowRate() external override view returns (uint256) { + function baseVariableBorrowRate() external override view returns (uint256) { return _baseVariableBorrowRate; } @@ -121,7 +121,7 @@ contract DefaultReserveInterestRateStrategy is IReserveInterestRateStrategy { uint256 currentStableBorrowRate = 0; uint256 currentLiquidityRate = 0; - uint256 utilizationRate = (totalBorrows == 0 && availableLiquidity == 0) + uint256 utilizationRate = totalBorrows == 0 ? 0 : totalBorrows.rayDiv(availableLiquidity.add(totalBorrows)); @@ -157,9 +157,7 @@ contract DefaultReserveInterestRateStrategy is IReserveInterestRateStrategy { ) .rayMul(utilizationRate); - return (currentLiquidityRate, - currentStableBorrowRate, - currentVariableBorrowRate); + return (currentLiquidityRate, currentStableBorrowRate, currentVariableBorrowRate); } /** diff --git a/contracts/lendingpool/LendingPool.sol b/contracts/lendingpool/LendingPool.sol index 8551a26e..1cf33799 100644 --- a/contracts/lendingpool/LendingPool.sol +++ b/contracts/lendingpool/LendingPool.sol @@ -43,18 +43,18 @@ contract LendingPool is VersionedInitializable, ILendingPool { uint256 public constant MAX_STABLE_RATE_BORROW_SIZE_PERCENT = 25; uint256 public constant FLASHLOAN_PREMIUM_TOTAL = 9; - ILendingPoolAddressesProvider internal addressesProvider; + ILendingPoolAddressesProvider internal _addressesProvider; mapping(address => ReserveLogic.ReserveData) internal _reserves; mapping(address => UserConfiguration.Map) internal _usersConfig; - address[] internal reservesList; + address[] internal _reservesList; /** * @dev only lending pools configurator can use functions affected by this modifier **/ modifier onlyLendingPoolConfigurator { - require(addressesProvider.getLendingPoolConfigurator() == msg.sender, '30'); + require(_addressesProvider.getLendingPoolConfigurator() == msg.sender, '30'); _; } @@ -72,7 +72,7 @@ contract LendingPool is VersionedInitializable, ILendingPool { * @param provider the address of the LendingPoolAddressesProvider registry **/ function initialize(ILendingPoolAddressesProvider provider) public initializer { - addressesProvider = provider; + _addressesProvider = provider; } /** @@ -91,37 +91,36 @@ contract LendingPool is VersionedInitializable, ILendingPool { ValidationLogic.validateDeposit(reserve, amount); - IAToken aToken = IAToken(reserve.aTokenAddress); - - bool isFirstDeposit = aToken.balanceOf(msg.sender) == 0; + address aToken = reserve.aTokenAddress; reserve.updateCumulativeIndexesAndTimestamp(); - reserve.updateInterestRates(asset, amount, 0); + reserve.updateInterestRates(asset, aToken, amount, 0); + bool isFirstDeposit = IAToken(aToken).balanceOf(msg.sender) == 0; if (isFirstDeposit) { _usersConfig[msg.sender].setUsingAsCollateral(reserve.index, true); } //minting AToken to user 1:1 with the specific exchange rate - aToken.mint(msg.sender, amount); + IAToken(aToken).mint(msg.sender, amount); //transfer to the aToken contract - IERC20(asset).safeTransferFrom(msg.sender, address(aToken), amount); + IERC20(asset).safeTransferFrom(msg.sender, aToken, amount); emit Deposit(asset, msg.sender, amount, referralCode); } /** - * @dev withdraws the _reserves of _user. + * @dev withdraws the _reserves of user. * @param asset the address of the reserve * @param amount the underlying amount to be redeemed **/ function withdraw(address asset, uint256 amount) external override { ReserveLogic.ReserveData storage reserve = _reserves[asset]; - IAToken aToken = IAToken(reserve.aTokenAddress); + address aToken = reserve.aTokenAddress; - uint256 userBalance = aToken.balanceOf(msg.sender); + uint256 userBalance = IAToken(aToken).balanceOf(msg.sender); uint256 amountToWithdraw = amount; @@ -132,24 +131,24 @@ contract LendingPool is VersionedInitializable, ILendingPool { ValidationLogic.validateWithdraw( asset, - address(aToken), + aToken, amountToWithdraw, userBalance, _reserves, _usersConfig[msg.sender], - reservesList, - addressesProvider.getPriceOracle() + _reservesList, + _addressesProvider.getPriceOracle() ); reserve.updateCumulativeIndexesAndTimestamp(); - reserve.updateInterestRates(asset, 0, amountToWithdraw); + reserve.updateInterestRates(asset, aToken, 0, amountToWithdraw); if (amountToWithdraw == userBalance) { _usersConfig[msg.sender].setUsingAsCollateral(reserve.index, false); } - aToken.burn(msg.sender, msg.sender, amountToWithdraw); + IAToken(aToken).burn(msg.sender, msg.sender, amountToWithdraw); emit Withdraw(asset, msg.sender, amount); } @@ -220,15 +219,17 @@ contract LendingPool is VersionedInitializable, ILendingPool { IVariableDebtToken(reserve.variableDebtTokenAddress).mint(vars.user, vars.amount); } - reserve.updateInterestRates(vars.asset, 0, (vars.releaseUnderlying) ? vars.amount : 0); + address aToken = reserve.aTokenAddress; + reserve.updateInterestRates(asset, aToken, 0, amount); - if (!userConfig.isBorrowing(reserve.index)) { - userConfig.setBorrowing(reserve.index, true); + uint256 reserveIndex = reserve.index; + if (!userConfig.isBorrowing(reserveIndex)) { + userConfig.setBorrowing(reserveIndex, true); } //if we reached this point and we need to, we can transfer if (vars.releaseUnderlying) { - IAToken(reserve.aTokenAddress).transferUnderlyingTo(vars.user, vars.amount); + IAToken(aToken).transferUnderlyingTo(vars.user, vars.amount); } emit Borrow( @@ -245,26 +246,26 @@ contract LendingPool is VersionedInitializable, ILendingPool { /** * @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, - * _onBehalfOf must be equal to msg.sender. + * @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. * @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 _onBehalfOf the address for which msg.sender is repaying. + * @param onBehalfOf the address for which msg.sender is repaying. **/ function repay( address asset, uint256 amount, - uint256 _rateMode, - address _onBehalfOf + uint256 rateMode, + address onBehalfOf ) external override { ReserveLogic.ReserveData storage reserve = _reserves[asset]; - (uint256 stableDebt, uint256 variableDebt) = Helpers.getUserCurrentDebt(_onBehalfOf, reserve); + (uint256 stableDebt, uint256 variableDebt) = Helpers.getUserCurrentDebt(onBehalfOf, reserve); - ReserveLogic.InterestRateMode rateMode = ReserveLogic.InterestRateMode(_rateMode); + ReserveLogic.InterestRateMode interestRateMode = ReserveLogic.InterestRateMode(rateMode); //default to max amount - uint256 paybackAmount = rateMode == ReserveLogic.InterestRateMode.STABLE + uint256 paybackAmount = interestRateMode == ReserveLogic.InterestRateMode.STABLE ? stableDebt : variableDebt; @@ -272,51 +273,59 @@ contract LendingPool is VersionedInitializable, ILendingPool { paybackAmount = amount; } - ValidationLogic.validateRepay(reserve, amount, rateMode, _onBehalfOf, stableDebt, variableDebt); + ValidationLogic.validateRepay( + reserve, + amount, + interestRateMode, + onBehalfOf, + stableDebt, + variableDebt + ); reserve.updateCumulativeIndexesAndTimestamp(); //burns an equivalent amount of debt tokens - if (rateMode == ReserveLogic.InterestRateMode.STABLE) { - IStableDebtToken(reserve.stableDebtTokenAddress).burn(_onBehalfOf, paybackAmount); + if (interestRateMode == ReserveLogic.InterestRateMode.STABLE) { + IStableDebtToken(reserve.stableDebtTokenAddress).burn(onBehalfOf, paybackAmount); } else { - IVariableDebtToken(reserve.variableDebtTokenAddress).burn(_onBehalfOf, paybackAmount); + IVariableDebtToken(reserve.variableDebtTokenAddress).burn(onBehalfOf, paybackAmount); } - reserve.updateInterestRates(asset, paybackAmount, 0); + address aToken = reserve.aTokenAddress; + reserve.updateInterestRates(asset, aToken, paybackAmount, 0); if (stableDebt.add(variableDebt).sub(paybackAmount) == 0) { - _usersConfig[_onBehalfOf].setBorrowing(reserve.index, false); + _usersConfig[onBehalfOf].setBorrowing(reserve.index, false); } - IERC20(asset).safeTransferFrom(msg.sender, reserve.aTokenAddress, paybackAmount); + IERC20(asset).safeTransferFrom(msg.sender, aToken, paybackAmount); - emit Repay(asset, _onBehalfOf, msg.sender, paybackAmount); + emit Repay(asset, onBehalfOf, msg.sender, paybackAmount); } /** * @dev borrowers can user this function to swap between stable and variable borrow rate modes. * @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 asset, uint256 _rateMode) external override { + function swapBorrowRateMode(address asset, uint256 rateMode) external override nonReentrant { ReserveLogic.ReserveData storage reserve = _reserves[asset]; (uint256 stableDebt, uint256 variableDebt) = Helpers.getUserCurrentDebt(msg.sender, reserve); - ReserveLogic.InterestRateMode rateMode = ReserveLogic.InterestRateMode(_rateMode); + ReserveLogic.InterestRateMode interestRateMode = ReserveLogic.InterestRateMode(rateMode); ValidationLogic.validateSwapRateMode( reserve, _usersConfig[msg.sender], stableDebt, variableDebt, - rateMode + interestRateMode ); reserve.updateCumulativeIndexesAndTimestamp(); - if (rateMode == ReserveLogic.InterestRateMode.STABLE) { + if (interestRateMode == ReserveLogic.InterestRateMode.STABLE) { //burn stable rate tokens, mint variable rate tokens IStableDebtToken(reserve.stableDebtTokenAddress).burn(msg.sender, stableDebt); IVariableDebtToken(reserve.variableDebtTokenAddress).mint(msg.sender, stableDebt); @@ -330,7 +339,7 @@ contract LendingPool is VersionedInitializable, ILendingPool { ); } - reserve.updateInterestRates(asset, 0, 0); + reserve.updateInterestRates(asset, reserve.aTokenAddress, 0, 0); emit Swap(asset, msg.sender); } @@ -340,14 +349,14 @@ contract LendingPool is VersionedInitializable, ILendingPool { * 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. * @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 asset, address _user) external override { + function rebalanceStableBorrowRate(address asset, address user) external override { ReserveLogic.ReserveData storage reserve = _reserves[asset]; IStableDebtToken stableDebtToken = IStableDebtToken(reserve.stableDebtTokenAddress); - uint256 stableBorrowBalance = IERC20(address(stableDebtToken)).balanceOf(_user); + uint256 stableBorrowBalance = IERC20(address(stableDebtToken)).balanceOf(user); // user must be borrowing on asset at a stable rate require(stableBorrowBalance > 0, 'User does not have any stable rate loan for this reserve'); @@ -361,7 +370,7 @@ contract LendingPool is VersionedInitializable, ILendingPool { //2. user stable rate is above the market avg borrow rate of a certain delta, and utilization rate is low. //In this case, the user is paying an interest that is too high, and needs to be rescaled down. - uint256 userStableRate = stableDebtToken.getUserStableRate(_user); + uint256 userStableRate = stableDebtToken.getUserStableRate(user); require( userStableRate < reserve.currentLiquidityRate || userStableRate > rebalanceDownRateThreshold, @@ -372,12 +381,12 @@ contract LendingPool is VersionedInitializable, ILendingPool { reserve.updateCumulativeIndexesAndTimestamp(); - stableDebtToken.burn(_user, stableBorrowBalance); - stableDebtToken.mint(_user, stableBorrowBalance, reserve.currentStableBorrowRate); + stableDebtToken.burn(user, stableBorrowBalance); + stableDebtToken.mint(user, stableBorrowBalance, reserve.currentStableBorrowRate); - reserve.updateInterestRates(asset, 0, 0); + reserve.updateInterestRates(asset, reserve.aTokenAddress, 0, 0); - emit RebalanceStableBorrowRate(asset, _user); + emit RebalanceStableBorrowRate(asset, user); return; } @@ -385,9 +394,12 @@ contract LendingPool is VersionedInitializable, ILendingPool { /** * @dev allows depositors to enable or disable a specific deposit as collateral. * @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 asset, bool _useAsCollateral) external override { + function setUserUseReserveAsCollateral(address asset, bool useAsCollateral) + external + override + { ReserveLogic.ReserveData storage reserve = _reserves[asset]; ValidationLogic.validateSetUseReserveAsCollateral( @@ -395,13 +407,13 @@ contract LendingPool is VersionedInitializable, ILendingPool { asset, _reserves, _usersConfig[msg.sender], - reservesList, - addressesProvider.getPriceOracle() + _reservesList, + _addressesProvider.getPriceOracle() ); - _usersConfig[msg.sender].setUsingAsCollateral(reserve.index, _useAsCollateral); + _usersConfig[msg.sender].setUsingAsCollateral(reserve.index, useAsCollateral); - if (_useAsCollateral) { + if (useAsCollateral) { emit ReserveUsedAsCollateralEnabled(asset, msg.sender); } else { emit ReserveUsedAsCollateralDisabled(asset, msg.sender); @@ -412,29 +424,29 @@ contract LendingPool is VersionedInitializable, ILendingPool { * @dev users can invoke this function to liquidate an undercollateralized position. * @param asset the address of the collateral to liquidated * @param asset the address of the principal reserve - * @param _user the address of the borrower - * @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 user the address of the borrower + * @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 * he wants to receive the underlying asset directly **/ function liquidationCall( - address _collateral, + address collateral, address asset, - address _user, - uint256 _purchaseAmount, - bool _receiveAToken + address user, + uint256 purchaseAmount, + bool receiveAToken ) external override { - address liquidationManager = addressesProvider.getLendingPoolLiquidationManager(); + address liquidationManager = _addressesProvider.getLendingPoolLiquidationManager(); //solium-disable-next-line (bool success, bytes memory result) = liquidationManager.delegatecall( abi.encodeWithSignature( 'liquidationCall(address,address,address,uint256,bool)', - _collateral, + collateral, asset, - _user, - _purchaseAmount, - _receiveAToken + user, + purchaseAmount, + receiveAToken ) ); require(success, 'Liquidation call failed'); @@ -644,7 +656,7 @@ contract LendingPool is VersionedInitializable, ILendingPool { ); } - function getUserAccountData(address _user) + function getUserAccountData(address user) external override view @@ -664,11 +676,11 @@ contract LendingPool is VersionedInitializable, ILendingPool { currentLiquidationThreshold, healthFactor ) = GenericLogic.calculateUserAccountData( - _user, + user, _reserves, - _usersConfig[_user], - reservesList, - addressesProvider.getPriceOracle() + _usersConfig[user], + _reservesList, + _addressesProvider.getPriceOracle() ); availableBorrowsETH = GenericLogic.calculateAvailableBorrowsETH( @@ -678,7 +690,7 @@ contract LendingPool is VersionedInitializable, ILendingPool { ); } - function getUserReserveData(address asset, address _user) + function getUserReserveData(address asset, address user) external override view @@ -697,20 +709,20 @@ contract LendingPool is VersionedInitializable, ILendingPool { { ReserveLogic.ReserveData storage reserve = _reserves[asset]; - currentATokenBalance = IERC20(reserve.aTokenAddress).balanceOf(_user); - (currentStableDebt, currentVariableDebt) = Helpers.getUserCurrentDebt(_user, reserve); - (principalStableDebt, principalVariableDebt) = Helpers.getUserPrincipalDebt(_user, reserve); + currentATokenBalance = IERC20(reserve.aTokenAddress).balanceOf(user); + (currentStableDebt, currentVariableDebt) = Helpers.getUserCurrentDebt(user, reserve); + (principalStableDebt, principalVariableDebt) = Helpers.getUserPrincipalDebt(user, reserve); liquidityRate = reserve.currentLiquidityRate; - stableBorrowRate = IStableDebtToken(reserve.stableDebtTokenAddress).getUserStableRate(_user); + stableBorrowRate = IStableDebtToken(reserve.stableDebtTokenAddress).getUserStableRate(user); stableRateLastUpdated = IStableDebtToken(reserve.stableDebtTokenAddress).getUserLastUpdated( - _user + user ); - usageAsCollateralEnabled = _usersConfig[_user].isUsingAsCollateral(reserve.index); - variableBorrowIndex = IVariableDebtToken(reserve.variableDebtTokenAddress).getUserIndex(_user); + usageAsCollateralEnabled = _usersConfig[user].isUsingAsCollateral(reserve.index); + variableBorrowIndex = IVariableDebtToken(reserve.variableDebtTokenAddress).getUserIndex(user); } function getReserves() external override view returns (address[] memory) { - return reservesList; + return _reservesList; } receive() external payable { @@ -720,21 +732,21 @@ contract LendingPool is VersionedInitializable, ILendingPool { /** * @dev initializes a reserve * @param asset the address of the reserve - * @param _aTokenAddress the address of the overlying aToken contract - * @param _interestRateStrategyAddress the address of the interest rate strategy contract + * @param aTokenAddress the address of the overlying aToken contract + * @param interestRateStrategyAddress the address of the interest rate strategy contract **/ function initReserve( address asset, - address _aTokenAddress, - address _stableDebtAddress, - address _variableDebtAddress, - address _interestRateStrategyAddress + address aTokenAddress, + address stableDebtAddress, + address variableDebtAddress, + address interestRateStrategyAddress ) external override onlyLendingPoolConfigurator { _reserves[asset].init( - _aTokenAddress, - _stableDebtAddress, - _variableDebtAddress, - _interestRateStrategyAddress + aTokenAddress, + stableDebtAddress, + variableDebtAddress, + interestRateStrategyAddress ); _addReserveToList(asset); } @@ -779,13 +791,13 @@ contract LendingPool is VersionedInitializable, ILendingPool { **/ function _addReserveToList(address asset) internal { bool reserveAlreadyAdded = false; - for (uint256 i = 0; i < reservesList.length; i++) - if (reservesList[i] == asset) { + for (uint256 i = 0; i < _reservesList.length; i++) + if (_reservesList[i] == asset) { reserveAlreadyAdded = true; } if (!reserveAlreadyAdded) { - _reserves[asset].index = uint8(reservesList.length); - reservesList.push(asset); + _reserves[asset].index = uint8(_reservesList.length); + _reservesList.push(asset); } } @@ -831,8 +843,8 @@ contract LendingPool is VersionedInitializable, ILendingPool { amount, _reserves, _usersConfig[user], - reservesList, - addressesProvider.getPriceOracle() + _reservesList, + _addressesProvider.getPriceOracle() ); } @@ -840,13 +852,13 @@ contract LendingPool is VersionedInitializable, ILendingPool { * @dev returns the list of the initialized reserves **/ function getReservesList() external view returns (address[] memory) { - return reservesList; + return _reservesList; } /** * @dev returns the addresses provider **/ function getAddressesProvider() external view returns (ILendingPoolAddressesProvider) { - return addressesProvider; + return _addressesProvider; } } diff --git a/contracts/lendingpool/LendingPoolConfigurator.sol b/contracts/lendingpool/LendingPoolConfigurator.sol index 9560b88e..5a2d732b 100644 --- a/contracts/lendingpool/LendingPoolConfigurator.sol +++ b/contracts/lendingpool/LendingPoolConfigurator.sol @@ -164,10 +164,10 @@ contract LendingPoolConfigurator is VersionedInitializable { /** * @dev emitted when the implementation of a variable debt token is upgraded * @param asset the address of the reserve - * @param _proxy the variable debt token proxy address - * @param _implementation the new aToken implementation + * @param proxy the variable debt token proxy address + * @param implementation the new aToken implementation **/ - event VariableDebtTokenUpgraded(address asset, address _proxy, address _implementation); + event VariableDebtTokenUpgraded(address asset, address proxy, address implementation); ILendingPoolAddressesProvider internal addressesProvider; ILendingPool internal pool; @@ -211,10 +211,7 @@ contract LendingPoolConfigurator is VersionedInitializable { uint8 underlyingAssetDecimals, address interestRateStrategyAddress ) public onlyLendingPoolManager { - address aTokenProxyAddress = _initTokenWithProxy( - aTokenImpl, - underlyingAssetDecimals - ); + address aTokenProxyAddress = _initTokenWithProxy(aTokenImpl, underlyingAssetDecimals); address stableDebtTokenProxyAddress = _initTokenWithProxy( stableDebtTokenImpl, @@ -280,6 +277,7 @@ contract LendingPoolConfigurator is VersionedInitializable { emit StableDebtTokenUpgraded(asset, stableDebtToken, implementation); } + /** * @dev updates the variable debt token implementation for the asset * @param asset the address of the reserve to be updated @@ -349,12 +347,7 @@ contract LendingPoolConfigurator is VersionedInitializable { pool.setConfiguration(asset, currentConfig.data); - emit ReserveEnabledAsCollateral( - asset, - ltv, - liquidationThreshold, - liquidationBonus - ); + emit ReserveEnabledAsCollateral(asset, ltv, liquidationThreshold, liquidationBonus); } /** @@ -553,10 +546,7 @@ contract LendingPoolConfigurator is VersionedInitializable { * @param implementation the address of the implementation * @param decimals the decimals of the token **/ - function _initTokenWithProxy( - address implementation, - uint8 decimals - ) internal returns (address) { + function _initTokenWithProxy(address implementation, uint8 decimals) internal returns (address) { InitializableAdminUpgradeabilityProxy proxy = new InitializableAdminUpgradeabilityProxy(); bytes memory params = abi.encodeWithSignature( diff --git a/contracts/lendingpool/LendingPoolLiquidationManager.sol b/contracts/lendingpool/LendingPoolLiquidationManager.sol index 21084154..0459f646 100644 --- a/contracts/lendingpool/LendingPoolLiquidationManager.sol +++ b/contracts/lendingpool/LendingPoolLiquidationManager.sol @@ -134,7 +134,9 @@ contract LendingPoolLiquidationManager is VersionedInitializable { ); } - vars.userCollateralBalance = IERC20(collateralReserve.aTokenAddress).balanceOf(user); + vars.collateralAtoken = IAToken(collateralReserve.aTokenAddress); + + vars.userCollateralBalance = vars.collateralAtoken.balanceOf(user); vars.isCollateralEnabled = collateralReserve.configuration.getLiquidationThreshold() > 0 && @@ -190,8 +192,6 @@ contract LendingPoolLiquidationManager is VersionedInitializable { vars.actualAmountToLiquidate = vars.principalAmountNeeded; } - vars.collateralAtoken = IAToken(collateralReserve.aTokenAddress); - //if liquidator reclaims the underlying asset, we make sure there is enough available collateral in the reserve if (!receiveAToken) { uint256 currentAvailableCollateral = IERC20(collateral).balanceOf( @@ -207,7 +207,12 @@ contract LendingPoolLiquidationManager is VersionedInitializable { //update the principal reserve principalReserve.updateCumulativeIndexesAndTimestamp(); - principalReserve.updateInterestRates(principal, vars.actualAmountToLiquidate, 0); + principalReserve.updateInterestRates( + principal, + principalReserve.aTokenAddress, + vars.actualAmountToLiquidate, + 0 + ); if (vars.userVariableDebt >= vars.actualAmountToLiquidate) { IVariableDebtToken(principalReserve.variableDebtTokenAddress).burn( @@ -233,7 +238,12 @@ contract LendingPoolLiquidationManager is VersionedInitializable { //updating collateral reserve collateralReserve.updateCumulativeIndexesAndTimestamp(); - collateralReserve.updateInterestRates(collateral, 0, vars.maxCollateralToLiquidate); + collateralReserve.updateInterestRates( + collateral, + address(vars.collateralAtoken), + 0, + vars.maxCollateralToLiquidate + ); //burn the equivalent amount of atoken vars.collateralAtoken.burn(user, msg.sender, vars.maxCollateralToLiquidate); @@ -281,8 +291,8 @@ contract LendingPoolLiquidationManager is VersionedInitializable { * @return principalAmountNeeded the purchase amount **/ function calculateAvailableCollateralToLiquidate( - ReserveLogic.ReserveData storage _collateralReserve, - ReserveLogic.ReserveData storage _principalReserve, + ReserveLogic.ReserveData storage collateralReserve, + ReserveLogic.ReserveData storage principalReserve, address collateralAddress, address principalAddress, uint256 purchaseAmount, @@ -298,10 +308,10 @@ contract LendingPoolLiquidationManager is VersionedInitializable { vars.collateralPrice = oracle.getAssetPrice(collateralAddress); vars.principalCurrencyPrice = oracle.getAssetPrice(principalAddress); - (, , vars.liquidationBonus, vars.collateralDecimals) = _collateralReserve + (, , vars.liquidationBonus, vars.collateralDecimals) = collateralReserve .configuration .getParams(); - vars.principalDecimals = _principalReserve.configuration.getDecimals(); + vars.principalDecimals = principalReserve.configuration.getDecimals(); //this is the maximum possible amount of the selected collateral that can be liquidated, given the //max amount of principal currency that is available for liquidation. diff --git a/contracts/libraries/logic/ReserveLogic.sol b/contracts/libraries/logic/ReserveLogic.sol index 6aab6932..893ca5c5 100644 --- a/contracts/libraries/logic/ReserveLogic.sol +++ b/contracts/libraries/logic/ReserveLogic.sol @@ -126,18 +126,18 @@ library ReserveLogic { IERC20(reserve.variableDebtTokenAddress).totalSupply() > 0 || IERC20(reserve.stableDebtTokenAddress).totalSupply() > 0 ) { + uint40 lastUpdateTimestamp = reserve.lastUpdateTimestamp; + uint256 cumulatedLiquidityInterest = MathUtils.calculateLinearInterest( reserve.currentLiquidityRate, - reserve.lastUpdateTimestamp + lastUpdateTimestamp ); - reserve.lastLiquidityIndex = cumulatedLiquidityInterest.rayMul( - reserve.lastLiquidityIndex - ); + reserve.lastLiquidityIndex = cumulatedLiquidityInterest.rayMul(reserve.lastLiquidityIndex); uint256 cumulatedVariableBorrowInterest = MathUtils.calculateCompoundedInterest( reserve.currentVariableBorrowRate, - reserve.lastUpdateTimestamp + lastUpdateTimestamp ); reserve.lastVariableBorrowIndex = cumulatedVariableBorrowInterest.rayMul( reserve.lastVariableBorrowIndex @@ -164,9 +164,7 @@ library ReserveLogic { uint256 cumulatedLiquidity = amountToLiquidityRatio.add(WadRayMath.ray()); - reserve.lastLiquidityIndex = cumulatedLiquidity.rayMul( - reserve.lastLiquidityIndex - ); + reserve.lastLiquidityIndex = cumulatedLiquidity.rayMul(reserve.lastLiquidityIndex); } /** @@ -208,21 +206,20 @@ library ReserveLogic { function updateInterestRates( ReserveData storage reserve, address reserveAddress, + address aTokenAddress, uint256 liquidityAdded, uint256 liquidityTaken ) internal { uint256 currentAvgStableRate = IStableDebtToken(reserve.stableDebtTokenAddress) .getAverageStableRate(); - uint256 balance = IERC20(reserveAddress).balanceOf(reserve.aTokenAddress); - ( uint256 newLiquidityRate, uint256 newStableRate, uint256 newVariableRate ) = IReserveInterestRateStrategy(reserve.interestRateStrategyAddress).calculateInterestRates( reserveAddress, - balance.add(liquidityAdded).sub(liquidityTaken), + IERC20(reserveAddress).balanceOf(aTokenAddress).add(liquidityAdded).sub(liquidityTaken), IERC20(reserve.stableDebtTokenAddress).totalSupply(), IERC20(reserve.variableDebtTokenAddress).totalSupply(), currentAvgStableRate diff --git a/test/helpers/utils/calculations.ts b/test/helpers/utils/calculations.ts index 257573be..4d1c55e4 100644 --- a/test/helpers/utils/calculations.ts +++ b/test/helpers/utils/calculations.ts @@ -7,15 +7,14 @@ import { EXCESS_UTILIZATION_RATE, ZERO_ADDRESS, } from '../../../helpers/constants'; -import {IReserveParams, iAavePoolAssets, RateMode} from '../../../helpers/types'; +import { IReserveParams, iAavePoolAssets, RateMode } from '../../../helpers/types'; import './math'; -import {ReserveData, UserReserveData} from './interfaces'; +import { ReserveData, UserReserveData } from './interfaces'; export const strToBN = (amount: string): BigNumber => new BigNumber(amount); interface Configuration { reservesParams: iAavePoolAssets; - ethereumAddress: string; } export const configuration: Configuration = {}; @@ -66,17 +65,7 @@ export const calcExpectedUserDataAfterDeposit = ( } expectedUserData.variableBorrowIndex = userDataBeforeAction.variableBorrowIndex; - - if (reserveDataBeforeAction.address === configuration.ethereumAddress) { - // console.log("** ETH CASE ****") - expectedUserData.walletBalance = userDataBeforeAction.walletBalance - .minus(txCost) - .minus(amountDeposited); - } else { - // console.log("** TOKEN CASE ****") - // console.log(userDataBeforeAction.walletBalance.toString()) - expectedUserData.walletBalance = userDataBeforeAction.walletBalance.minus(amountDeposited); - } + expectedUserData.walletBalance = userDataBeforeAction.walletBalance.minus(amountDeposited); expectedUserData.principalATokenBalance = expectedUserData.currentATokenBalance = calcExpectedATokenBalance( reserveDataBeforeAction, @@ -171,14 +160,7 @@ export const calcExpectedUserDataAfterWithdraw = ( } expectedUserData.variableBorrowIndex = userDataBeforeAction.variableBorrowIndex; - - if (reserveDataBeforeAction.address === configuration.ethereumAddress) { - expectedUserData.walletBalance = userDataBeforeAction.walletBalance - .minus(txCost) - .plus(amountWithdrawn); - } else { - expectedUserData.walletBalance = userDataBeforeAction.walletBalance.plus(amountWithdrawn); - } + expectedUserData.walletBalance = userDataBeforeAction.walletBalance.plus(amountWithdrawn); expectedUserData.redirectedBalance = userDataBeforeAction.redirectedBalance; @@ -600,13 +582,7 @@ export const calcExpectedUserDataAfterBorrow = ( userDataBeforeAction.redirectionAddressRedirectedBalance; expectedUserData.currentATokenUserIndex = userDataBeforeAction.currentATokenUserIndex; - if (reserveDataBeforeAction.address === configuration.ethereumAddress) { - expectedUserData.walletBalance = userDataBeforeAction.walletBalance - .minus(txCost) - .plus(amountBorrowed); - } else { - expectedUserData.walletBalance = userDataBeforeAction.walletBalance.plus(amountBorrowed); - } + expectedUserData.walletBalance = userDataBeforeAction.walletBalance.plus(amountBorrowed); return expectedUserData; }; @@ -657,8 +633,7 @@ export const calcExpectedUserDataAfterRepay = ( expectedUserData.stableBorrowRate = expectedUserData.stableRateLastUpdated = new BigNumber( '0' ); - } - else{ + } else { expectedUserData.stableBorrowRate = userDataBeforeAction.stableBorrowRate; expectedUserData.stableRateLastUpdated = txTimestamp; } @@ -697,14 +672,7 @@ export const calcExpectedUserDataAfterRepay = ( expectedUserData.currentATokenUserIndex = userDataBeforeAction.currentATokenUserIndex; if (user === onBehalfOf) { - //if user repaid for himself, update the wallet balances - if (reserveDataBeforeAction.address === configuration.ethereumAddress) { - expectedUserData.walletBalance = userDataBeforeAction.walletBalance - .minus(txCost) - .minus(totalRepaid); - } else { - expectedUserData.walletBalance = userDataBeforeAction.walletBalance.minus(totalRepaid); - } + expectedUserData.walletBalance = userDataBeforeAction.walletBalance.minus(totalRepaid); } else { //wallet balance didn't change expectedUserData.walletBalance = userDataBeforeAction.walletBalance; @@ -719,14 +687,10 @@ export const calcExpectedUserDataAfterSetUseAsCollateral = ( userDataBeforeAction: UserReserveData, txCost: BigNumber ): UserReserveData => { - const expectedUserData = {...userDataBeforeAction}; + const expectedUserData = { ...userDataBeforeAction }; expectedUserData.usageAsCollateralEnabled = useAsCollateral; - if (reserveDataBeforeAction.address === configuration.ethereumAddress) { - expectedUserData.walletBalance = userDataBeforeAction.walletBalance.minus(txCost); - } - return expectedUserData; }; @@ -829,7 +793,7 @@ export const calcExpectedUserDataAfterSwapRateMode = ( txCost: BigNumber, txTimestamp: BigNumber ): UserReserveData => { - const expectedUserData = {...userDataBeforeAction}; + const expectedUserData = { ...userDataBeforeAction }; const variableBorrowBalance = calcExpectedVariableDebtTokenBalance( reserveDataBeforeAction, @@ -892,9 +856,6 @@ export const calcExpectedUserDataAfterSwapRateMode = ( expectedUserData.liquidityRate = expectedDataAfterAction.liquidityRate; - if (reserveDataBeforeAction.address === configuration.ethereumAddress) { - expectedUserData.walletBalance = userDataBeforeAction.walletBalance.minus(txCost); - } return expectedUserData; }; @@ -976,7 +937,7 @@ export const calcExpectedUserDataAfterStableRateRebalance = ( txCost: BigNumber, txTimestamp: BigNumber ): UserReserveData => { - const expectedUserData = {...userDataBeforeAction}; + const expectedUserData = { ...userDataBeforeAction }; expectedUserData.principalVariableDebt = calcExpectedVariableDebtTokenBalance( reserveDataBeforeAction, @@ -1000,12 +961,6 @@ export const calcExpectedUserDataAfterStableRateRebalance = ( expectedUserData.liquidityRate = expectedDataAfterAction.liquidityRate; - if (reserveDataBeforeAction.address === configuration.ethereumAddress) { - expectedUserData.walletBalance = userDataBeforeAction.walletBalance.minus(txCost); - } - - expectedUserData.liquidityRate = expectedDataAfterAction.liquidityRate; - expectedUserData.currentATokenBalance = calcExpectedATokenBalance( reserveDataBeforeAction, userDataBeforeAction, @@ -1037,8 +992,8 @@ export const calcExpectedUsersDataAfterRedirectInterest = ( txCost: BigNumber, txTimestamp: BigNumber ): UserReserveData[] => { - const expectedFromData = {...fromDataBeforeAction}; - const expectedToData = {...toDataBeforeAction}; + const expectedFromData = { ...fromDataBeforeAction }; + const expectedToData = { ...toDataBeforeAction }; expectedFromData.currentStableDebt = calcExpectedStableDebtTokenBalance( fromDataBeforeAction, @@ -1069,12 +1024,6 @@ export const calcExpectedUsersDataAfterRedirectInterest = ( txTimestamp ); - if (isFromExecutingTx) { - if (reserveDataBeforeAction.address === configuration.ethereumAddress) { - expectedFromData.walletBalance = fromDataBeforeAction.walletBalance.minus(txCost); - } - } - expectedToData.redirectedBalance = toDataBeforeAction.redirectedBalance.plus( expectedFromData.currentATokenBalance ); @@ -1215,7 +1164,7 @@ export const calcExpectedVariableDebtTokenBalance = ( ) => { const debt = calcExpectedReserveNormalizedDebt(reserveDataBeforeAction, currentTimestamp); - const {principalVariableDebt, variableBorrowIndex} = userDataBeforeAction; + const { principalVariableDebt, variableBorrowIndex } = userDataBeforeAction; if (variableBorrowIndex.eq(0)) { return principalVariableDebt; @@ -1228,7 +1177,7 @@ export const calcExpectedStableDebtTokenBalance = ( userDataBeforeAction: UserReserveData, currentTimestamp: BigNumber ) => { - const {principalStableDebt, stableBorrowRate, stableRateLastUpdated} = userDataBeforeAction; + const { principalStableDebt, stableBorrowRate, stableRateLastUpdated } = userDataBeforeAction; if ( stableBorrowRate.eq(0) || @@ -1301,7 +1250,7 @@ const calcExpectedInterestRates = ( totalBorrowsVariable: BigNumber, averageStableBorrowRate: BigNumber ): BigNumber[] => { - const {reservesParams} = configuration; + const { reservesParams } = configuration; const reserveIndex = Object.keys(reservesParams).findIndex((value) => value === reserveSymbol); const [, reserveConfiguration] = (Object.entries(reservesParams) as [string, IReserveParams][])[ @@ -1391,7 +1340,7 @@ const calcExpectedReserveNormalizedIncome = ( reserveData: ReserveData, currentTimestamp: BigNumber ) => { - const {liquidityRate, liquidityIndex, lastUpdateTimestamp} = reserveData; + const { liquidityRate, liquidityIndex, lastUpdateTimestamp } = reserveData; //if utilization rate is 0, nothing to compound if (liquidityRate.eq('0')) { @@ -1413,7 +1362,7 @@ const calcExpectedReserveNormalizedDebt = ( reserveData: ReserveData, currentTimestamp: BigNumber ) => { - const {variableBorrowRate, variableBorrowIndex, lastUpdateTimestamp} = reserveData; + const { variableBorrowRate, variableBorrowIndex, lastUpdateTimestamp } = reserveData; //if utilization rate is 0, nothing to compound if (variableBorrowRate.eq('0')) { @@ -1472,31 +1421,3 @@ const calcExpectedVariableBorrowIndex = (reserveData: ReserveData, timestamp: Bi return cumulatedInterest.rayMul(reserveData.variableBorrowIndex); }; - -export const calculateHealthFactorFromBalances = ( - collateralBalanceETH: BigNumber, - borrowBalanceETH: BigNumber, - currentLiquidationThreshold: BigNumber -): BigNumber => { - if (borrowBalanceETH.eq(0)) { - return strToBN('-1'); // invalid number - } - return collateralBalanceETH.multipliedBy(currentLiquidationThreshold).div(borrowBalanceETH); -}; - -const calculateAvailableBorrowsETH = ( - collateralBalanceETH: BigNumber, - borrowBalanceETH: BigNumber, - currentLtv: BigNumber -): BigNumber => { - if (currentLtv.eq(0)) { - return strToBN('0'); - } - let availableBorrowsETH = collateralBalanceETH.multipliedBy(currentLtv); - if (availableBorrowsETH.lt(borrowBalanceETH)) { - return strToBN('0'); - } - availableBorrowsETH = availableBorrowsETH.minus(borrowBalanceETH); - const borrowFee = availableBorrowsETH.multipliedBy(0.0025); - return availableBorrowsETH.minus(borrowFee); -};