refactor: removed balanceDecreaseAllowed

This commit is contained in:
The3D 2021-04-29 19:55:52 +02:00
parent 45acc0b854
commit ed987ac46e
4 changed files with 38 additions and 178 deletions

View File

@ -156,16 +156,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
amountToWithdraw = userBalance; amountToWithdraw = userBalance;
} }
ValidationLogic.validateWithdraw( ValidationLogic.validateWithdraw(reserve, amountToWithdraw, userBalance);
asset,
amountToWithdraw,
userBalance,
_reserves,
_usersConfig[msg.sender],
_reservesList,
_reservesCount,
_addressesProvider.getPriceOracle()
);
reserve.updateState(); reserve.updateState();
@ -178,6 +169,15 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
IAToken(aToken).burn(msg.sender, to, amountToWithdraw, reserve.liquidityIndex); 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); emit Withdraw(asset, msg.sender, to, amountToWithdraw);
return amountToWithdraw; return amountToWithdraw;
@ -391,22 +391,22 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
{ {
DataTypes.ReserveData storage reserve = _reserves[asset]; DataTypes.ReserveData storage reserve = _reserves[asset];
ValidationLogic.validateSetUseReserveAsCollateral( ValidationLogic.validateSetUseReserveAsCollateral(reserve);
reserve,
asset,
useAsCollateral,
_reserves,
_usersConfig[msg.sender],
_reservesList,
_reservesCount,
_addressesProvider.getPriceOracle()
);
_usersConfig[msg.sender].setUsingAsCollateral(reserve.id, useAsCollateral); _usersConfig[msg.sender].setUsingAsCollateral(reserve.id, useAsCollateral);
if (useAsCollateral) { if (useAsCollateral) {
emit ReserveUsedAsCollateralEnabled(asset, msg.sender); emit ReserveUsedAsCollateralEnabled(asset, msg.sender);
} else { } else {
ValidationLogic.validateHealthFactor(
msg.sender,
_reserves,
_usersConfig[msg.sender],
_reservesList,
_reservesCount,
_addressesProvider.getPriceOracle()
);
emit ReserveUsedAsCollateralDisabled(asset, msg.sender); 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) { function FLASHLOAN_PREMIUM_TOTAL() public view returns (uint256) {
return _flashLoanPremiumTotal; return _flashLoanPremiumTotal;
@ -746,7 +746,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
) external override whenNotPaused { ) external override whenNotPaused {
require(msg.sender == _reserves[asset].aTokenAddress, Errors.LP_CALLER_MUST_BE_AN_ATOKEN); require(msg.sender == _reserves[asset].aTokenAddress, Errors.LP_CALLER_MUST_BE_AN_ATOKEN);
ValidationLogic.validateTransfer( ValidationLogic.validateHealthFactor(
from, from,
_reserves, _reserves,
_usersConfig[from], _usersConfig[from],

View File

@ -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_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_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_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_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_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' string public constant VL_COLLATERAL_BALANCE_IS_0 = '9'; // 'The collateral balance is 0'

View File

@ -28,94 +28,6 @@ library GenericLogic {
uint256 public constant HEALTH_FACTOR_LIQUIDATION_THRESHOLD = 1 ether; 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 { struct CalculateUserAccountDataVars {
uint256 assetPrice; uint256 assetPrice;
uint256 assetUnit; uint256 assetUnit;
@ -220,8 +132,7 @@ library GenericLogic {
IERC20(currentReserve.stableDebtTokenAddress).balanceOf(user) IERC20(currentReserve.stableDebtTokenAddress).balanceOf(user)
); );
vars.userDebtETH = vars.assetPrice.mul(vars.userDebt).div(vars.assetUnit); vars.userDebtETH = vars.assetPrice.mul(vars.userDebt).div(vars.assetUnit);
vars.totalDebtInETH = vars.totalDebtInETH.add(vars.userDebtETH); vars.totalDebtInETH = vars.totalDebtInETH.add(vars.userDebtETH);
} }
} }

View File

@ -38,7 +38,7 @@ library ValidationLogic {
* @param reserve The reserve object on which the user is depositing * @param reserve The reserve object on which the user is depositing
* @param amount The amount to be deposited * @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(); (bool isActive, bool isFrozen, , ) = reserve.configuration.getFlags();
require(amount != 0, Errors.VL_INVALID_AMOUNT); require(amount != 0, Errors.VL_INVALID_AMOUNT);
@ -46,46 +46,23 @@ library ValidationLogic {
require(!isFrozen, Errors.VL_RESERVE_FROZEN); require(!isFrozen, Errors.VL_RESERVE_FROZEN);
} }
/** /**
* @dev Validates a withdraw action * @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 amount The amount to be withdrawn
* @param userBalance The balance of the user * @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( function validateWithdraw(
address reserveAddress, DataTypes.ReserveData storage reserve,
uint256 amount, uint256 amount,
uint256 userBalance, uint256 userBalance
mapping(address => DataTypes.ReserveData) storage reservesData, ) internal view {
DataTypes.UserConfigurationMap storage userConfig,
mapping(uint256 => address) storage reserves,
uint256 reservesCount,
address oracle
) external view {
require(amount != 0, Errors.VL_INVALID_AMOUNT); require(amount != 0, Errors.VL_INVALID_AMOUNT);
require(amount <= userBalance, Errors.VL_NOT_ENOUGH_AVAILABLE_USER_BALANCE); 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(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 { struct ValidateBorrowLocalVars {
@ -130,7 +107,7 @@ library ValidationLogic {
mapping(uint256 => address) storage reserves, mapping(uint256 => address) storage reserves,
uint256 reservesCount, uint256 reservesCount,
address oracle address oracle
) external view { ) internal view {
ValidateBorrowLocalVars memory vars; ValidateBorrowLocalVars memory vars;
(vars.isActive, vars.isFrozen, vars.borrowingEnabled, vars.stableRateBorrowingEnabled) = reserve (vars.isActive, vars.isFrozen, vars.borrowingEnabled, vars.stableRateBorrowingEnabled) = reserve
@ -227,7 +204,7 @@ library ValidationLogic {
address onBehalfOf, address onBehalfOf,
uint256 stableDebt, uint256 stableDebt,
uint256 variableDebt uint256 variableDebt
) external view { ) internal view {
bool isActive = reserve.configuration.getActive(); bool isActive = reserve.configuration.getActive();
require(isActive, Errors.VL_NO_ACTIVE_RESERVE); require(isActive, Errors.VL_NO_ACTIVE_RESERVE);
@ -306,7 +283,7 @@ library ValidationLogic {
IERC20 stableDebtToken, IERC20 stableDebtToken,
IERC20 variableDebtToken, IERC20 variableDebtToken,
address aTokenAddress address aTokenAddress
) external view { ) internal view {
(bool isActive, , , ) = reserve.configuration.getFlags(); (bool isActive, , , ) = reserve.configuration.getFlags();
require(isActive, Errors.VL_NO_ACTIVE_RESERVE); require(isActive, Errors.VL_NO_ACTIVE_RESERVE);
@ -335,40 +312,13 @@ library ValidationLogic {
/** /**
* @dev Validates the action of setting an asset as collateral * @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 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( function validateSetUseReserveAsCollateral(
DataTypes.ReserveData storage reserve, DataTypes.ReserveData storage reserve
address reserveAddress, ) internal view {
bool useAsCollateral,
mapping(address => DataTypes.ReserveData) storage reservesData,
DataTypes.UserConfigurationMap storage userConfig,
mapping(uint256 => address) storage reserves,
uint256 reservesCount,
address oracle
) external view {
uint256 underlyingBalance = IERC20(reserve.aTokenAddress).balanceOf(msg.sender); uint256 underlyingBalance = IERC20(reserve.aTokenAddress).balanceOf(msg.sender);
require(underlyingBalance > 0, Errors.VL_UNDERLYING_BALANCE_NOT_GREATER_THAN_0); 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 from The user from which the aTokens are being transferred
* @param reservesData The state of all the reserves * @param reservesData The state of all the reserves
* @param userConfig The state of the user for the specific reserve * @param userConfig The state of the user for the specific reserve
* @param reserves The addresses of all the active reserves * @param reserves The addresses of all the active reserves
* @param oracle The price oracle * @param oracle The price oracle
*/ */
function validateTransfer( function validateHealthFactor(
address from, address from,
mapping(address => DataTypes.ReserveData) storage reservesData, mapping(address => DataTypes.ReserveData) storage reservesData,
DataTypes.UserConfigurationMap storage userConfig, DataTypes.UserConfigurationMap storage userConfig,
@ -463,7 +413,7 @@ library ValidationLogic {
require( require(
healthFactor >= GenericLogic.HEALTH_FACTOR_LIQUIDATION_THRESHOLD, healthFactor >= GenericLogic.HEALTH_FACTOR_LIQUIDATION_THRESHOLD,
Errors.VL_TRANSFER_NOT_ALLOWED Errors.VL_HEALTH_FACTOR_LOWER_THAN_LIQUIDATION_THRESHOLD
); );
} }
} }