ForceCloseSteps

The ForceCloseSteps Facet provides a step-based force close flow that supports both normal (isolated) and cross-mode PartyBs. It was introduced because the legacy single-transaction forceClosePosition on the ForceActionsFacet cannot handle cross-mode PartyBs, where settlement requires a UnifiedSettlementSig covering multiple PartyAs and the settlement + close must use consistent price snapshots.


Overview

The ForceCloseSteps Facet provides two ways to execute a force close:

  • 3-Step Flow: initializeForceClosesettleUpnlForForceClose (optional) → finalizeForceClose. Each step is a separate transaction, allowing large settlements to be broken across multiple calls.

  • Convenience Function: forceCloseAndSettlePositionsUnified combines all three steps into a single transaction when the settlement data is small enough to fit within gas limits.

Behavioral Differences by PartyB Mode

Behavior
Normal (Isolated) PartyB
Cross-Mode PartyB

Insolvency handling

Reserve vault fallback → PartyB liquidation

Close with uPnL ignored → CLOSED_INSOLVENT status

Settlement scope

Same PartyB, same PartyA only

Same PartyB, any PartyA (shared pool)

On insolvency event

LiquidatePartyB

ForceClosePosition + ForceClosePartyBInsolvent

Reserve vault used

Yes

No

Cross-mode PartyBs are never liquidated during force close. If PartyB is insolvent, the position either closes (marked CLOSED_INSOLVENT) or the transaction reverts with insufficient balance.


initializeForceClose()

Step 1. Validates force-close conditions and computes the close price. The quote must be in CLOSE_PENDING status with a LIMIT order type, the force-close cooldown must have elapsed, and the close price must have been reached within the signature's high/low price range. Checks that PartyA remains solvent after the close.

Stores a ForceCloseDetail snapshot containing the computed close price, PartyB's uPnL, and the current market price. This snapshot is used by subsequent steps and does not change after initialization.

Function Signature:

Parameters:

  • quoteId: The ID of the quote to force-close.

  • sig: The Muon HighLowPriceSig containing high/low prices used to calculate the close price with penalty.

Example:

Events Emitted:

  • ForceCloseInitialized(address caller, address partyB, uint256 quoteId, bytes reqId, uint256 closePrice, uint256 timestamp)


settleUpnlForForceClose()

Step 2. Settles unrealized PnL using UnifiedSettlementSig to fund the close when either party lacks sufficient available balance. This step can be called multiple times if the settlement needs to be spread across several transactions.

Which positions can be settled depends on the scenario:

  • PartyA lacks funds: Settle PartyA's profitable positions with any other PartyB (not the force-close quote's PartyB). This increases PartyA's allocated balance.

  • PartyB (non-cross) lacks funds: Settle the same PartyB's profitable positions, but only with the force-close quote's PartyA. In isolated mode, each per-PartyA bucket is separate, so the contract enforces that only one PartyA is included in the settlement.

  • PartyB (cross) lacks funds: Settle the same PartyB's positions with any PartyA. Everything goes to the shared address(0) pool.

After settlement, the stored upnlPartyB snapshot is adjusted by the settlement delta (only when the settlement targets the force-close quote's PartyB), ensuring consistency for the finalize step.

Function Signature:

Parameters:

  • quoteId: The ID of the quote in the force-close workflow.

  • settlementSig: The UnifiedSettlementSig containing uPnL data and pricing for settlement.

  • updatedPrices: New prices to set as openedPrice for the settled quotes.

Events Emitted:

  • SettleUpnlUnified(bytes reqId, QuotesSettlementsData[] data, uint256[] updatedPrices, address partyB, address[] partyAs, uint256[] newPartyAsAllocatedBalances, uint256 newPartyBAllocatedBalance)


finalizeForceClose()

Step 3. Refreshes the uPnL and current price snapshot with a fresh Muon signature (ensuring PartyA solvency at the latest prices), then closes the position.

The close behavior differs by PartyB mode:

  • Normal PartyB: If PartyB is solvent after close, emits ForceClosePosition. If insolvent, attempts the reserve vault fallback. If the reserve vault covers the deficit, the position closes. If not, triggers PartyB liquidation and emits LiquidatePartyB.

  • Cross-Mode PartyB: Always emits ForceClosePosition. If PartyB is insolvent, the position still closes (marked CLOSED_INSOLVENT) and additionally emits ForceClosePartyBInsolvent. If even the "ignore uPnL" fallback is insufficient, the transaction reverts.

Function Signature:

Parameters:

  • quoteId: The ID of the quote to finalize the force close for.

  • sig: A fresh Muon PairUpnlAndPriceSig to refresh the uPnL and current price snapshot.

Events Emitted (normal PartyB, solvent):

  • ForceClosePosition(uint256 quoteId, address partyA, address partyB, uint256 filledAmount, uint256 closePrice, QuoteStatus status, uint256 closeId)

Events Emitted (normal PartyB, insolvent):

  • LiquidatePartyB(address liquidator, address partyB, address partyA, uint256 partyBAllocatedBalance, int256 upnlPartyB)

Events Emitted (cross PartyB, solvent):

  • ForceClosePosition(...)

Events Emitted (cross PartyB, insolvent):

  • ForceClosePosition(...)

  • ForceClosePartyBInsolvent(uint256 quoteId, address partyA, address partyB, uint256 closePrice, uint256 currentPrice, int256 upnlPartyB, int256 partyBAvailableAfterClose)


forceCloseAndSettlePositionsUnified()

Convenience function that combines all three steps — initialize, settle (optional), and finalize — into a single transaction. Unlike the step-by-step flow, the finalize here does not take a fresh PairUpnlAndPriceSig. It uses the uPnL and current price values from the init signature directly (adjusted by any settlement delta).

Settlement is skipped if updatedPrices is empty.

Function Signature:

Parameters:

  • quoteId: The ID of the quote to force-close.

  • sig: The Muon HighLowPriceSig for calculating the close price.

  • settlementSig: The UnifiedSettlementSig for settlement. Ignored if updatedPrices is empty.

  • updatedPrices: New prices for settled quotes. Pass an empty array to skip settlement.

Events Emitted:

  • ForceCloseInitialized(...) — from the init step

  • SettleUpnlUnified(...) — from the settle step (only if updatedPrices is non-empty)

  • ForceClosePosition(...) and/or ForceClosePartyBInsolvent(...) or LiquidatePartyB(...) — from the finalize step

Last updated