Emergency Liquidation Flow¶
Last Resort
This flow should never be used in normal operation. It exists for one specific, extreme scenario. Using it unnecessarily imposes real slippage costs on all remaining investors.
Trigger: System is paused AND idle reserve is depleted AND HouseBuffer cannot top up AND no positions are near settlement. Caller: Governance (operator)
When to Use¶
All of the following must be true:
| Condition | Check |
|---|---|
| System is paused | vault.paused() == true |
| Idle reserve is depleted | idleReserve < dailyCap |
| HouseBuffer cannot or will not top up | Buffer is empty or governance decision |
| No positions settling soon | No position with maturity < now + 7 days |
| Investors are locked with no other path | Queue depth > 0, no other resolution |
Try these first
- If a position settlement is within 7 days — wait for settlement instead of selling at a loss
- If HouseBuffer can top up — use that instead
- If the pause is caused by gap but reserve is adequate — the system will unpause when the gap narrows
rebasePosition()may be sufficient to reduce the gap below the pause threshold
The On-Chain Guard¶
emergencyLiquidate() reverts if the system is not paused. This prevents opportunistic use during normal operations.
Steps¶
- Operator determines which position to partially liquidate. Preference order:
- Position closest to settlement (least time value remaining — smallest loss from selling early)
- Position with worst gap (most impaired)
-
Smallest position (least market impact)
-
Operator determines
maxShares— the minimum number of NO shares needed to restoreidleReserveabovedailyCap. Do not sell more than necessary. -
Operator calls
vault.emergencyLiquidate(slotIndex, maxShares). -
Vault calls
adapter.sellNoShares(maxShares). -
Adapter sells NO shares on the prediction market at current market price. Returns USDC received to vault.
-
Vault adds returned USDC to
idleReserve. -
Vault adjusts position:
allocatedAssetsdecreases by the modeled value of shares sold-
If all shares liquidated: slot status →
EMPTY -
EmergencyLiquidation(slot, sharesLiquidated, usdcRecovered, slippageBps)emitted. -
Automatic unpause check: If
idleReserve > dailyCapANDaggregateGapBps < 1500, system unpauses. Keeper can resumeprocessWithdrawals().
Accounting Impact¶
// Example: emergency liquidation of 100K NO shares
// Position modeled price: $0.97
// Market price before sale: $0.91
// Execution price after slippage: $0.89
Modeled value of shares sold: $97,000
USDC recovered: $89,000
Gap loss (already unrealized): $6,000 ← was already reflected in market NAV
Slippage loss (new): $2,000 ← new permanent loss imposed on all holders
Net NAV reduction: $8,000 (the slippage cost)
Slippage Management¶
- Maximum slippage: 200 bps (2%)
- If execution would cause > 2% price impact, reduce
maxSharesand sell in smaller increments - Allow order book to recover between calls (minutes to hours depending on venue liquidity)
- The 200 bps guard is enforced in the adapter's
sellNoSharesimplementation — it reverts if the execution price falls too far below the pre-trade market price
Risks¶
| Risk | Mitigation |
|---|---|
| Slippage amplification | Sell in small increments; let book recover between calls |
| Cascading gap widening | If the vault holds >10% of a market's open interest, selling can push price down, widening the gap on the remaining position |
| Governance abuse | Pause requirement is enforced on-chain; all actions are transparent on-chain; multisig governance reduces single-party risk |
| Post-liquidation pricing | After the system unpauses, the first batch of withdrawal requests will be priced at the post-liquidation NAV (lower) — investors receive less than pre-crisis prices |