Skip to main content

Liquidation paths

When a trove falls under MCR (or under TCR in recovery mode), it's liquidatable. The protocol always tries to clear undercollateralized debt within the block it's discovered, using two paths in order. This page covers the on-chain mechanics. User view is Liquidations & Recovery Mode.

The branch contracts involved: Liquidations, StabilityPool, Rewards, DefaultPool, ActivePool / ActiveShieldedPool, CollSurplusPool, GasPool, SortedTroves.

Entry points

Liquidations.liquidate(address _borrower)
Liquidations.liquidateTroves(uint _n)
Liquidations.batchLiquidate(address[] _borrowers)

liquidate is a one-off. liquidateTroves walks the bottom of the unshielded sorted list and clears up to _n troves whose ICR is below MCR (or below TCR in recovery mode). batchLiquidate clears a caller-supplied list.

All three require the branch oracle to be healthy (!priceFeed.previewWillShutdown(false)). If the branch oracle is failing, the branch must be shut down via BorrowerOperations.shutdownFromOracleFailure() instead.

The two paths

1. Offset against the Stability Pool

If the branch's StabilityPool has enough RD to cover the trove's debt, the protocol offsets in full:

SP burns:   trove.netDebt RD from depositor balances (pro-rata)
SP gains: collateral worth (trove.netDebt × par × LIQUIDATION_PENALTY / oracle_price)
where LIQUIDATION_PENALTY ≈ 1.05 (= 5% kicker to depositors)
(per-branch parameter, typical 105%)

LIQUIDATION_PENALTY is the multiplier that determines how much collateral the SP receives. At 1.05, depositors get collateral worth 105% of the burned debt's par value (capped of course by the trove's actual collateral). The 5% spread is depositor profit.

The remainder of the trove's collateral (if any) is the "surplus", the borrower can claim it via BorrowerOperations.claimCollateral().

2. Redistribution

If the SP is empty or under-funded, the residual debt and collateral are redistributed to other troves on the branch:

DefaultPool receives:
trove.remaining_coll × LIQUIDATION_PENALTY_REDIST / 1e18
trove.remaining_debt
where LIQUIDATION_PENALTY_REDIST ≈ 1.10 (= 10% spread)
(per-branch parameter, typical 110%)

Every other active trove on the branch inherits a pro-rata slice of the DefaultPool balance. The redistribution accumulators (L_RDDebt, L_Collateral) are updated.

On any future state-touching call (open, adjust, close, liquidate) of an active trove, Rewards.applyPendingRewards(...) settles the trove's slice: adding the inherited collateral and debt to its position.

Mixed liquidations

If the SP has some RD but not enough, the protocol splits:

SP_RD  = stabilityPool.balance
SP_offset = trove.debt that SP can absorb
redistribute = trove.debt - SP_offset

offset: SP burns SP_offset RD, gets coll worth (SP_offset × penalty / price)
redist: DefaultPool gets (trove.coll - SP_coll_seized) × redist_penalty

The mixed path is gas-heavier but produces the same end state: trove closed, debt cleared, collateral allocated between SP depositors and surviving troves.

Gas compensation

Every active trove holds RD_GAS_COMPENSATION = 200 RD in the protocol's GasPool. On liquidation, the protocol pays this to the liquidator (the EOA or contract that triggered the call) in two parts:

  • 200 RD from GasPool: denominated in stable, predictable.
  • A small collateral kicker: _gasCompensation() returns min(0.5%, trove.coll × 0.5%), a few tenths of a percent of the trove's collateral, paid in branch collateral.

The kicker exists so the liquidator can pay tx gas in the collateral's native token if needed; the 200 RD covers the gas economics of a normal liquidation.

Recovery mode rules

Branch TCR is computed once per liquidation batch. If TCR < CCR (typically 150%), the branch is in recovery mode and rules change:

  • Liquidatable troves expand. Any trove with ICR < TCR (not just ICR < MCR) becomes liquidatable. The protocol prioritizes restoring TCR.
  • Capped collateral seizure. When liquidating above-MCR troves in recovery mode, the SP / redistribution can't claim more collateral than _maxPenaltyColl(debt, par, penalty, price) allows, the rest goes to the borrower as surplus.
  • Order matters. Recovery-mode batches walk troves in ascending ICR order; the bottom of the list clears first.

Recovery mode ends as soon as TCR is back above CCR. There's no manual intervention.

Liquidating shielded troves

The shielded sorted list is not walked for routine liquidateTroves(_n) calls, those walk the unshielded list. Shielded liquidations happen via:

  • liquidate(address), explicit one-off.
  • batchLiquidate([...]), caller-supplied list including shielded addresses.

So a shielded trove that goes under MCR sits unliquidated until a keeper notices and calls liquidate on it directly. The shield doesn't prevent liquidation; it just isolates the trove from the redemption walk and from the "clear from the bottom" liquidation batch.

Mini-dwarf sweeps

A trove can become a mini-dwarf through redistribution, pending rewards push its effective debt below the practical threshold for clean liquidation. Mini-dwarfs are:

  • Not walked for redemption (skipped).
  • Cleaned up via dedicated sweep paths when discovered (typically by a redemption or liquidation that crosses them).
  • Their residual collateral goes to CollSurplusPool for the owner to claim.

The full picture

                ┌─────────────────────────────────────┐
│ Liquidations.liquidate │
└──────────────┬──────────────────────┘

apply pending redistribution rewards

check ICR vs threshold

┌──────────────┴──────────────┐
▼ ▼
SP has enough RD? SP empty / partial
│ │
▼ ▼
Offset path: Mixed / redistribute:
burn RD, SP takes what it can,
seize coll, DefaultPool takes the rest,
pay liquidator, Rewards updates accumulators,
surplus → CollSurplus pay liquidator
│ │
└──────────────┬──────────────┘

SortedTroves.remove(trove)
GasPool → liquidator (200 RD)

Why this design

  • SP is the preferred path. Burning RD against the pool removes the debt outright. Redistribution just spreads it, which eventually has to be cleared too.
  • The redistribution penalty is higher. Pulling collateral via redistribution is more expensive for the borrower (10% vs 5%) because it imposes work on the rest of the branch.
  • The protocol prefers to clear right now. That's why recovery mode aggressively widens what's liquidatable, solvency before borrower convenience.
  • Gas compensation is denominated in RD, not collateral. RD's value is more predictable than collateral's, so liquidator economics are more stable.

Deep dive