Liquidations
The health of Bend is dependent on the 'health' of the positions within the protocol, also known as the 'health factor'. When the 'health factor' of an account's total loans is below 1, anyone can make a liquidationCall() to the Pool
contract, pay back part of the debt owed and receive discounted collateral in return (also known as the liquidation bonus).
This incentivizes 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, ensure borrows are sufficiently collateralized.
There are multiple ways to participate in liquidations:
- By calling the liquidationCall() directly in the
Pool
contract. - By creating your own automated bot or system to liquidate loans.
WARNING
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.
TIP
Bend protocol allows 100% of debt (i.e. MAX_LIQUIDATION_CLOSE_FACTOR
) to be liquidated in single liquidationCall()
if: HF < CLOSE_FACTOR_HF_THRESHOLD
Before Making Liquidation Call
When making a liquidationCall(), you must:
Know the account (i.e. the ethereum 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 validliquidationCall()
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 validliquidationCall()
You can set the
debtToCover
touint(-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.
Know the collateral asset
collateralAsset
you are closing, i.e. the asset that the user hasbacking
their outstanding loan that you will receive as abonus
.Whether you want to receive aTokens or the underlying asset after a successful
liquidationCall()
.
Getting Accounts to Liquidate
Only accounts with HF < 1
can be liquidated. To get a user's health factor on-chain:
- 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.
- Call
getUserAccountData
to see if the current user'sHF < 1
, meeting the liquidation criteria.
Liquidation Example
//Note: Please don't treat this code as a working solution and the usage should be more as a "template" to suit your specific needs.
import { ethers } from "ethers";
// connect to Berachain using the provided rpc url
const provider = new ethers.providers.JsonRpcProvider(
"https://bartio.rpc.berachain.com/"
);
// replace with your wallet's private key
const signer = new ethers.Wallet("YOUR_PRIVATE_KEY", provider);
// addresses for the contracts and assets involved
const poolAddress = "0x30A3039675E5b5cbEA49d9a5eacbc11f9199B86D"; // pool contract address on bArtio
const collateralAssetAddress = "0xCollateralAssetAddress"; // replace with the actual collateral asset address
const debtAssetAddress = "0xDebtAssetAddress"; // replace with the actual debt asset address
const userAddress = "0xUserAddress"; // address of the user whose loan is being liquidated
// the amount of debt we want to cover (for this example, 1000 $honey)
const debtToCover = ethers.utils.parseUnits("1000.0", 18);
// abi for the pool contract, focusing on the liquidationCall function
const poolAbi = [
"function liquidationCall(address collateralAsset, address debtAsset, address user, uint256 debtToCover, bool receiveAToken) external",
];
async function liquidateLoan() {
try {
const poolContract = new ethers.Contract(poolAddress, poolAbi, signer);
// perform the liquidation call
const tx = await poolContract.liquidationCall(
collateralAssetAddress, // the collateral asset we want to seize
debtAssetAddress, // the debt asset we're covering
userAddress, // the user whose loan is being liquidated
debtToCover, // amount of debt to cover
false // set to true if you want to receive aTokens instead of the underlying asset
);
await tx.wait();
console.log(
`liquidation performed successfully! transaction hash: ${tx.hash}`
);
} catch (error) {
console.error("there was an error performing the liquidation:", error);
}
}
// run the liquidation function
liquidateLoan();