The liquidation process is a critical safety mechanism that maintains protocol solvency by automatically liquidating undercollateralized positions. When a user's health factor falls below 1.0, liquidators can repay part of their debt in exchange for discounted collateral, ensuring the protocol remains properly collateralized.
Liquidation Triggers
Health Factor Threshold
Liquidation is triggered when a user's health factor drops below 1.0:
Health Factor = (Collateral Value × Liquidation Threshold) / Debt Value
Liquidation Conditions:
Health Factor < 1.0: Position becomes liquidatable
Health Factor ≥ 1.0: Position is safe from liquidation
Example Liquidation Scenario
Initial Position:
User deposits 10 ETH at $3,000 = $30,000 collateral
function liquidate(
address collateralAsset, // Asset to seize (ETH, LINK)
address debtAsset, // Asset to repay (EURC)
uint256 debtAmount, // Amount of debt to repay
address from // User being liquidated
) external nonReentrant;
1. Liquidator calls liquidate()
2. Protocol validates liquidation conditions
3. Protocol calculates collateral to seize
4. Liquidator transfers debt tokens to protocol
5. Protocol burns debt tokens from user
6. Protocol transfers collateral to liquidator
7. User's position is improved
// Check assets are valid
require(collateralAssetList.contains(collateralAsset), "Invalid collateral");
require(debtAssetList.contains(debtAsset), "Invalid debt asset");
// Check assets not paused
require(!collateralConfig.isPaused, "Collateral paused");
require(!debtConfig.isPaused, "Debt asset paused");
// Verify user is liquidatable
UserAccountData memory userData = getUserAccountData(from);
require(userData.healthFactor < HEALTH_FACTOR_BASE, "Not liquidatable");
// Limit to 50% of user's debt for this asset
uint256 userDebtBalance = IERC20(debtToken).balanceOf(from);
uint256 maxLiquidatable = userDebtBalance / 2;
if (debtAmount > maxLiquidatable) {
debtAmount = maxLiquidatable;
}
// Get prices from oracle
uint256 debtPrice = oracleManager.getAssetPrice(debtAsset);
uint256 collateralPrice = oracleManager.getAssetPrice(collateralAsset);
// Calculate USD value of debt being repaid
uint256 debtValueUSD = (debtAmount * debtPrice) / 10**debtDecimals;
// Apply liquidation bonus
uint256 bonusValue = (debtValueUSD * liquidationBonus) / 10000;
// Convert to collateral amount
uint256 collateralAmount = (bonusValue * 10**collateralDecimals) / collateralPrice;
// Transfer debt from liquidator to protocol
IERC20(debtAsset).safeTransferFrom(liquidator, colEUR, debtAmount);
// Burn debt tokens from liquidated user
IDebtEUR(debtToken).burn(from, debtAmount);
// Burn collateral tokens from user
IColToken(colToken).burn(from, collateralAmount);
// Transfer collateral to liquidator
IVault(vault).unlockCollateral(liquidator, collateralAmount);
liquidationThreshold: 8500, // 85% - liquidation trigger
liquidationBonus: 10500, // 105% - 5% discount to liquidators
liquidationProtocolFee: 1000, // 10% of bonus goes to protocol
liquidationThreshold: 7500, // 75% - liquidation trigger
liquidationBonus: 11000, // 110% - 10% discount to liquidators
liquidationProtocolFee: 1000, // 10% of bonus goes to protocol
Total Liquidation Bonus = Debt Repaid × (Liquidation Bonus - 100%)
Liquidator Receives = Total Bonus × (100% - Protocol Fee%)
Protocol Receives = Total Bonus × Protocol Fee%