Liquidations in the Borrowing Module
Tutorial to participate in liquidations in Angle Borrowing Module
Last updated
Was this helpful?
Tutorial to participate in liquidations in Angle Borrowing Module
Last updated
Was this helpful?
The health of Angle Protocol borrowing module is dependent on the health of the positions (or vaults) within the system, also known as the health factor. When the health factor of a vault is below 1, anyone can make a liquidate
call to the VaultManager
contract where the vault is, paying back a portion of the debt owed by the vault and receiving discounted collateral in return.
This incentivises third parties to participate in the health of the overall protocol, by acting on their own interest (to receive the discounted collateral) and as a result, ensure AgTokens in circulation from this module are sufficiently collateralised.
This contains an implementation example of how to liquidate in the Borrowing module.
Liquidations are quite-common in DeFi. There are however some peculiarities within the Angle system liquidators should have in mind before engaging with the Angle Protocol:
It is possible to liquidate multiple positions/vaults in just one transaction with Angle. If different positions of the same VaultManager
can be liquidated, then both of them can liquidated in one transaction with just one stablecoin transfer from the liquidator and collateral transfer to it.
Liquidations have been designed to be capital-efficient meaning that you can liquidate with no upfront capital: discounted collateral is given first to the liquidator which can in the same transaction swap it to stablecoins to then repay the debt. This is however an optional feature and liquidators could proceed as they normally do in other protocols.
The protocol proposes two different liquidation interfaces for liquidators: one that lets them specify a contract address and data to process a swap if needed, and one which enables them to proceed without this logic. The two different options correspond to the two different liquidate
functions in the VaultManager
contract.
Discount given to liquidators is not fixed and is a dynamic variable of the health ratio of a vault. Basically the smaller a health ratio, the bigger the discount of a liquidator is.
When making a liquidate()
call, you must:
Know the vaults (i.e. the uint256
defining the ID of vaults) which health factor are below 1.
Know the VaultManager
(that is the contract corresponding to a collateral type-stablecoin pair in Angle Borrowing Module) in which liquidation should take place: this is the contract in which you will have to call the liquidate
function
Choose if you want to swap the collateral obtained from liquidations to stablecoins using some sort of Swapper
contract or directly bring the stablecoins to repay. In the first case, you may want to look at our guide to see how to use Swapper
contract in your Angle execution flow.
Know the amount of stablecoins you want to repay in these vaults. There are several ways in which you can estimate this. The optimal way is to rely on the function checkLiquidation
defined in each VaultManager
contract. When called on a given vaultID
that is liquidable, this function returns several elements which can be used in a subsequent liquidation call:
maxStablecoinAmountToRepay
: Maximum stablecoin amount that can be repaid by liquidators upon liquidating the vault
maxCollateralAmountToGive
: This is the amount of collateral you would receive if you were to repay maxStablecoinAmountToRepay
thresholdRepayAmount
: For some vaults, if liquidators were to liquidate a certain portion of their debt, then these vaults may end up with a "dusty" amount of debt of collateral in it. The protocol prevents liquidators from putting vaults in situations like that. As such, a non-null thresholdRepayAmount
means that you can repay an amount of the debt either smaller to this thresholdRepayAmount
or exactly equal to the maxStablecoinAmountToRepay
discount
: Discount you will get on the oracle value price of the collateral
currentDebt
: Total amount of debt in the vault
These values may vary in time, as such if you're running a smart contract you may want to embed your call to checkLiquidation
in the same transaction as the liquidate
call. If you're not sure about the maxStablecoinAmountToRepay
, the protocol will round the amount
value you pass in the liquidation function to the maxStablecoinAmountToRepay
if it is superior to the thresholdRepayAmount
in case it is not null or to the maxStablecoinAmountToRepay
.
Only vaults that have a health factor below 1 can be liquidated. There are multiple ways you can get the health factor of a vault.
The easiest way to identify liquidable vaults is to call in a given VaultManager
contract checkLiquidation
for all existing vaults (you may simply iterate over the vaultIDCount
variable to get all these vaults). Since this just requires repeatedly calling a view function, it does not incur any cost.
As explained above, There are two functions that you can call to liquidate:
And:
Upon choosing the amount of debt of a vault you want to repay, you have the possibility to specify a from
address from which stablecoins should be taken. This address should have approved for the stablecoin the address used to trigger the liquidation. You can also specify a to
address to which collateral will be sent.
In the second option, you can specify a who
contract as well as some data
to swap the obtained collateral for stablecoins (or just a portion of it to minimize slippage) efficiently.
If you are using a smart contract to liquidate, then you may want to process the results obtained from the liquidation you performed. You basically get different returned values:
stablecoinAmountToReceive
: This is the amount of stablecoins you have given for the liquidation
collateralAmountToGive
: Current amount of collateral you've gotten from the contract
Note that these returned values are denominated from a protocol perspective and they could be named differently. The contract also returns some utility values which may be less useful to the liquidator:
badDebtFromLiquidation
: Bad debt accrued across the liquidation process
oracleValue
: Oracle value at which the liquidation took place
newInterestAccumulator
: Value of the interestAccumulator
at the time of the call (this is a value used to track vaults outstanding debt)
Depending on your environment, preferred programming tools and languages, your bot should:
Ensure it has enough (or access to enough) funds when liquidating or that it is able to correctly swap the collateral obtained for stablecoins
Calculate the profitability of liquidating loans vs gas costs, taking into account the most lucrative collateral to liquidate.
Ensure it has access to the latest protocol data.
Have the usual fail safes and security you'd expect for any production service.
Calculating profitability vs gas cost.
Be able to estimate slippage in the case where collateral is swapped for stablecoins (or used to mint stablecoins).
The health factor of a vault is computed from the vault's collateral amount (in stablecoin value) multiplied by the current collateral factor divided by the vault's current debt. This debt can be obtained on-chain by querying the function: getVaultDebt
.
The forumula for the health factor is then the following:
To get the necessary values, you can do the following:
The liquidation discount given to liquidators is a function of the health factor of the liquidated vault.
This discount is always capped by a maximum discount value defined in each VaultManager
contract.
Angle Protocol uses Chainlink as a price oracle. You may find the list of oracle contracts used .