mirror of
https://github.com/Instadapp/aave-protocol-v2.git
synced 2024-07-29 21:47:30 +00:00
fix: changed conditions of the exposure ceiling
This commit is contained in:
parent
715635def4
commit
435c34fefd
|
@ -289,7 +289,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
|
|||
if (useAsCollateral) {
|
||||
emit ReserveUsedAsCollateralEnabled(asset, msg.sender);
|
||||
} else {
|
||||
ValidationLogic.validateWithdrawCollateral(
|
||||
ValidationLogic.validateHFAndExposureCap(
|
||||
asset,
|
||||
msg.sender,
|
||||
_reserves,
|
||||
|
@ -497,7 +497,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
|
|||
totalDebtETH,
|
||||
ltv,
|
||||
currentLiquidationThreshold,
|
||||
healthFactor
|
||||
healthFactor,
|
||||
) = GenericLogic.getUserAccountData(
|
||||
user,
|
||||
_reserves,
|
||||
|
@ -629,7 +629,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
|
|||
|
||||
if (fromConfig.isUsingAsCollateral(reserveId)) {
|
||||
if (fromConfig.isBorrowingAny()) {
|
||||
ValidationLogic.validateWithdrawCollateral(
|
||||
ValidationLogic.validateHFAndExposureCap(
|
||||
asset,
|
||||
from,
|
||||
_reserves,
|
||||
|
@ -877,7 +877,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
|
|||
|
||||
if (userConfig.isUsingAsCollateral(reserve.id)) {
|
||||
if (userConfig.isBorrowingAny()) {
|
||||
ValidationLogic.validateWithdrawCollateral(
|
||||
ValidationLogic.validateHFAndExposureCap(
|
||||
asset,
|
||||
msg.sender,
|
||||
_reserves,
|
||||
|
|
|
@ -34,6 +34,7 @@ library GenericLogic {
|
|||
uint256 userBalance;
|
||||
uint256 userBalanceETH;
|
||||
uint256 userDebt;
|
||||
uint256 userStableDebt;
|
||||
uint256 userDebtETH;
|
||||
uint256 decimals;
|
||||
uint256 ltv;
|
||||
|
@ -43,6 +44,7 @@ library GenericLogic {
|
|||
uint256 totalCollateralInETH;
|
||||
uint256 totalDebtInETH;
|
||||
uint256 avgLtv;
|
||||
uint256 avgUncappedLtv;
|
||||
uint256 avgLiquidationThreshold;
|
||||
uint256 reservesLength;
|
||||
uint256 normalizedIncome;
|
||||
|
@ -65,7 +67,7 @@ library GenericLogic {
|
|||
* @param userConfig The configuration of the user
|
||||
* @param reserves The list of the available reserves
|
||||
* @param oracle The price oracle address
|
||||
* @return The total collateral and total debt of the user in ETH, the avg ltv, liquidation threshold and the HF
|
||||
* @return The total collateral and total debt of the user in ETH, the avg ltv, liquidation threshold, the HF and the uncapped avg ltv (without exposure ceiling)
|
||||
**/
|
||||
function calculateUserAccountData(
|
||||
address user,
|
||||
|
@ -82,13 +84,14 @@ library GenericLogic {
|
|||
uint256,
|
||||
uint256,
|
||||
uint256,
|
||||
uint256,
|
||||
uint256
|
||||
)
|
||||
{
|
||||
CalculateUserAccountDataVars memory vars;
|
||||
|
||||
if (userConfig.isEmpty()) {
|
||||
return (0, 0, 0, 0, uint256(-1));
|
||||
return (0, 0, 0, 0, uint256(-1), 0);
|
||||
}
|
||||
for (vars.i = 0; vars.i < reservesCount; vars.i++) {
|
||||
if (!userConfig.isUsingAsCollateralOrBorrowing(vars.i)) {
|
||||
|
@ -130,14 +133,18 @@ library GenericLogic {
|
|||
vars.exposureCapCrossed =
|
||||
vars.exposureCap != 0 &&
|
||||
vars.aTokenSupply.div(10**vars.decimals) > vars.exposureCap;
|
||||
|
||||
vars.avgLtv = vars.avgLtv.add(vars.exposureCapCrossed ? 0 : vars.userBalanceETH.mul(vars.ltv));
|
||||
|
||||
vars.avgLtv = vars.avgLtv.add(
|
||||
vars.exposureCapCrossed ? 0 : vars.userBalanceETH.mul(vars.ltv)
|
||||
);
|
||||
vars.avgUncappedLtv = vars.avgUncappedLtv.add(vars.userBalanceETH.mul(vars.ltv));
|
||||
vars.avgLiquidationThreshold = vars.avgLiquidationThreshold.add(
|
||||
vars.userBalanceETH.mul(vars.liquidationThreshold)
|
||||
);
|
||||
}
|
||||
|
||||
if (userConfig.isBorrowing(vars.i)) {
|
||||
vars.userStableDebt = IERC20(currentReserve.stableDebtTokenAddress).balanceOf(user);
|
||||
vars.userDebt = IScaledBalanceToken(currentReserve.variableDebtTokenAddress)
|
||||
.scaledBalanceOf(user);
|
||||
|
||||
|
@ -145,16 +152,16 @@ library GenericLogic {
|
|||
vars.normalizedDebt = currentReserve.getNormalizedDebt();
|
||||
vars.userDebt = vars.userDebt.rayMul(vars.normalizedDebt);
|
||||
}
|
||||
|
||||
vars.userDebt = vars.userDebt.add(
|
||||
IERC20(currentReserve.stableDebtTokenAddress).balanceOf(user)
|
||||
);
|
||||
vars.userDebt = vars.userDebt.add(vars.userStableDebt);
|
||||
vars.userDebtETH = vars.assetPrice.mul(vars.userDebt).div(vars.assetUnit);
|
||||
vars.totalDebtInETH = vars.totalDebtInETH.add(vars.userDebtETH);
|
||||
}
|
||||
}
|
||||
|
||||
vars.avgLtv = vars.totalCollateralInETH > 0 ? vars.avgLtv.div(vars.totalCollateralInETH) : 0;
|
||||
vars.avgUncappedLtv = vars.totalCollateralInETH > 0
|
||||
? vars.avgUncappedLtv.div(vars.totalCollateralInETH)
|
||||
: 0;
|
||||
vars.avgLiquidationThreshold = vars.totalCollateralInETH > 0
|
||||
? vars.avgLiquidationThreshold.div(vars.totalCollateralInETH)
|
||||
: 0;
|
||||
|
@ -169,7 +176,8 @@ library GenericLogic {
|
|||
vars.totalDebtInETH,
|
||||
vars.avgLtv,
|
||||
vars.avgLiquidationThreshold,
|
||||
vars.healthFactor
|
||||
vars.healthFactor,
|
||||
vars.avgUncappedLtv
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -239,6 +247,7 @@ library GenericLogic {
|
|||
uint256,
|
||||
uint256,
|
||||
uint256,
|
||||
uint256,
|
||||
uint256
|
||||
)
|
||||
{
|
||||
|
|
|
@ -185,7 +185,7 @@ library ValidationLogic {
|
|||
vars.userBorrowBalanceETH,
|
||||
vars.currentLtv,
|
||||
vars.currentLiquidationThreshold,
|
||||
vars.healthFactor
|
||||
vars.healthFactor,
|
||||
) = GenericLogic.calculateUserAccountData(
|
||||
userAddress,
|
||||
reservesData,
|
||||
|
@ -263,7 +263,7 @@ library ValidationLogic {
|
|||
address onBehalfOf,
|
||||
uint256 stableDebt,
|
||||
uint256 variableDebt
|
||||
) internal view {
|
||||
) external view {
|
||||
(bool isActive, , , , bool isPaused) = reserveCache.reserveConfiguration.getFlagsMemory();
|
||||
require(isActive, Errors.VL_NO_ACTIVE_RESERVE);
|
||||
require(!isPaused, Errors.VL_RESERVE_PAUSED);
|
||||
|
@ -469,7 +469,7 @@ library ValidationLogic {
|
|||
return (uint256(Errors.CollateralManagerErrors.PAUSED_RESERVE), Errors.VL_RESERVE_PAUSED);
|
||||
}
|
||||
|
||||
(, , , , vars.healthFactor) = GenericLogic.calculateUserAccountData(
|
||||
(, , , , vars.healthFactor, ) = GenericLogic.calculateUserAccountData(
|
||||
user,
|
||||
reservesData,
|
||||
userConfig,
|
||||
|
@ -508,7 +508,7 @@ library ValidationLogic {
|
|||
}
|
||||
|
||||
/**
|
||||
* @dev Validates the health factor of a user
|
||||
* @dev Validates the health factor of a user and the exposure cap for the asset being withdrawn
|
||||
* @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
|
||||
|
@ -516,7 +516,7 @@ library ValidationLogic {
|
|||
* @param reservesCount The number of available reserves
|
||||
* @param oracle The price oracle
|
||||
*/
|
||||
function validateWithdrawCollateral(
|
||||
function validateHFAndExposureCap(
|
||||
address collateral,
|
||||
address from,
|
||||
mapping(address => DataTypes.ReserveData) storage reservesData,
|
||||
|
@ -526,7 +526,7 @@ library ValidationLogic {
|
|||
address oracle
|
||||
) external view {
|
||||
DataTypes.ReserveData memory reserve = reservesData[collateral];
|
||||
(, , uint256 ltv, uint256 liquidationThreshold, uint256 healthFactor) =
|
||||
(, , uint256 ltv, uint256 liquidationThreshold, uint256 healthFactor, uint256 uncappedLtv) =
|
||||
GenericLogic.calculateUserAccountData(
|
||||
from,
|
||||
reservesData,
|
||||
|
@ -536,28 +536,22 @@ library ValidationLogic {
|
|||
oracle
|
||||
);
|
||||
|
||||
uint256 exposureCap = reserve.configuration.getExposureCapMemory();
|
||||
uint256 totalSupplyAtoken = IERC20(reserve.aTokenAddress).totalSupply();
|
||||
(, , , uint256 reserveDecimals, ) = reserve.configuration.getParamsMemory();
|
||||
|
||||
require(
|
||||
healthFactor >= GenericLogic.HEALTH_FACTOR_LIQUIDATION_THRESHOLD,
|
||||
Errors.VL_HEALTH_FACTOR_LOWER_THAN_LIQUIDATION_THRESHOLD
|
||||
);
|
||||
|
||||
// exposureCap == 0 means no cap => can withdraw
|
||||
// ltv > liquidationThreshold means that there is enough collateral margin => can withdraw
|
||||
// ltv == 0 means all current collaterals have exceeded the exposure cap => can withdraw
|
||||
// last means that for this asset the cap is not yet exceeded => can withdraw
|
||||
// else this means the user is trying to withdraw a collateral that has exceeded the exposure cap, and that it
|
||||
// as other collaterals available to withdraw: he must withdraw from other collateral reserves first
|
||||
require(
|
||||
exposureCap == 0 ||
|
||||
ltv > liquidationThreshold ||
|
||||
ltv == 0 ||
|
||||
totalSupplyAtoken.div(10**reserveDecimals) < exposureCap,
|
||||
Errors.VL_COLLATERAL_EXPOSURE_CAP_EXCEEDED
|
||||
);
|
||||
uint256 exposureCap = reserve.configuration.getExposureCapMemory();
|
||||
|
||||
if (exposureCap != 0) {
|
||||
if (ltv < uncappedLtv) {
|
||||
uint256 totalSupplyAtoken = IERC20(reserve.aTokenAddress).totalSupply();
|
||||
(, , , uint256 reserveDecimals, ) = reserve.configuration.getParamsMemory();
|
||||
bool isAssetCapped = totalSupplyAtoken.div(10**reserveDecimals) >= exposureCap;
|
||||
require(isAssetCapped, Errors.VL_COLLATERAL_EXPOSURE_CAP_EXCEEDED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue
Block a user