Skip to content

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

  1. If a position settlement is within 7 days — wait for settlement instead of selling at a loss
  2. If HouseBuffer can top up — use that instead
  3. If the pause is caused by gap but reserve is adequate — the system will unpause when the gap narrows
  4. rebasePosition() may be sufficient to reduce the gap below the pause threshold

The On-Chain Guard

require(paused(), "System must be paused");

emergencyLiquidate() reverts if the system is not paused. This prevents opportunistic use during normal operations.

Steps

  1. Operator determines which position to partially liquidate. Preference order:
  2. Position closest to settlement (least time value remaining — smallest loss from selling early)
  3. Position with worst gap (most impaired)
  4. Smallest position (least market impact)

  5. Operator determines maxShares — the minimum number of NO shares needed to restore idleReserve above dailyCap. Do not sell more than necessary.

  6. Operator calls vault.emergencyLiquidate(slotIndex, maxShares).

  7. Vault calls adapter.sellNoShares(maxShares).

  8. Adapter sells NO shares on the prediction market at current market price. Returns USDC received to vault.

  9. Vault adds returned USDC to idleReserve.

  10. Vault adjusts position:

  11. allocatedAssets decreases by the modeled value of shares sold
  12. If all shares liquidated: slot status → EMPTY

  13. EmergencyLiquidation(slot, sharesLiquidated, usdcRecovered, slippageBps) emitted.

  14. Automatic unpause check: If idleReserve > dailyCap AND aggregateGapBps < 1500, system unpauses. Keeper can resume processWithdrawals().

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 maxShares and 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 sellNoShares implementation — 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