From ed987ac46eb05ac439026cdb3f78cd6cf63ca693 Mon Sep 17 00:00:00 2001 From: The3D Date: Thu, 29 Apr 2021 19:55:52 +0200 Subject: [PATCH] refactor: removed balanceDecreaseAllowed --- .../protocol/lendingpool/LendingPool.sol | 44 ++++----- .../protocol/libraries/helpers/Errors.sol | 1 - .../protocol/libraries/logic/GenericLogic.sol | 91 +------------------ .../libraries/logic/ValidationLogic.sol | 80 +++------------- 4 files changed, 38 insertions(+), 178 deletions(-) diff --git a/contracts/protocol/lendingpool/LendingPool.sol b/contracts/protocol/lendingpool/LendingPool.sol index 8e38650c..3d2be8ce 100644 --- a/contracts/protocol/lendingpool/LendingPool.sol +++ b/contracts/protocol/lendingpool/LendingPool.sol @@ -156,16 +156,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage amountToWithdraw = userBalance; } - ValidationLogic.validateWithdraw( - asset, - amountToWithdraw, - userBalance, - _reserves, - _usersConfig[msg.sender], - _reservesList, - _reservesCount, - _addressesProvider.getPriceOracle() - ); + ValidationLogic.validateWithdraw(reserve, amountToWithdraw, userBalance); reserve.updateState(); @@ -178,6 +169,15 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage IAToken(aToken).burn(msg.sender, to, amountToWithdraw, reserve.liquidityIndex); + ValidationLogic.validateHealthFactor( + msg.sender, + _reserves, + _usersConfig[msg.sender], + _reservesList, + _reservesCount, + _addressesProvider.getPriceOracle() + ); + emit Withdraw(asset, msg.sender, to, amountToWithdraw); return amountToWithdraw; @@ -391,22 +391,22 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage { DataTypes.ReserveData storage reserve = _reserves[asset]; - ValidationLogic.validateSetUseReserveAsCollateral( - reserve, - asset, - useAsCollateral, - _reserves, - _usersConfig[msg.sender], - _reservesList, - _reservesCount, - _addressesProvider.getPriceOracle() - ); + ValidationLogic.validateSetUseReserveAsCollateral(reserve); _usersConfig[msg.sender].setUsingAsCollateral(reserve.id, useAsCollateral); if (useAsCollateral) { emit ReserveUsedAsCollateralEnabled(asset, msg.sender); } else { + ValidationLogic.validateHealthFactor( + msg.sender, + _reserves, + _usersConfig[msg.sender], + _reservesList, + _reservesCount, + _addressesProvider.getPriceOracle() + ); + emit ReserveUsedAsCollateralDisabled(asset, msg.sender); } } @@ -713,7 +713,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage } /** - * @dev Returns the fee on flash loans + * @dev Returns the fee on flash loans */ function FLASHLOAN_PREMIUM_TOTAL() public view returns (uint256) { return _flashLoanPremiumTotal; @@ -746,7 +746,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage ) external override whenNotPaused { require(msg.sender == _reserves[asset].aTokenAddress, Errors.LP_CALLER_MUST_BE_AN_ATOKEN); - ValidationLogic.validateTransfer( + ValidationLogic.validateHealthFactor( from, _reserves, _usersConfig[from], diff --git a/contracts/protocol/libraries/helpers/Errors.sol b/contracts/protocol/libraries/helpers/Errors.sol index 8756d797..9729379d 100644 --- a/contracts/protocol/libraries/helpers/Errors.sol +++ b/contracts/protocol/libraries/helpers/Errors.sol @@ -30,7 +30,6 @@ library Errors { string public constant VL_RESERVE_FROZEN = '3'; // 'Action cannot be performed because the reserve is frozen' string public constant VL_CURRENT_AVAILABLE_LIQUIDITY_NOT_ENOUGH = '4'; // 'The current liquidity is not enough' string public constant VL_NOT_ENOUGH_AVAILABLE_USER_BALANCE = '5'; // 'User cannot withdraw more than the available balance' - string public constant VL_TRANSFER_NOT_ALLOWED = '6'; // 'Transfer cannot be allowed.' string public constant VL_BORROWING_NOT_ENABLED = '7'; // 'Borrowing is not enabled' string public constant VL_INVALID_INTEREST_RATE_MODE_SELECTED = '8'; // 'Invalid interest rate mode selected' string public constant VL_COLLATERAL_BALANCE_IS_0 = '9'; // 'The collateral balance is 0' diff --git a/contracts/protocol/libraries/logic/GenericLogic.sol b/contracts/protocol/libraries/logic/GenericLogic.sol index 5722dd2b..381fe804 100644 --- a/contracts/protocol/libraries/logic/GenericLogic.sol +++ b/contracts/protocol/libraries/logic/GenericLogic.sol @@ -28,94 +28,6 @@ library GenericLogic { uint256 public constant HEALTH_FACTOR_LIQUIDATION_THRESHOLD = 1 ether; - struct balanceDecreaseAllowedLocalVars { - uint256 decimals; - uint256 liquidationThreshold; - uint256 totalCollateralInETH; - uint256 totalDebtInETH; - uint256 avgLiquidationThreshold; - uint256 amountToDecreaseInETH; - uint256 collateralBalanceAfterDecrease; - uint256 liquidationThresholdAfterDecrease; - uint256 healthFactorAfterDecrease; - bool reserveUsageAsCollateralEnabled; - } - - /** - * @dev Checks if a specific balance decrease is allowed - * (i.e. doesn't bring the user borrow position health factor under HEALTH_FACTOR_LIQUIDATION_THRESHOLD) - * @param asset The address of the underlying asset of the reserve - * @param user The address of the user - * @param amount The amount to decrease - * @param reservesData The data of all the reserves - * @param userConfig The user configuration - * @param reserves The list of all the active reserves - * @param oracle The address of the oracle contract - * @return true if the decrease of the balance is allowed - **/ - function balanceDecreaseAllowed( - address asset, - address user, - uint256 amount, - mapping(address => DataTypes.ReserveData) storage reservesData, - DataTypes.UserConfigurationMap calldata userConfig, - mapping(uint256 => address) storage reserves, - uint256 reservesCount, - address oracle - ) external view returns (bool) { - if (!userConfig.isBorrowingAny() || !userConfig.isUsingAsCollateral(reservesData[asset].id)) { - return true; - } - - balanceDecreaseAllowedLocalVars memory vars; - - (, vars.liquidationThreshold, , vars.decimals, ) = reservesData[asset] - .configuration - .getParams(); - - if (vars.liquidationThreshold == 0) { - return true; - } - - ( - vars.totalCollateralInETH, - vars.totalDebtInETH, - , - vars.avgLiquidationThreshold, - - ) = calculateUserAccountData(user, reservesData, userConfig, reserves, reservesCount, oracle); - - if (vars.totalDebtInETH == 0) { - return true; - } - - vars.amountToDecreaseInETH = IPriceOracleGetter(oracle).getAssetPrice(asset).mul(amount).div( - 10**vars.decimals - ); - - vars.collateralBalanceAfterDecrease = vars.totalCollateralInETH.sub(vars.amountToDecreaseInETH); - - //if there is a borrow, there can't be 0 collateral - if (vars.collateralBalanceAfterDecrease == 0) { - return false; - } - - vars.liquidationThresholdAfterDecrease = vars - .totalCollateralInETH - .mul(vars.avgLiquidationThreshold) - .sub(vars.amountToDecreaseInETH.mul(vars.liquidationThreshold)) - .div(vars.collateralBalanceAfterDecrease); - - uint256 healthFactorAfterDecrease = - calculateHealthFactorFromBalances( - vars.collateralBalanceAfterDecrease, - vars.totalDebtInETH, - vars.liquidationThresholdAfterDecrease - ); - - return healthFactorAfterDecrease >= GenericLogic.HEALTH_FACTOR_LIQUIDATION_THRESHOLD; - } - struct CalculateUserAccountDataVars { uint256 assetPrice; uint256 assetUnit; @@ -220,8 +132,7 @@ library GenericLogic { IERC20(currentReserve.stableDebtTokenAddress).balanceOf(user) ); vars.userDebtETH = vars.assetPrice.mul(vars.userDebt).div(vars.assetUnit); - vars.totalDebtInETH = vars.totalDebtInETH.add(vars.userDebtETH); - + vars.totalDebtInETH = vars.totalDebtInETH.add(vars.userDebtETH); } } diff --git a/contracts/protocol/libraries/logic/ValidationLogic.sol b/contracts/protocol/libraries/logic/ValidationLogic.sol index 080b792d..6c15a4e1 100644 --- a/contracts/protocol/libraries/logic/ValidationLogic.sol +++ b/contracts/protocol/libraries/logic/ValidationLogic.sol @@ -38,7 +38,7 @@ library ValidationLogic { * @param reserve The reserve object on which the user is depositing * @param amount The amount to be deposited */ - function validateDeposit(DataTypes.ReserveData storage reserve, uint256 amount) external view { + function validateDeposit(DataTypes.ReserveData storage reserve, uint256 amount) internal view { (bool isActive, bool isFrozen, , ) = reserve.configuration.getFlags(); require(amount != 0, Errors.VL_INVALID_AMOUNT); @@ -46,46 +46,23 @@ library ValidationLogic { require(!isFrozen, Errors.VL_RESERVE_FROZEN); } + /** * @dev Validates a withdraw action - * @param reserveAddress The address of the reserve + * @param reserve The reserve object * @param amount The amount to be withdrawn * @param userBalance The balance of the user - * @param reservesData The reserves state - * @param userConfig The user configuration - * @param reserves The addresses of the reserves - * @param reservesCount The number of reserves - * @param oracle The price oracle */ function validateWithdraw( - address reserveAddress, + DataTypes.ReserveData storage reserve, uint256 amount, - uint256 userBalance, - mapping(address => DataTypes.ReserveData) storage reservesData, - DataTypes.UserConfigurationMap storage userConfig, - mapping(uint256 => address) storage reserves, - uint256 reservesCount, - address oracle - ) external view { + uint256 userBalance + ) internal view { require(amount != 0, Errors.VL_INVALID_AMOUNT); require(amount <= userBalance, Errors.VL_NOT_ENOUGH_AVAILABLE_USER_BALANCE); - (bool isActive, , , ) = reservesData[reserveAddress].configuration.getFlags(); + (bool isActive, , , ) = reserve.configuration.getFlags(); require(isActive, Errors.VL_NO_ACTIVE_RESERVE); - - require( - GenericLogic.balanceDecreaseAllowed( - reserveAddress, - msg.sender, - amount, - reservesData, - userConfig, - reserves, - reservesCount, - oracle - ), - Errors.VL_TRANSFER_NOT_ALLOWED - ); } struct ValidateBorrowLocalVars { @@ -130,7 +107,7 @@ library ValidationLogic { mapping(uint256 => address) storage reserves, uint256 reservesCount, address oracle - ) external view { + ) internal view { ValidateBorrowLocalVars memory vars; (vars.isActive, vars.isFrozen, vars.borrowingEnabled, vars.stableRateBorrowingEnabled) = reserve @@ -227,7 +204,7 @@ library ValidationLogic { address onBehalfOf, uint256 stableDebt, uint256 variableDebt - ) external view { + ) internal view { bool isActive = reserve.configuration.getActive(); require(isActive, Errors.VL_NO_ACTIVE_RESERVE); @@ -306,7 +283,7 @@ library ValidationLogic { IERC20 stableDebtToken, IERC20 variableDebtToken, address aTokenAddress - ) external view { + ) internal view { (bool isActive, , , ) = reserve.configuration.getFlags(); require(isActive, Errors.VL_NO_ACTIVE_RESERVE); @@ -335,40 +312,13 @@ library ValidationLogic { /** * @dev Validates the action of setting an asset as collateral * @param reserve The state of the reserve that the user is enabling or disabling as collateral - * @param reserveAddress The address of the reserve - * @param reservesData The data of all the reserves - * @param userConfig The state of the user for the specific reserve - * @param reserves The addresses of all the active reserves - * @param oracle The price oracle */ function validateSetUseReserveAsCollateral( - DataTypes.ReserveData storage reserve, - address reserveAddress, - bool useAsCollateral, - mapping(address => DataTypes.ReserveData) storage reservesData, - DataTypes.UserConfigurationMap storage userConfig, - mapping(uint256 => address) storage reserves, - uint256 reservesCount, - address oracle - ) external view { + DataTypes.ReserveData storage reserve + ) internal view { uint256 underlyingBalance = IERC20(reserve.aTokenAddress).balanceOf(msg.sender); require(underlyingBalance > 0, Errors.VL_UNDERLYING_BALANCE_NOT_GREATER_THAN_0); - - require( - useAsCollateral || - GenericLogic.balanceDecreaseAllowed( - reserveAddress, - msg.sender, - underlyingBalance, - reservesData, - userConfig, - reserves, - reservesCount, - oracle - ), - Errors.VL_DEPOSIT_ALREADY_IN_USE - ); } /** @@ -436,14 +386,14 @@ library ValidationLogic { } /** - * @dev Validates an aToken transfer + * @dev Validates the health factor of a user * @param from The user from which the aTokens are being transferred * @param reservesData The state of all the reserves * @param userConfig The state of the user for the specific reserve * @param reserves The addresses of all the active reserves * @param oracle The price oracle */ - function validateTransfer( + function validateHealthFactor( address from, mapping(address => DataTypes.ReserveData) storage reservesData, DataTypes.UserConfigurationMap storage userConfig, @@ -463,7 +413,7 @@ library ValidationLogic { require( healthFactor >= GenericLogic.HEALTH_FACTOR_LIQUIDATION_THRESHOLD, - Errors.VL_TRANSFER_NOT_ALLOWED + Errors.VL_HEALTH_FACTOR_LOWER_THAN_LIQUIDATION_THRESHOLD ); } }