Liquidations
The health factor is a critical metric within the Aave Protocol that measures the safety of a borrow position. It is calculated as:
Health Factor = (Total Collateral Value * Weighted Average Liquidation Threshold) / Total Borrow Value
The health factor measures a borrow position’s stability. A health factor below 1 risks liquidation. The liquidation threshold, set by Aave Governance for each asset, determines the maximum percentage of value that can be borrowed against the asset. For example, if a user supplies $10,000 in ETH with an 80% liquidation threshold and borrows $6,000 in GHO, the health factor would be 1.333.
A health factor above 1 represents a position that is above the liquidation threshold. Regular monitoring is essential, as the health factor fluctuates based on both the value of collateral and borrowed assets. To improve the health factor, users can either supply more collateral or repay part of the borrow position. The health factor is directly tied to collateral value. If the value rises, the health factor improves; if it falls, the health factor declines, increasing the risk of liquidation.
Liquidation happens when a borrower's health factor drops below 1, meaning their collateral is insufficient to cover the borrowed amount. This can occur when the value of collateral decreases or the borrowing amount is increased. When a liquidation occurs, up to 50% of the borrower's debt is repaid by a liquidator. A liquidation fee is also levied against the borrower's collateral. Liquidations are permissionless, meaning any participant within the network can initiate the liquidation of an eligible borrow position.
Liquidations are highly competitive, requiring a deep understanding of the protocol and technical proficiency. Liquidators closely monitor borrow positions, react swiftly to market changes, and prioritise liquidation transactions to be the first to execute the liquidation.
When the 'health factor' of an account's total loans is below 1, anyone can make a liquidationCall() to the Pool or L2Pool (in case of L2 rollup networks) contract, pay back part of the debt owed and receive discounted collateral in return (also known as the liquidation bonus).
This incentivises third parties to participate in the health of the overall protocol, by acting in their own interest (to receive the discounted collateral) and as a result, preserve that borrows are sufficiently collateralized.
There are multiple ways to participate in liquidations:
For liquidation calls to be profitable, you must take into account the gas cost involved in liquidating the loan. If a high gas price is used, then the liquidation may be unprofitable for you. See the Calculating profitability section for more details.
V3 allows 100% of debt (i.e. MAX_LIQUIDATION_CLOSE_FACTOR) to be liquidated in single liquidationCall() if HF < CLOSE_FACTOR_HF_THRESHOLD
Prerequisites
When making a liquidationCall(), you must:
Know the account (i.e. the ethreum address: user) whose health factor is below 1.
- Know the valid debt amount and asset (i.e. debtToCover & debtAsset)
If the HF is above CLOSE_FACTOR_HF_THRESHOLD, then only a maximum of 50% (i.e. DEFAULT_LIQUIDATION_CLOSE_FACTOR) of the debt can be liquidated per valid liquidationCall()
If the HF is below CLOSE_FACTOR_HF_THRESHOLD, then 100% (i.e. MAX_LIQUIDATION_CLOSE_FACTOR) of the debt can be liquidated in single valid liquidationCall()
You can set the debtToCover to uint(-1) and the protocol will proceed with the highest possible liquidation allowed by the close factor.
You must already have sufficient balance of the debt asset, which will be used by the liquidationCall to pay back the debt. You can use flashLoan for liquidations 😉
Know the collateral asset collateralAsset you closing, i.e. the asset that the user has backing their outstanding loan that you will receive as a bonus.
Whether you want to receive aTokens or the underlying asset after a successful liquidationCall() .
Getting accounts to liquidate
"User Account" in the Aave Protocol refer to a single ethereum address that has interacted with the protocol. This can be an externally owned account or contract.
Only user accounts that have HF < 1 can be liquidated. There are multiple ways you can get the health factor:
Onchain
- To gather user account data from on-chain data, one way would be to monitor emitted events from the protocol and keep an up to date index of user data locally.
Events are emitted each time a user interacts with the protocol (supply, borrow, repay, withdraw etc.)
When you have the user's address, you can simply call getUserAccountData(), to read the user's current healthFactor. If the HF < 1, then the account can be liquidated.
GraphQL
Similarly to the sections above you will need to gather user account data and keep an index of the user data locally.
SInce GraphQL does not provide real time calculated user data such as healthFactor, you will need to compute this locally. The easiest way is to use the Aave Utilities sdk, which has methods to compute user summary data.
Executing the liquidation call
Once you have the account(s) to liquidate, you will need to calculate the amount of collateral that can be liquidated:
- Max debt that be cleared by single liquidation call is given by the DEFAULT_LIQUIDATION_CLOSE_FACTOR(when CLOSE_FACTOR_HF_THRESHOLD < HF < 1) or MAX_LIQUIDATION_CLOSE_FACTOR (when HF < CLOSE_FACTOR_HF_THRESHOLD)
debtToCover = (userVariableDebt) * LiquidationCloseFactor
You can pass uint(-1), i.e. MAX_UINT, as the debtToCover to liquidate the maximum amount allowed.
- Max amount of collateral that can be liquidated to cover debt is given by the current liquidationBonus for the reserves that have usageAsCollateralEnabled as true.
maxAmountOfCollateralToLiquidate = (debtAssetPrice * debtToCover * liquidationBonus)/ collateralPrice
Calculating profitability vs gas cost
One way to calculate the profitability is the following:
Store and retrieve each collateral's relevant details such as address, decimals used and liquidation bonus.
Get the user's collateral balance (aTokenBalance).
Get the asset's price according to the Aave's oracle contract using getAssetPrice().
The maximum collateral bonus received on liquidation is given by the maxAmountOfCollateralToLiquidate * (1 - liquidationBonus) * collateralAssetPriceEth
The maximum cost of your transaction will be you gas price multiplied by the amount of gas used. You should be able to get a good estimation of the gas amount used by calling estimateGas via your web3 provider.
Your approximate profit will be the value of the collateral bonus (4) minus the cost of your transaction (5).
Appendix
How is health factor calculated?
The health factor is calculated from the user's total collateral, i.e. all reserves for which usageAsCollateral is enabled, balance (in ETH) multiplied by the liquidation threshold percentage for all the user's outstanding assets, divided by the user's total borrow balance across all reserves (in ETH).
This can be calculated both off-chain and on-chain, see Aave Utilities and GenericLogic Library respectively for reference.
How is liquidation bonus determined?
Liquidation bonuses for all the assets are evaluated and determined based on each asset's liquidity risk and updated via Aave Governance process.