Liquidation Design

A liquidation moves unsafe security-bond allowance from an undercollateralized target vault to a non-liquidatable liquidator vault. Liquidation is punitive: it moves debt to the liquidator and seizes unlocked REP from the target vault at a bonus-priced exchange rate.

The purpose of liquidation is explicit: punish the vault that let its backing fall below the required threshold, reward the liquidator that takes on the unsafe debt, and move the system into a healthier state.

  1. The liquidated vault is punished by losing unlocked REP.
  2. The liquidator is rewarded with seized REP above market value.
  3. The target shortfall shrinks because required REP backing falls faster than REP is seized, and moved debt is accepted only by a caller vault that remains non-liquidatable, meaning at or above the collateral threshold.

Here, healthier means the target shortfall shrinks and the moved debt lands only on a caller vault that remains non-liquidatable under the securityMultiplier-adjusted collateral threshold. Liquidation redistributes REP and allowance; it does not increase aggregate backing.

Terms used below: targetUnlockedRep = target vault unlocked REP claim, targetAllowanceEth = target vault allowance, securityMultiplier = security multiplier, currentRepPerEthPrice = current REP/ETH price, PRICE_PRECISION = 1e18.

Liquidatable Condition

A vault is liquidatable when its unlocked REP backing is below the required threshold:

Target Vault unsafe debt loses unlocked REP debt plus bonus-priced REP Liquidator Vault absorbs debt earns seized REP

Punitive FlowThe liquidator takes debt and receives unlocked REP from the target vault. The target is punished, the liquidator is rewarded, and the target becomes healthier only because required REP backing falls faster than REP is seized.

targetAllowanceEth securityMultiplier currentRepPerEthPrice > targetUnlockedRep PRICE_PRECISION

Liquidatable ConditionThe vault is unsafe when required REP backing exceeds unlocked REP.

The contract snapshots the target vault when liquidation is queued. Execution reuses that snapshot, so adding REP later cannot block the pending liquidation.

Execution Gates

The liquidatable-threshold inequality is necessary but not sufficient for execution. A staged liquidation also needs a valid current oracle price, an unexpired staging window, target allowance unchanged and target ownership not below the queued snapshot, and enough distance beyond the threshold to satisfy minLiquidationPriceDistanceBps. These gates fail in different ways. If the current price is stale, execution reverts and the staged operation stays pending. If coordinator-level checks fail after a valid price is available, such as expiry, stale snapshot data, or too little distance from the threshold, the coordinator consumes the staged operation without calling the pool. If the pool call itself fails after consumption, for example because the caller would become liquidatable or because a requested chunk leaves forbidden debt dust, the coordinator emits a failed execution result. See OpenOracle integration for the full settlement and distance-check flow.

Penalty Math

The seized REP is based on the debt chunk's market value plus a fixed liquidation bonus. The current implementation uses LIQUIDATION_REP_BONUS_BPS = 500, or a five percent REP bonus to the liquidator.

Constant Value Unit Source
BPS_DENOMINATOR 10000 basis points SecurityPoolUtils.sol
LIQUIDATION_REP_BONUS_BPS 500 basis points SecurityPoolUtils.sol
MIN_REP_DEPOSIT 10e18 REP wei SecurityPoolUtils.sol
MIN_SECURITY_BOND_DEBT 1e18 ETH wei SecurityPoolUtils.sol
PRICE_PRECISION 1e18 fixed-point scale SecurityPoolUtils.sol
repToMove = ceil ( debtToMovecurrentRepPerEthPrice(BPS_DENOMINATOR+liquidationRepBonusBps) PRICE_PRECISIONBPS_DENOMINATOR )

REP PenaltyThe liquidator receives REP worth the liquidated debt plus a bonus. This computed repToMove is the penalty and event amount; the pool moves the corresponding ownership units, so displayed REP claims can differ by ownership-rounding dust.

The maximum executable debt chunk is bounded by the target's unlocked REP. The contract will not liquidate away the last MIN_REP_DEPOSIT unless a separate flow closes the vault fully.

repBoundDebt = if targetUnlockedRep>MIN_REP_DEPOSIT ,   floor ( (targetUnlockedRep-MIN_REP_DEPOSIT)PRICE_PRECISIONBPS_DENOMINATOR currentRepPerEthPrice(BPS_DENOMINATOR+liquidationRepBonusBps) )  else 0 targetCapBeforeDebtFloor = min(targetAllowanceEth,repBoundDebt) targetCapAfterDebtFloor = if 0<targetAllowanceEth-targetCapBeforeDebtFloor<MIN_SECURITY_BOND_DEBT ,  targetAllowanceEth>MIN_SECURITY_BOND_DEBT ?targetAllowanceEth-MIN_SECURITY_BOND_DEBT:0 ,  else targetCapBeforeDebtFloor debtToMove = min(requestedDebt,targetCapAfterDebtFloor)

Executable BoundThe requested debt chunk is capped by the target's unlocked REP and then checked against the minimum debt floors.

debtToMove securityMultiplier currentRepPerEthPrice > repToMove PRICE_PRECISION

Health-Improvement GuardEvery successful liquidation must strictly reduce the target shortfall. Equality still fails, so ceiling-rounded REP seizure can make one-wei or otherwise tiny chunks non-executable.

There is one more chunking constraint at execution time: remainingDebt = targetAllowanceEth - debtToMove must be zero or at least MIN_SECURITY_BOND_DEBT. The caller's post-liquidation allowance must also be at least MIN_SECURITY_BOND_DEBT, because any successful liquidation moves non-zero debt to the caller. A chunk that is safe for the target can still revert if it would leave the liquidator below that minimum non-zero debt floor. Very small chunks can also revert when ceiling-rounded REP seizure would reduce the target's REP faster than the chunk reduces required backing, because every successful liquidation must strictly improve target health.

Repeated Liquidations

A punitive liquidation is not guaranteed to restore target safety in one execution. A liquidation can move the target toward safety without restoring it completely, because the liquidator is also paid a REP bonus. Repeated liquidations at the same price can therefore remain possible until the target debt is cleared, the target becomes safe again, the target hits a floor constraint, or the liquidator side would become liquidatable after absorbing more debt. This is one source of path dependence: a smaller first liquidation can make the target safe again and block a later same-price liquidation that would have been absorbed inside one larger execution.

Worked Examples

Unless a row says otherwise, assume the caller vault already has enough REP backing to remain non-liquidatable after it absorbs the moved debt and receives seized REP. The rows focus on target-side sizing and penalty math; execution still applies the caller post-liquidation check.

Case Inputs Result
Penalty liquidation targetUnlockedRep = 1000 REP, targetAllowanceEth = 75 ETH, securityMultiplier = 2, currentRepPerEthPrice = 10 REP/ETH Required backing is 75 * 2 * 10 = 1500 REP, so the target starts 500 REP short. A 25 ETH liquidation seizes 25 * 10 * 1.05 = 262.5 REP. After liquidation the target has 50 ETH of debt and 737.5 REP of backing. The target is still unsafe, but the shortfall shrinks from 500 REP to 262.5 REP.
Locked escalation REP stays untouched targetUnlockedRep = 300 REP unlocked, targetAllowanceEth = 200 ETH, securityMultiplier = 2, currentRepPerEthPrice = 1 REP/ETH A full 200 ETH liquidation would seize 210 REP, leaving 90 REP unlocked and 0 ETH debt. Escalation-locked REP is still ignored when sizing the liquidation, so only the unlocked vault claim is at risk.
Target-side debt dust clamp targetAllowanceEth = 1.4 ETH, targetUnlockedRep = 1000 REP, securityMultiplier = 2, currentRepPerEthPrice = 1000 REP/ETH The target has enough unlocked REP for about 0.94 ETH of punitive liquidation while still keeping 10 REP. That would leave 0.46 ETH of target debt, which is forbidden dust, so the executable target-side cap is reduced to 0.4 ETH instead.
Caller-side dust revert targetAllowanceEth = 1.4 ETH, targetUnlockedRep = 1000 REP, securityMultiplier = 2, executable target-side cap is 0.4 ETH, caller starts with zero debt A 0.4 ETH liquidation would leave the caller with a non-zero allowance below MIN_SECURITY_BOND_DEBT, so the pool rejects it. In that setup, no punitive liquidation chunk is executable.

Slider Examples

These calculators use whole ETH and REP units for readability. The equations above describe the scaled integer math used onchain.

Punitive liquidation calculator

Status: Liquidatable

Required REP: 1500 REP

REP shortfall: 500 REP

Target-side cap before caller checks: 75 ETH

Post-max debt: 0 ETH

REP seized at Max: 787.5 REP

This calculator only models the target-side cap. A real execution can still revert if the caller vault would fail its own debt-floor or post-liquidation non-liquidatable checks. It also clamps away non-deployable low multipliers, but it remains a whole-unit target-side illustration rather than a wei-level requested-chunk simulator for the strict health-improvement guard.

Path dependence check

Base case is fixed at targetUnlockedRep = 1000 REP, targetAllowanceEth = 75 ETH, securityMultiplier = 2, and currentRepPerEthPrice = 10 REP/ETH.

Single liquidation using first + second: 50 ETH debt remaining

Two-step path: 50 ETH debt remaining

Same state? Yes

This path comparison assumes each step's caller vault passes the post-liquidation non-liquidatable and debt-floor checks. It models target-side path dependence only.

Incentive Implications

The protocol uses a target-funded REP penalty. That means the liquidator has a direct immediate reward and the target is explicitly punished when it falls below the collateral threshold.

This only improves the target if debt relief frees more required backing than the protocol seizes as a REP bonus. Ignoring integer rounding, the economic condition is:

securityMultiplier > 1 + liquidation bonus

With a 2x security multiplier and a 5% REP bonus, ordinary-sized liquidations reduce required backing faster than seized REP, so the target gets healthier even while it loses collateral. The executable rule is still the strict onchain health-improvement guard debtToMove * securityMultiplier * currentRepPerEthPrice > repToMove * PRICE_PRECISION; ceil-rounded tiny chunks can fail with No gain.

The tradeoff is boundary sensitivity, not generic path dependence. Partial liquidations can leave the target still liquidatable, and exact results become path-sensitive when integer rounding, REP floors, debt floors, or caller threshold checks bind. Away from those boundaries, the linear REP penalty means repeated partial liquidations at a fixed price can reach the same final state as one combined liquidation.