Skip to main content

Liquidation paths

When a trove falls under MCR, it's liquidatable — MCR is the only liquidation threshold, in every mode. The protocol always tries to clear undercollateralized debt within the block it's discovered, using two paths in order. Redemption Shield is redemption protection, not liquidation protection: troves with and without it are liquidated under the exact same rules, and liquidateTroves walks both books together. 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 both sorted lists — base and Redemption Shield — in ascending ICR and clears up to _n troves whose ICR is below MCR. 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().

Liquidated trove10,000 RD debt(fell under MCR)10,000 RDStability Pooldeposits ↓ 10,000 RDcollateral ↑ 10,500 (value)Other troves (rest of branch)no change
SP offset only. The Stability Pool has enough RD to cover the whole debt. It burns 10,000 RD from depositor balances and receives collateral worth ×1.05 that (the 5% spread is depositor profit). Every other trove on the branch is untouched.

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:
debt: trove.remaining_debt
coll: min(trove.remaining_coll,
remaining_debt × par × LIQUIDATION_PENALTY_REDIST / oracle_price)
where LIQUIDATION_PENALTY_REDIST ≈ 1.10 (= 10% spread)
(per-branch parameter, typical 110%)

Like the offset path, this is a cap on seized value, not a multiplier on the trove's collateral: absorbing troves receive at most 110% of the redistributed debt's par value, and any collateral beyond the cap goes back to the borrower as surplus.

Every other active trove on the branch inherits a pro-rata slice of the DefaultPool balance. The redistribution accumulators (L_Coll for collateral; L_baseNormRDDebt / L_shieldNormRDDebt for debt) 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.

Liquidated trove10,000 RD debt(fell under MCR)10,000 RDStability Poolno change (empty / underfunded)Other troves (rest of branch)debt ↑ 10,000 RDcollateral ↑ 11,000 (value)
Redistribution only. The Stability Pool is empty (or too small), so the debt and collateral are spread pro-rata across the branch's other active troves. They inherit the debt and collateral worth ×1.10 of it — a slight ICR improvement, settled on each trove's next state-touching call.

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 capped at (SP_offset × par × 1.05 / price)
redist: DefaultPool gets remaining coll, capped at (redistribute × par × 1.10 / price)

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

Liquidated trove10,000 RD debt(fell under MCR)6,000 RD4,000 RDStability Pooldeposits ↓ 6,000 RDcollateral ↑ 6,300 (value)Other troves (rest of branch)debt ↑ 4,000 RDcollateral ↑ 4,400 (value)
Mixed. The Stability Pool has some RD but not enough. It absorbs what it can (here 6,000 RD, at ×1.05); the remaining 4,000 RD of debt is redistributed to the other troves (at ×1.10). Same end state — trove closed, debt cleared — just split across both.

What a liquidation costs the borrower​

Both penalties are caps on seized value, measured at par: debt × par × penalty / price (_maxPenaltyColl). Everything above the cap is credited back to the borrower through the CollSurplusPool. The bars below split an example 10,000 RD trove between the caller, the recipients, and the borrower on each path — drag the ICR to see the surplus shrink to zero exactly at the penalty cap:

Three things fall out of the caps. Liquidation is bounded, not confiscatory — at any ICR above the cap the borrower gets collateral back. A funded Stability Pool halves the borrower's penalty (5% vs 10%), which is one more reason the protocol wants deposits in it. And below the cap the loss inverts: the recipients absorb the shortfall, which is why liquidating early (just under MCR) is better for everyone than liquidating late.

Liquidator 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: _getCollGasCompensation() returns entireColl / 200 — 0.5% of the trove's collateral, paid in the branch's collateral token.
Liquidated trove10,000 RD debt(fell under MCR)GasPool200 RD per trove(deposited at trove open)0.5% of collateral200 RDStability Pooloffset path — as aboveOther troves (rest of branch)redistribution path — as aboveLiquidator (whoever called)collateral ↑ entireColl / 200RD ↑ 200 (gas compensation)
Liquidator compensation rides on top of either path above. The caller takes a 0.5% collateral kicker (entireColl / 200) straight from the trove, plus the trove's 200 RD gas compensation held in the GasPool since the trove opened. The debt and remaining collateral flow to the Stability Pool / other troves exactly as in the paths above.

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​

If branch TCR < CCR, the branch is in recovery mode. Liquidation does not change — the threshold is ICR < MCR, always. What changes is what borrowers may do (BorrowerOperations._requireValidAdjustment):

A recovery-mode configuration: the liquidation line stays at MCR. The hatched band marks the borrowing restrictions — while TCR is below CCR, no adjustment may reduce a trove's ICR, and new debt (or a new trove) must end at ICR ≥ CCR.

  • Top-ups and repayments are always allowed (they improve ICR).
  • Collateral withdrawals are allowed only if the resulting ICR ≥ MCR and the ICR does not decrease.
  • Debt increases are allowed only alongside enough collateral that the ICR improves and ends ≥ CCR. New troves must open at ICR ≥ CCR.
  • In normal mode the constraints are: resulting ICR ≥ MCR and the adjustment must not pull TCR below CCR.

(Collateral seizure in any liquidation, in any mode, is penalty-capped via _maxPenaltyColl(debt, par, penalty, price); collateral beyond the cap returns to the borrower as surplus.)

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

Dwarf & mini-dwarf cleanup​

When a branch's Redemption Shield share is high, the shield discount can drive a trove without Redemption Shield's effective rate below zero, negative interest, so its actual debt erodes over time. A trove that drifts below the minimum has two dedicated cleanup paths, by band:

Dwarf — actual debt between the 200 RD gas reserve and the 2,000 RD minimum (RD_GAS_COMPENSATION < actualDebt < RD_GAS_COMPENSATION + MIN_NET_DEBT), and still healthy (ICR ≥ MCR, so not liquidatable). Anyone can call BorrowerOperations.forceCloseTrove(address): the caller repays the trove's net debt out of their own RD and is paid a collateral bounty worth that net debt plus a cleanup bonus of up to the 200 RD gas reserve (bounty = netDebt + min(netDebt, 200), priced at par and capped at the trove's collateral). Any collateral above the bounty returns to the borrower via CollSurplusPool.

Mini-dwarf — actual debt at or below the 200 RD gas reserve (actualDebt ≤ RD_GAS_COMPENSATION); there's essentially no borrowable debt left. TroveManager.sweepCloseTrove(address) (one-off) or sweepLeadingMiniDwarves(n) (keeper batch, from the redeemable tail) closes it: the residual debt is burned from the GasPool and all of the trove's collateral is returned to the borrower via CollSurplusPool, nothing is seized. Mini-dwarfs are skipped by redemption walks, so sweeping them keeps the sorted-list tail clean.

The full picture​

The tree below is the actual branching in Liquidations.sol — hover any box for the contract-level detail:

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.
  • Liquidation is capped, not confiscatory. Seizure is limited to 105%/110% of the debt's par value and the rest returns to the borrower — the borrower's downside is bounded at 5–10% plus gas compensation, no matter how the price gapped.
  • 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​