Perpetual liquidations¶
Liquidation is a keeper-driven, multi-transaction state machine implemented across AccountCore, PerpEngine, and PerpOrderBook. Each submitted step is atomic, while the namespace lock persists between start/cancel, later partial reductions, takeover, or clear. The system reuses normal FIFO liquidity and accounting instead of maintaining a separate liquidation venue.
Scope and authorization¶
- Governance allowlists liquidation keepers in
AccountCore. - Cross liquidation targets one account's complete namespace in one quote-specific Engine.
- Isolated liquidation targets one account-market namespace.
- Start, each partial reduction, and takeover independently require a currently allowlisted keeper. A takeover destination must also authorize that keeper through
TRADE. - A cross destination's risk state in that Engine must have no active positions and must not be liquidating, with zero cross maker-fee reserve and resting-order count; every transferred market must have no conflicting destination mode. Existing cross margin may be present. An isolated destination must be
NONEwith zero position, exposure, and maker-fee reserve for that market; existing isolated margin may be present. - The destination must be prefunded enough to pass post-transfer initial margin.
Keepers receive no separate protocol reward in this snapshot.
State machine¶
1. Start and cancel orders¶
The keeper starts cross or isolated liquidation. The Engine requires sane prices and health below cancelMargin, sets the liquidation lock, and cancels resting orders atomically.
For cross margin, the keeper supplies a strictly increasing list of market IDs containing the account's orders. Every market must belong to the selected Engine and the Engine-wide cross resting-order count must be zero at the end. This bounds work without adding a separate global order index.
The Engine calls cancelAllForLiquidation on each book. That function returns exposure and maker-fee release journals and never calls AccountCore, avoiding a circular callback. If cancellation alone restores maintenance health, the Engine immediately clears the lock.
2. Partial forced reduction¶
If the namespace remains unhealthy, the keeper selects a position market, maximum base lots, and worst acceptable price. The Engine caps execution by:
- remaining position size;
- keeper-requested size; and
- market
maxLiquidationBaseLots.
It then calls the book's Engine-only executeLiquidation, which runs a reduce-only IOC through the normal FIFO matcher. Normal maker priority and maker-fee snapshots apply. The target pays its ordinary effective taker fee; builder fees do not apply.
The Engine applies the returned maker-fill journal in the same transaction. Maintenance health must strictly improve. Failure of cancellation accounting, fill settlement, fees, price checks, or the improvement rule reverts both Engine and orderbook mutation. Recovery above maintenance clears the lock.
3. Terminal takeover¶
If health is below takeoverMargin, a keeper may transfer:
- the complete cross namespace, including every active cross position and cross margin; or
- one isolated position and its isolated margin.
The destination must satisfy the exact empty-namespace checks above and initial margin after transfer. Takeover is a namespace transfer, not a token payout to the keeper.
4. Clear recovery¶
Anyone may clear a liquidation lock once current maintenance health has recovered. The clear entrypoints are permissionless so an account is not dependent on the original keeper.
Interaction with protocol controls¶
| Operation | Relevant gates |
|---|---|
| Start liquidation | allowlisted keeper, unhealthy namespace, sane prices; not blocked by AccountCore global pause or orderbook hard pause |
| Forced cancellation | Engine-only orderbook path; works in all orderbook states |
| Partial reduction | allowlisted keeper, existing lock, sane prices, strict health improvement; blocked by orderbook HARD_PAUSED |
| Takeover | allowlisted keeper, existing terminal lock, sane prices, keeper TRADE permission over destination, destination checks; no FIFO execution-state dependency |
| Clear recovered lock | permissionless maintenance-health check; current path does not require a fresh/oracle-sane price |
HARD_PAUSED therefore prevents ordinary user actions and partial liquidation execution, though forced cancellation still works. Recovery may then depend on collateral addition, takeover eligibility, or governance/ops loosening the book state.
AccountCore market disablement blocks normal updates and isolated user operations, but does not itself block liquidation start. If prices become stale while the market is disabled, governance must restore a path for price refresh before sane-price-gated liquidation can progress.
Accounting and observability¶
Important events include:
PerpLiquidationStartedandPerpLiquidationClearedfrom the Engine;PerpPositionLiquidatedfrom AccountCore for each successful partial reduction;PerpNamespaceTakenOverfor terminal transfer;- normal
PerpFillSettled, margin, position, exposure, maker-fee-reserve, packed trade, and packed book-update events from the same transaction.
If cancellation during start immediately restores maintenance health, the Engine clears the lock but emits only PerpLiquidationStarted(..., recovered=true), not PerpLiquidationCleared. Takeover clears/transfers the locked state and emits PerpNamespaceTakenOver, also without a separate cleared event. PerpLiquidationCleared is emitted when a partial reduction restores maintenance health and when the explicit permissionless-clear path succeeds.
For cross events, marketId == 0 identifies the Engine-local cross namespace, not a tradeable market.
Failure boundary¶
Margin balances are unsigned. This revision has no explicit negative-equity ledger, insurance fund, bankruptcy process, backstop, or ADL. A realized loss, fee, or funding debit larger than available stored margin reverts instead of persisting a deficit. That limitation is especially material at the terminal liquidation boundary and must be resolved or explicitly accepted before production claims of complete insolvency handling.
A non-reduce-only maker fill that leaves maker risk active rechecks transfer health at execution, even if it reduces that position; a fill that clears the maker flat skips the check. An unhealthy resting maker can therefore revert a taker's action; there is no permissionless stale-maker eviction path beyond the available cancellation controls.