Skip to content

Commit

Permalink
Merge pull request #154 from aave/feat/liquidation-close-factor
Browse files Browse the repository at this point in the history
Feat/liquidation close factor
  • Loading branch information
The-3D authored Oct 18, 2021
2 parents f16034b + 1093b58 commit 7827d17
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 43 deletions.
2 changes: 0 additions & 2 deletions contracts/protocol/libraries/logic/GenericLogic.sol
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@ library GenericLogic {
using ReserveConfiguration for DataTypes.ReserveConfigurationMap;
using UserConfiguration for DataTypes.UserConfigurationMap;

uint256 public constant HEALTH_FACTOR_LIQUIDATION_THRESHOLD = 1 ether;

struct CalculateUserAccountDataVars {
uint256 assetPrice;
uint256 assetUnit;
Expand Down
38 changes: 25 additions & 13 deletions contracts/protocol/libraries/logic/LiquidationLogic.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {Errors} from '../../libraries/helpers/Errors.sol';
import {DataTypes} from '../../libraries/types/DataTypes.sol';
import {ReserveLogic} from '../../libraries/logic/ReserveLogic.sol';
import {ValidationLogic} from '../../libraries/logic/ValidationLogic.sol';
import {GenericLogic} from '../../libraries/logic/GenericLogic.sol';
import {UserConfiguration} from '../../libraries/configuration/UserConfiguration.sol';
import {ReserveConfiguration} from '../../libraries/configuration/ReserveConfiguration.sol';
import {IAToken} from '../../../interfaces/IAToken.sol';
Expand Down Expand Up @@ -45,7 +46,9 @@ library LiquidationLogic {
bool receiveAToken
);

uint256 internal constant LIQUIDATION_CLOSE_FACTOR_PERCENT = 5000;
uint256 internal constant DEFAULT_LIQUIDATION_CLOSE_FACTOR = 5000;
uint256 public constant MAX_LIQUIDATION_CLOSE_FACTOR = 10000;
uint256 public constant CLOSE_FACTOR_HF_THRESHOLD = 0.95 * 1e18;

struct LiquidationCallLocalVars {
uint256 userCollateralBalance;
Expand All @@ -57,13 +60,12 @@ library LiquidationLogic {
uint256 debtAmountNeeded;
uint256 liquidatorPreviousATokenBalance;
uint256 liquidationBonus;
uint256 healthFactor;
uint256 liquidationProtocolFeeAmount;
uint256 closeFactor;
IAToken collateralAtoken;
IPriceOracleGetter oracle;
bool isCollateralEnabled;
uint256 errorCode;
string errorMsg;
DataTypes.ReserveCache debtReserveCache;
uint256 liquidationProtocolFeeAmount;
}

/**
Expand All @@ -84,35 +86,47 @@ library LiquidationLogic {
DataTypes.ReserveData storage debtReserve = reserves[params.debtAsset];
DataTypes.UserConfigurationMap storage userConfig = usersConfig[params.user];
vars.debtReserveCache = debtReserve.cache();
debtReserve.updateState(vars.debtReserveCache);

(vars.userStableDebt, vars.userVariableDebt) = Helpers.getUserCurrentDebt(
params.user,
debtReserve
);
vars.oracle = IPriceOracleGetter(params.priceOracle);

ValidationLogic.validateLiquidationCall(
(, , , , vars.healthFactor, ) = GenericLogic.calculateUserAccountData(
reserves,
reservesList,
eModeCategories,
DataTypes.CalculateUserAccountDataParams(
userConfig,
params.reservesCount,
params.user,
params.priceOracle,
params.userEModeCategory
)
);

ValidationLogic.validateLiquidationCall(
userConfig,
collateralReserve,
DataTypes.ValidateLiquidationCallParams(
vars.debtReserveCache,
vars.userStableDebt + vars.userVariableDebt,
params.user,
params.reservesCount,
params.priceOracle,
params.userEModeCategory,
vars.healthFactor,
params.priceOracleSentinel
)
);

vars.collateralAtoken = IAToken(collateralReserve.aTokenAddress);
vars.userCollateralBalance = vars.collateralAtoken.balanceOf(params.user);

vars.closeFactor = vars.healthFactor > CLOSE_FACTOR_HF_THRESHOLD
? DEFAULT_LIQUIDATION_CLOSE_FACTOR
: MAX_LIQUIDATION_CLOSE_FACTOR;

vars.maxLiquidatableDebt = (vars.userStableDebt + vars.userVariableDebt).percentMul(
LIQUIDATION_CLOSE_FACTOR_PERCENT
vars.closeFactor
);

vars.actualDebtToLiquidate = params.debtToCover > vars.maxLiquidatableDebt
Expand Down Expand Up @@ -146,8 +160,6 @@ library LiquidationLogic {
vars.actualDebtToLiquidate = vars.debtAmountNeeded;
}

debtReserve.updateState(vars.debtReserveCache);

if (vars.userVariableDebt >= vars.actualDebtToLiquidate) {
vars.debtReserveCache.nextScaledVariableDebt = IVariableDebtToken(
vars.debtReserveCache.variableDebtTokenAddress
Expand Down
29 changes: 5 additions & 24 deletions contracts/protocol/libraries/logic/ValidationLogic.sol
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ library ValidationLogic {
uint256 public constant REBALANCE_UP_LIQUIDITY_RATE_THRESHOLD = 4000;
uint256 public constant REBALANCE_UP_USAGE_RATIO_THRESHOLD = 0.95 * 1e27; //usage ratio of 95%
uint256 public constant MINIMUM_HEALTH_FACTOR_LIQUIDATION_THRESHOLD = 0.95 * 1e18;
uint256 public constant HEALTH_FACTOR_LIQUIDATION_THRESHOLD = 1e18;

// for borrowings in isolation mode, we give for granted that the eMode category for stablecoins is the category with id 1.
// this MUST be kept into account when configuring the stablecoins eMode category, otherwise users depositing asset in isolation
Expand Down Expand Up @@ -234,7 +235,7 @@ library ValidationLogic {
require(vars.userCollateralInBaseCurrency > 0, Errors.VL_COLLATERAL_BALANCE_IS_0);

require(
vars.healthFactor > GenericLogic.HEALTH_FACTOR_LIQUIDATION_THRESHOLD,
vars.healthFactor > HEALTH_FACTOR_LIQUIDATION_THRESHOLD,
Errors.VL_HEALTH_FACTOR_LOWER_THAN_LIQUIDATION_THRESHOLD
);

Expand Down Expand Up @@ -477,7 +478,6 @@ library ValidationLogic {
}

struct ValidateLiquidationCallLocalVars {
uint256 healthFactor;
bool collateralReserveActive;
bool collateralReservePaused;
bool principalReserveActive;
Expand All @@ -487,17 +487,11 @@ library ValidationLogic {

/**
* @notice Validates the liquidation action
* @param reservesData The mapping of the reserves data
* @param reserves The list of the reserves
* @param eModeCategories The mapping of the eMode categories
* @param userConfig The user configuration mapping
* @param collateralReserve The reserve data of the collateral
* @param params Additional parameters needed for the validation
*/
function validateLiquidationCall(
mapping(address => DataTypes.ReserveData) storage reservesData,
mapping(uint256 => address) storage reserves,
mapping(uint8 => DataTypes.EModeCategory) storage eModeCategories,
DataTypes.UserConfigurationMap storage userConfig,
DataTypes.ReserveData storage collateralReserve,
DataTypes.ValidateLiquidationCallParams memory params
Expand All @@ -522,28 +516,15 @@ library ValidationLogic {
Errors.VL_RESERVE_PAUSED
);

(, , , , vars.healthFactor, ) = GenericLogic.calculateUserAccountData(
reservesData,
reserves,
eModeCategories,
DataTypes.CalculateUserAccountDataParams(
userConfig,
params.reservesCount,
params.user,
params.oracle,
params.userEModeCategory
)
);

require(
params.priceOracleSentinel == address(0) ||
vars.healthFactor < MINIMUM_HEALTH_FACTOR_LIQUIDATION_THRESHOLD ||
params.healthFactor < MINIMUM_HEALTH_FACTOR_LIQUIDATION_THRESHOLD ||
IPriceOracleSentinel(params.priceOracleSentinel).isLiquidationAllowed(),
Errors.VL_PRICE_ORACLE_SENTINEL_CHECK_FAILED
);

require(
vars.healthFactor < GenericLogic.HEALTH_FACTOR_LIQUIDATION_THRESHOLD,
params.healthFactor < HEALTH_FACTOR_LIQUIDATION_THRESHOLD,
Errors.VL_HEALTH_FACTOR_NOT_BELOW_THRESHOLD
);

Expand Down Expand Up @@ -581,7 +562,7 @@ library ValidationLogic {
);

require(
healthFactor >= GenericLogic.HEALTH_FACTOR_LIQUIDATION_THRESHOLD,
healthFactor >= HEALTH_FACTOR_LIQUIDATION_THRESHOLD,
Errors.VL_HEALTH_FACTOR_LOWER_THAN_LIQUIDATION_THRESHOLD
);

Expand Down
5 changes: 1 addition & 4 deletions contracts/protocol/libraries/types/DataTypes.sol
Original file line number Diff line number Diff line change
Expand Up @@ -222,10 +222,7 @@ library DataTypes {
struct ValidateLiquidationCallParams {
DataTypes.ReserveCache debtReserveCache;
uint256 totalDebt;
address user;
uint256 reservesCount;
address oracle;
uint8 userEModeCategory;
uint256 healthFactor;
address priceOracleSentinel;
}

Expand Down

0 comments on commit 7827d17

Please sign in to comment.