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.
- The liquidated vault is punished by losing unlocked REP.
- The liquidator is rewarded with seized REP above market value.
- 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:
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.
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 |
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.
Executable BoundThe requested debt chunk is capped by the target's unlocked REP and then checked against the minimum debt floors.
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.