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) {
|
if (useAsCollateral) {
|
||||||
emit ReserveUsedAsCollateralEnabled(asset, msg.sender);
|
emit ReserveUsedAsCollateralEnabled(asset, msg.sender);
|
||||||
} else {
|
} else {
|
||||||
ValidationLogic.validateWithdrawCollateral(
|
ValidationLogic.validateHFAndExposureCap(
|
||||||
asset,
|
asset,
|
||||||
msg.sender,
|
msg.sender,
|
||||||
_reserves,
|
_reserves,
|
||||||
|
@ -497,7 +497,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
|
||||||
totalDebtETH,
|
totalDebtETH,
|
||||||
ltv,
|
ltv,
|
||||||
currentLiquidationThreshold,
|
currentLiquidationThreshold,
|
||||||
healthFactor
|
healthFactor,
|
||||||
) = GenericLogic.getUserAccountData(
|
) = GenericLogic.getUserAccountData(
|
||||||
user,
|
user,
|
||||||
_reserves,
|
_reserves,
|
||||||
|
@ -629,7 +629,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
|
||||||
|
|
||||||
if (fromConfig.isUsingAsCollateral(reserveId)) {
|
if (fromConfig.isUsingAsCollateral(reserveId)) {
|
||||||
if (fromConfig.isBorrowingAny()) {
|
if (fromConfig.isBorrowingAny()) {
|
||||||
ValidationLogic.validateWithdrawCollateral(
|
ValidationLogic.validateHFAndExposureCap(
|
||||||
asset,
|
asset,
|
||||||
from,
|
from,
|
||||||
_reserves,
|
_reserves,
|
||||||
|
@ -877,7 +877,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
|
||||||
|
|
||||||
if (userConfig.isUsingAsCollateral(reserve.id)) {
|
if (userConfig.isUsingAsCollateral(reserve.id)) {
|
||||||
if (userConfig.isBorrowingAny()) {
|
if (userConfig.isBorrowingAny()) {
|
||||||
ValidationLogic.validateWithdrawCollateral(
|
ValidationLogic.validateHFAndExposureCap(
|
||||||
asset,
|
asset,
|
||||||
msg.sender,
|
msg.sender,
|
||||||
_reserves,
|
_reserves,
|
||||||
|
|
|
@ -34,6 +34,7 @@ library GenericLogic {
|
||||||
uint256 userBalance;
|
uint256 userBalance;
|
||||||
uint256 userBalanceETH;
|
uint256 userBalanceETH;
|
||||||
uint256 userDebt;
|
uint256 userDebt;
|
||||||
|
uint256 userStableDebt;
|
||||||
uint256 userDebtETH;
|
uint256 userDebtETH;
|
||||||
uint256 decimals;
|
uint256 decimals;
|
||||||
uint256 ltv;
|
uint256 ltv;
|
||||||
|
@ -43,6 +44,7 @@ library GenericLogic {
|
||||||
uint256 totalCollateralInETH;
|
uint256 totalCollateralInETH;
|
||||||
uint256 totalDebtInETH;
|
uint256 totalDebtInETH;
|
||||||
uint256 avgLtv;
|
uint256 avgLtv;
|
||||||
|
uint256 avgUncappedLtv;
|
||||||
uint256 avgLiquidationThreshold;
|
uint256 avgLiquidationThreshold;
|
||||||
uint256 reservesLength;
|
uint256 reservesLength;
|
||||||
uint256 normalizedIncome;
|
uint256 normalizedIncome;
|
||||||
|
@ -65,7 +67,7 @@ library GenericLogic {
|
||||||
* @param userConfig The configuration of the user
|
* @param userConfig The configuration of the user
|
||||||
* @param reserves The list of the available reserves
|
* @param reserves The list of the available reserves
|
||||||
* @param oracle The price oracle address
|
* @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(
|
function calculateUserAccountData(
|
||||||
address user,
|
address user,
|
||||||
|
@ -82,13 +84,14 @@ library GenericLogic {
|
||||||
uint256,
|
uint256,
|
||||||
uint256,
|
uint256,
|
||||||
uint256,
|
uint256,
|
||||||
|
uint256,
|
||||||
uint256
|
uint256
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
CalculateUserAccountDataVars memory vars;
|
CalculateUserAccountDataVars memory vars;
|
||||||
|
|
||||||
if (userConfig.isEmpty()) {
|
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++) {
|
for (vars.i = 0; vars.i < reservesCount; vars.i++) {
|
||||||
if (!userConfig.isUsingAsCollateralOrBorrowing(vars.i)) {
|
if (!userConfig.isUsingAsCollateralOrBorrowing(vars.i)) {
|
||||||
|
@ -131,13 +134,17 @@ library GenericLogic {
|
||||||
vars.exposureCap != 0 &&
|
vars.exposureCap != 0 &&
|
||||||
vars.aTokenSupply.div(10**vars.decimals) > vars.exposureCap;
|
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.avgLiquidationThreshold = vars.avgLiquidationThreshold.add(
|
||||||
vars.userBalanceETH.mul(vars.liquidationThreshold)
|
vars.userBalanceETH.mul(vars.liquidationThreshold)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (userConfig.isBorrowing(vars.i)) {
|
if (userConfig.isBorrowing(vars.i)) {
|
||||||
|
vars.userStableDebt = IERC20(currentReserve.stableDebtTokenAddress).balanceOf(user);
|
||||||
vars.userDebt = IScaledBalanceToken(currentReserve.variableDebtTokenAddress)
|
vars.userDebt = IScaledBalanceToken(currentReserve.variableDebtTokenAddress)
|
||||||
.scaledBalanceOf(user);
|
.scaledBalanceOf(user);
|
||||||
|
|
||||||
|
@ -145,16 +152,16 @@ library GenericLogic {
|
||||||
vars.normalizedDebt = currentReserve.getNormalizedDebt();
|
vars.normalizedDebt = currentReserve.getNormalizedDebt();
|
||||||
vars.userDebt = vars.userDebt.rayMul(vars.normalizedDebt);
|
vars.userDebt = vars.userDebt.rayMul(vars.normalizedDebt);
|
||||||
}
|
}
|
||||||
|
vars.userDebt = vars.userDebt.add(vars.userStableDebt);
|
||||||
vars.userDebt = vars.userDebt.add(
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vars.avgLtv = vars.totalCollateralInETH > 0 ? vars.avgLtv.div(vars.totalCollateralInETH) : 0;
|
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 = vars.totalCollateralInETH > 0
|
||||||
? vars.avgLiquidationThreshold.div(vars.totalCollateralInETH)
|
? vars.avgLiquidationThreshold.div(vars.totalCollateralInETH)
|
||||||
: 0;
|
: 0;
|
||||||
|
@ -169,7 +176,8 @@ library GenericLogic {
|
||||||
vars.totalDebtInETH,
|
vars.totalDebtInETH,
|
||||||
vars.avgLtv,
|
vars.avgLtv,
|
||||||
vars.avgLiquidationThreshold,
|
vars.avgLiquidationThreshold,
|
||||||
vars.healthFactor
|
vars.healthFactor,
|
||||||
|
vars.avgUncappedLtv
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -239,6 +247,7 @@ library GenericLogic {
|
||||||
uint256,
|
uint256,
|
||||||
uint256,
|
uint256,
|
||||||
uint256,
|
uint256,
|
||||||
|
uint256,
|
||||||
uint256
|
uint256
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
|
|
@ -185,7 +185,7 @@ library ValidationLogic {
|
||||||
vars.userBorrowBalanceETH,
|
vars.userBorrowBalanceETH,
|
||||||
vars.currentLtv,
|
vars.currentLtv,
|
||||||
vars.currentLiquidationThreshold,
|
vars.currentLiquidationThreshold,
|
||||||
vars.healthFactor
|
vars.healthFactor,
|
||||||
) = GenericLogic.calculateUserAccountData(
|
) = GenericLogic.calculateUserAccountData(
|
||||||
userAddress,
|
userAddress,
|
||||||
reservesData,
|
reservesData,
|
||||||
|
@ -263,7 +263,7 @@ library ValidationLogic {
|
||||||
address onBehalfOf,
|
address onBehalfOf,
|
||||||
uint256 stableDebt,
|
uint256 stableDebt,
|
||||||
uint256 variableDebt
|
uint256 variableDebt
|
||||||
) internal view {
|
) external view {
|
||||||
(bool isActive, , , , bool isPaused) = reserveCache.reserveConfiguration.getFlagsMemory();
|
(bool isActive, , , , bool isPaused) = reserveCache.reserveConfiguration.getFlagsMemory();
|
||||||
require(isActive, Errors.VL_NO_ACTIVE_RESERVE);
|
require(isActive, Errors.VL_NO_ACTIVE_RESERVE);
|
||||||
require(!isPaused, Errors.VL_RESERVE_PAUSED);
|
require(!isPaused, Errors.VL_RESERVE_PAUSED);
|
||||||
|
@ -469,7 +469,7 @@ library ValidationLogic {
|
||||||
return (uint256(Errors.CollateralManagerErrors.PAUSED_RESERVE), Errors.VL_RESERVE_PAUSED);
|
return (uint256(Errors.CollateralManagerErrors.PAUSED_RESERVE), Errors.VL_RESERVE_PAUSED);
|
||||||
}
|
}
|
||||||
|
|
||||||
(, , , , vars.healthFactor) = GenericLogic.calculateUserAccountData(
|
(, , , , vars.healthFactor, ) = GenericLogic.calculateUserAccountData(
|
||||||
user,
|
user,
|
||||||
reservesData,
|
reservesData,
|
||||||
userConfig,
|
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 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
|
||||||
|
@ -516,7 +516,7 @@ library ValidationLogic {
|
||||||
* @param reservesCount The number of available reserves
|
* @param reservesCount The number of available reserves
|
||||||
* @param oracle The price oracle
|
* @param oracle The price oracle
|
||||||
*/
|
*/
|
||||||
function validateWithdrawCollateral(
|
function validateHFAndExposureCap(
|
||||||
address collateral,
|
address collateral,
|
||||||
address from,
|
address from,
|
||||||
mapping(address => DataTypes.ReserveData) storage reservesData,
|
mapping(address => DataTypes.ReserveData) storage reservesData,
|
||||||
|
@ -526,7 +526,7 @@ library ValidationLogic {
|
||||||
address oracle
|
address oracle
|
||||||
) external view {
|
) external view {
|
||||||
DataTypes.ReserveData memory reserve = reservesData[collateral];
|
DataTypes.ReserveData memory reserve = reservesData[collateral];
|
||||||
(, , uint256 ltv, uint256 liquidationThreshold, uint256 healthFactor) =
|
(, , uint256 ltv, uint256 liquidationThreshold, uint256 healthFactor, uint256 uncappedLtv) =
|
||||||
GenericLogic.calculateUserAccountData(
|
GenericLogic.calculateUserAccountData(
|
||||||
from,
|
from,
|
||||||
reservesData,
|
reservesData,
|
||||||
|
@ -536,28 +536,22 @@ library ValidationLogic {
|
||||||
oracle
|
oracle
|
||||||
);
|
);
|
||||||
|
|
||||||
uint256 exposureCap = reserve.configuration.getExposureCapMemory();
|
|
||||||
uint256 totalSupplyAtoken = IERC20(reserve.aTokenAddress).totalSupply();
|
|
||||||
(, , , uint256 reserveDecimals, ) = reserve.configuration.getParamsMemory();
|
|
||||||
|
|
||||||
require(
|
require(
|
||||||
healthFactor >= GenericLogic.HEALTH_FACTOR_LIQUIDATION_THRESHOLD,
|
healthFactor >= GenericLogic.HEALTH_FACTOR_LIQUIDATION_THRESHOLD,
|
||||||
Errors.VL_HEALTH_FACTOR_LOWER_THAN_LIQUIDATION_THRESHOLD
|
Errors.VL_HEALTH_FACTOR_LOWER_THAN_LIQUIDATION_THRESHOLD
|
||||||
);
|
);
|
||||||
|
|
||||||
// exposureCap == 0 means no cap => can withdraw
|
uint256 exposureCap = reserve.configuration.getExposureCapMemory();
|
||||||
// ltv > liquidationThreshold means that there is enough collateral margin => can withdraw
|
|
||||||
// ltv == 0 means all current collaterals have exceeded the exposure cap => can withdraw
|
if (exposureCap != 0) {
|
||||||
// last means that for this asset the cap is not yet exceeded => can withdraw
|
if (ltv < uncappedLtv) {
|
||||||
// else this means the user is trying to withdraw a collateral that has exceeded the exposure cap, and that it
|
uint256 totalSupplyAtoken = IERC20(reserve.aTokenAddress).totalSupply();
|
||||||
// as other collaterals available to withdraw: he must withdraw from other collateral reserves first
|
(, , , uint256 reserveDecimals, ) = reserve.configuration.getParamsMemory();
|
||||||
require(
|
bool isAssetCapped = totalSupplyAtoken.div(10**reserveDecimals) >= exposureCap;
|
||||||
exposureCap == 0 ||
|
require(isAssetCapped, Errors.VL_COLLATERAL_EXPOSURE_CAP_EXCEEDED);
|
||||||
ltv > liquidationThreshold ||
|
}
|
||||||
ltv == 0 ||
|
}
|
||||||
totalSupplyAtoken.div(10**reserveDecimals) < exposureCap,
|
|
||||||
Errors.VL_COLLATERAL_EXPOSURE_CAP_EXCEEDED
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue
Block a user