Antler by Autoflux

Liquidation

Handles undercollateralised position auctions and bad-debt socialisation.

Path: liquidation

Third-party documentation. This is independently authored analysis of the public Aurum Protocol codebase — not the official docs, and not reviewed or endorsed by the Aurum Protocol team.

Liquidation Module

When a user's health-factor drops below 1.0, their position is eligible for liquidation. Any external keeper holding LIQUIDATOR_ROLE can trigger the auction.

Auction Mechanics

  1. Keeper calls liquidate(borrower, asset, repayAmount)
  2. Protocol repays up to 50% of the borrower's debt on their behalf
  3. Borrower's collateral is seized at a 5% discount (liquidation bonus)
  4. If collateral is insufficient to cover debt (bad debt), the shortfall is socialised across the insurance fund

Health Factor Formula

HF = Σ(collateral_i × collateralFactor_i) / totalDebt

A position is safe when HF ≥ 1.0. Liquidation is available when HF < 1.0. The protocol applies a 5% liquidation bonus to incentivise keepers.

Bad Debt

If a position's collateral value is less than its outstanding debt (e.g. due to a rapid price crash), the shortfall is covered by the protocol's insurance buffer held in the Treasury module. If the buffer is exhausted, the loss is socialised pro-rata among liquidity providers.

Examples

Keeper bot liquidation loop

Keeper bot liquidation loop
typescript
async function runKeeperLoop(users: string[]) {
for (const user of users) {
const liquidatable = await liquidation.isLiquidatable(user);
if (!liquidatable) continue;
 
const vault = await core.getVault(user);
const repayAmt = vault.debt / 2n; // max 50%
 
const seized = await liquidation.callStatic.liquidate(user, USDC_ADDRESS, repayAmt);
console.log(`Seizing ${ethers.formatEther(seized)} collateral`);
 
await liquidation.liquidate(user, USDC_ADDRESS, repayAmt);
}
}
STATUSexample

A basic keeper loop that checks all tracked users and liquidates eligible positions.

Edge Cases

  • liquidate() reverts if health-factor ≥ 1.0 at the time of execution (front-run protection)
  • repayAmount is capped at 50% of outstanding debt per transaction to prevent full liquidations
  • If collateral is zero (full bad debt), the function succeeds but collateralSeized returns 0
  • Liquidation bonus is applied in collateral asset terms, not USD — fast-moving prices can erode the incentive

Interface

Interface
solidity
interface ILiquidation {
/// @notice Liquidate up to repayAmount of borrower's debt
/// @param borrower Address of the undercollateralised user
/// @param asset Debt asset to repay
/// @param repayAmount Amount of debt to repay (max 50% of total)
function liquidate(
address borrower,
address asset,
uint256 repayAmount
) external returns (uint256 collateralSeized);
 
/// @notice Returns true when a position is eligible for liquidation
function isLiquidatable(address user) external view returns (bool);
 
/// @notice Current liquidation bonus (1e18 = 100%, e.g. 1.05e18 = 5% bonus)
function liquidationBonus() external view returns (uint256);
 
event Liquidated(
address indexed liquidator,
address indexed borrower,
address asset,
uint256 debtRepaid,
uint256 collateralSeized
);
}
 
STATUSinterface