LogoLogo
  • Overview
    • Introduction
    • Table of Contents
  • Token Information
    • Symmio Foundation
  • Protocol Architecture
    • Protocol Introduction
    • Technical Documentation
      • Building an Application with SYMM
        • Introduction and Diamond Explainer
        • Querying Info from the SYMM Diamond
        • MultiAccount
        • Creating an Account and Depositing Funds
        • Sending a Quote
        • Closing a Quote
        • Instant Trading
          • Instant Login (EOA)
          • Instant Login (Account Abstraction)
          • Sending a Quote (Instant Open)
          • Sending a Quote (Instant Close)
        • Frequently Used Queries
      • Solver Docs
        • Solver Docs (github)
        • Solver Implementation Guide (High Level Overview)
        • Building a Solver on SYMMIO
          • 1. Intent Creation
          • 2. Seeing the Intent
          • 3. Hedging Off-Chain
          • 4. Opening/Closing a Position On-Chain
          • Creating the APIs
            • GET Contract Symbols
            • GET Open Interest
            • GET Notional Cap
            • GET Price Range
            • GET Error Codes
            • GET Get Locked Params
            • GET Get Funding Info
            • POST Position State
          • Solver Flow Summary Example
          • Recommended Architecture for Solvers
          • Glossary
        • Conditional Orders Handler
        • Rasa Solver TP/SL Implementation
        • Instant Trading
          • Instant Trading (Solvers)
          • Rasa Instant Trading Implementation
          • Instant Trading Condition Checks
        • Fetching Gas Prices Script
        • How to Add a Market as a Solver
        • Verifying Account Abstracted Instant Actions (ERC-4337)
      • Frontend Docs
        • Setting up a Frontend with SYMMIO
        • Frontend SDK Setup Guide
        • MultiAccount Deployment Guide
        • Instant Trading (Frontends)
          • Account Abstracted Instant Actions (Frontends)
        • Implement a Trading Bot on Symmio (OLD)
          • Setup
          • Creating a Sub-Account
          • Minting Collateral Tokens (Optional)
          • Depositing and Allocating Tokens
          • Obtaining Muon Signatures
          • Sending a Quote
          • Monitoring Price for Execution
      • Contract Docs
        • SYMMIO CORE v0.82
        • Contracts Documentation 0.8.2
          • Main Flow
          • The SYMM Diamond
          • Facets
            • Account Facet
            • Control Facet
            • Funding Rate Facet
            • PartyA Facet
            • PartyB Facet
            • Liquidation Facet
            • View Facet
          • MultiAccount
            • PartyA
            • PartyB
          • SYMM App (Muon)
            • LibMuon
            • MuonStorage
        • Contracts Documentation 0.8.3
          • Facets
            • Control Facet
            • Account Facet
            • PartyA Facet
            • PartyB Facet
            • View Facet
            • Bridge Facet
            • Liquidation Facet (Implementation)
          • Modified Events
          • New Events
          • MuonStorage
        • Contracts Documentation 0.8.4
          • Main Flow (0.8.4)
          • The SYMM Diamond (0.8.4)
          • Facets
            • Account Facet (0.8.4)
            • Bridge Facet (0.8.4)
            • Control Facet (0.8.4)
            • Force Actions Facet (0.8.4)
            • Funding Rate Facet (0.8.4)
            • Liquidations Facet (0.8.4)
            • PartyA Facet (0.8.4)
            • PartyB Group Actions Facet (0.8.4)
            • PartyB Quote Actions Facet (0.8.4)
            • PartyB Position Actions Facet (0.8.4)
            • Settlement Facet (0.8.4)
            • View Facet (0.8.4)
          • MultiAccount (0.8.4)
            • SymmioPartyA
            • SymmioPartyB
          • SYMM App (Muon)
            • LibMuon (0.8.4)
            • MuonStorage (0.8.4)
      • Contract Addresses / Solver Endpoints
        • Mantle
        • Mode
        • IOTA
        • Base
        • BSC
        • Arbitrum
        • Polygon
        • Berachain
        • Solver Endpoints and Addresses
          • Perps Hub
          • Rasa Capital
          • Rasa Capital (Zero Spread)
          • Zenith
      • How to Query our Contracts
      • Muon API Queries
      • Solver Error Codes
      • Interacting with SYMMIO Contracts
    • Protocol higher level architecture
      • 12-Hour Fraud Proof Window
      • PartyB
      • Solver Settings
      • Max Leverage
      • Maintenance Margin (CVA) Calculations
    • Symmio Whitepaper
  • Building on Symmio
    • Builders introduction
    • Solving for Symmio
      • Solver documentation
      • Solver - Example Flow
    • Trading Fees
      • Perps - Settlement Costs
      • Pair Trading - Settlement costs
    • Exchanges (Frontends)
      • Frontend Introduction
      • SDK - SYMM client
      • Trade on Symmio
  • Legal & Brand & Security
    • Security (Audits / Bugbounty)
      • Bug bounty / Coverage
        • How to contact ?
      • Audits
        • SYMM - V0.8 - 0.81
          • Sherlock Audit - Jun 15, 2023
          • Smart State - Jul 2, 2023
        • SYMM - 0.82
          • Sherlock Audit -Aug 30, 2023
        • SYMM - 0.83
          • Sherlock Audit - Jun 17, 2024
        • SYMM - 0.84
          • Sherlock Audit - Oct 3, 2024
        • Vaults
          • Sherlock Audit - Jan 2, 2024
    • Terms of Service & Licensing
      • TRADEMARK & COPYRIGHT NOTICE
      • CONTACT US
      • TERMS OF SERVICE
      • FRONTEND LICENSE
        • Frontend Modifications
        • Frontend Use Grants
      • CONTRACT LICENSE
        • Contract Use Grants
        • Contract Modifications
    • Brand - Assets Logos
Powered by GitBook
LogoLogo

All rights to the people (c) 2023 Symmetry Labs A.G.

On this page
  • Liquidations Facet (0.8.4)
  • Liquidation Flow
  • Liquidate Party A
  • liquidatePartyA()
  • setSymbolsPrice()
  • deferredLiquidatePartyA()
  • deferredSetSymbolsPrice()
  • liquidatePendingPositionsPartyA()
  • liquidatePositionsPartyA()
  • settlePartyALiquidation()
  • resolveLiquidationDispute()
  • liquidatePartyB()
  • liquidatePositionsPartyB()
  1. Protocol Architecture
  2. Technical Documentation
  3. Contract Docs
  4. Contracts Documentation 0.8.4
  5. Facets

Liquidations Facet (0.8.4)

PreviousFunding Rate Facet (0.8.4)NextPartyA Facet (0.8.4)

Last updated 4 months ago

Liquidations Facet (0.8.4)

The Liquidations Facet enables authorized liquidators to intervene when a party’s available balance falls below required thresholds. Liquidation actions include:

  • Liquidating Party A or Party B positions

  • Setting symbol prices at liquidation time

  • Processing deferred liquidations

  • Liquidating pending positions

  • Settling and resolving liquidation disputes


In order to grasp the intricacies of the liquidation process, a fundamental understanding of the 'pending locked' concept is crucial. When a user sends a quote request, the corresponding amount of the position goes into a 'pending' state. During this phase, the user is restricted from opening other positions with that specific amount. Nonetheless, this amount continues to contribute to the user's allocated funds when assessing their liquidity status. Once Party B opens the position, this amount goes from the 'pending' to the 'locked' state.

Liquidation Flow

Liquidate Party A

For a better understanding of how a user gets liquidated, let’s look at one with a $1000 allocated balance as an example:

User positions are all considered to be cross, meaning that in the above picture, values can be the sum of the equivalent values in 4 different positions. Pending locked values are from user quotes that have not been opened yet.

Now let’s say that the user is having a bad day, and one of their positions is sinking deep into loss:

Each user position has a respective UPNL, which determines whether the position is in profit(positive UPNL) or loss(negative UPNL). Adding all those UPNLs, we get the user’s total UPNL. Now let’s see what happens if UPNL changes:

  • Total upnl > 0: User is overall in profit

  • -500 < Total UPNL < 0: User’s locked MMs are supporting their positions

  • -700 < Total UPNL < -500: User’s free balance is now supporting their positions

  • -900 < Total UPNL < -700: User’s pending locked values are supporting their position

  • Total UPNL < -900: User will be liquidated now

As this is a cross-system, whenever a user gets liquidated, all of their quotes and positions will go to a liquidated state, or in other words they all get canceled.

On the contract side, the liquidation of partyA is a four-step process. The liquidator should first liquidate the user:

function liquidatePartyA(address partyA, SingleUpnlSig memory upnlSig);

At this point the user is marked as liquidated and the timestamp for that is recorded.

Then the liquidator should set the prices for all symbols associated with the user's positions:

function setSymbolsPrice(address partyA, PriceSig memory priceSig);
// priceSig contains
// uint256[] symbolIds;
// uint256[] prices;

Then the liquidator should liquidate partyA pending positions:

function liquidatePendingPositionsPartyA(address partyA);

And after that the liquidator should liquidate partyA open positions:

function liquidatePositionsPartyA(address partyA, uint256[] memory quoteIds);

liquidatePartyA()

Liquidates Party A when their available balance falls below the required threshold. This function verifies a Muon signature (contained in a LiquidationSig struct) and, upon successful verification, marks Party A as liquidated, updates their liquidation details, and records the liquidator.

Function Signature:

function liquidatePartyA(
    address partyA,
    LiquidationSig memory liquidationSig
) external whenNotLiquidationPaused notLiquidatedPartyA(partyA) onlyRole(LibAccessibility.LIQUIDATOR_ROLE);

Parameters:

  • partyA: Address of the Party A to be liquidated.

  • liquidationSig: A structure containing:

    • upnl: Unrealized profit and loss.

    • totalUnrealizedLoss: Total loss incurred.

    • liquidationId: Unique identifier for the liquidation.

    • timestamp: Signature timestamp, among other fields.

struct LiquidationSig {
	bytes reqId; // Unique identifier for the liquidation request
	uint256 timestamp; // Timestamp when the liquidation signature was created
	bytes liquidationId; // Unique identifier for the liquidation event
	int256 upnl; // User's unrealized profit and loss at the time of insolvency
	int256 totalUnrealizedLoss; // Total unrealized loss of the user at the time of insolvency
	uint256[] symbolIds; // List of symbol IDs involved in the liquidation
	uint256[] prices; // Corresponding prices of the symbols involved in the liquidation
	bytes gatewaySignature; // Signature from the gateway for verification
	SchnorrSign sigs; // Schnorr signature for additional verification
}

Example Usage:

LiquidationSig memory sig = /* obtain liquidation signature data */;
diamond.liquidatePartyA(partyAAddress, sig);

Events Emitted:

  • LiquidatePartyA(address liquidator, address partyA, uint256 allocatedBalance, int256 upnl, int256 totalUnrealizedLoss, bytes liquidationId)

  • (A backward compatibility version is also emitted without the liquidationId.)


setSymbolsPrice()

Updates the prices for all relevant symbols at the time of liquidation. The provided LiquidationSig includes arrays of symbol IDs and prices, which are stored along with the liquidation timestamp.

Function Signature:

function setSymbolsPrice(
    address partyA,
    LiquidationSig memory liquidationSig
) external whenNotLiquidationPaused onlyRole(LibAccessibility.LIQUIDATOR_ROLE);

Parameters:

  • partyA: Address of Party A for which the symbol prices are being set.

  • liquidationSig: A liquidation signature containing:

struct LiquidationSig {
	bytes reqId; // Unique identifier for the liquidation request
	uint256 timestamp; // Timestamp when the liquidation signature was created
	bytes liquidationId; // Unique identifier for the liquidation event
	int256 upnl; // User's unrealized profit and loss at the time of insolvency
	int256 totalUnrealizedLoss; // Total unrealized loss of the user at the time of insolvency
	uint256[] symbolIds; // List of symbol IDs involved in the liquidation
	uint256[] prices; // Corresponding prices of the symbols involved in the liquidation
	bytes gatewaySignature; // Signature from the gateway for verification
	SchnorrSign sigs; // Schnorr signature for additional verification
}

Example Usage:

LiquidationSig memory sig = /* obtain liquidation signature data with symbol prices */;
diamond.setSymbolsPrice(partyAAddress, sig);

Events Emitted:

  • SetSymbolsPrices(address liquidator, address partyA, uint256[] symbolIds, uint256[] prices, bytes liquidationId)

  • (A backward compatibility version is also emitted.)


deferredLiquidatePartyA()

Processes a deferred liquidation for Party A using a DeferredLiquidationSig.

Deferred Liquidation

Previously, the upnlValidTime variable in the Muon configuration prevented the liquidator from liquidating a user after a certain amount of time. This update allows the liquidator to liquidate the user if they haven't increased their nonce, provided the Muon app can supply signatures for a specific block requested by the liquidator. The LiquidationSig struct has been updated accordingly:

Function Signature:

function deferredLiquidatePartyA(
    address partyA,
    DeferredLiquidationSig memory liquidationSig
) external whenNotLiquidationPaused notLiquidatedPartyA(partyA) onlyRole(LibAccessibility.LIQUIDATOR_ROLE);

Parameters:

  • partyA: Address of the Party A to be liquidated.

  • liquidationSig: A deferred liquidation signature struct.

DeferredLiquidationSig Struct:

struct DeferredLiquidationSig {
	bytes reqId; // Unique identifier for the liquidation request
	uint256 timestamp; // Timestamp when the liquidation signature was created
	uint256 liquidationBlockNumber; // Block number at which the user became insolvent
	uint256 liquidationTimestamp; // Timestamp when the user became insolvent
	uint256 liquidationAllocatedBalance; // User's allocated balance at the time of insolvency
	bytes liquidationId; // Unique identifier for the liquidation event
	int256 upnl; // User's unrealized profit and loss at the time of insolvency
	int256 totalUnrealizedLoss; // Total unrealized loss of the user at the time of insolvency
	uint256[] symbolIds; // List of symbol IDs involved in the liquidation
	uint256[] prices; // Corresponding prices of the symbols involved in the liquidation
	bytes gatewaySignature; // Signature from the gateway for verification
	SchnorrSign sigs; // Schnorr signature for additional verification
}

Example Usage:

DeferredLiquidationSig memory deferredSig = /* obtain deferred liquidation signature data */;
diamond.deferredLiquidatePartyA(partyAAddress, deferredSig);

Events Emitted:

  • DeferredLiquidatePartyA(address liquidator, address partyA, uint256 allocatedBalance, int256 upnl, int256 totalUnrealizedLoss, bytes liquidationId, uint256 liquidationBlockNumber, uint256 liquidationTimestamp, uint256 liquidationAllocatedBalance)


deferredSetSymbolsPrice()

Sets the symbol prices in a deferred liquidation scenario using a DeferredLiquidationSig. Functionally similar to setSymbolsPrice, but for deferred liquidations.

Function Signature:

function deferredSetSymbolsPrice(
    address partyA,
    DeferredLiquidationSig memory liquidationSig
) external whenNotLiquidationPaused onlyRole(LibAccessibility.LIQUIDATOR_ROLE);

Parameters:

  • partyA: Address of Party A.

  • liquidationSig: Contains symbol IDs, prices, and a liquidation identifier from the deferred liquidation process.

DeferredLiquidationSig Struct:

struct DeferredLiquidationSig {
	bytes reqId; // Unique identifier for the liquidation request
	uint256 timestamp; // Timestamp when the liquidation signature was created
	uint256 liquidationBlockNumber; // Block number at which the user became insolvent
	uint256 liquidationTimestamp; // Timestamp when the user became insolvent
	uint256 liquidationAllocatedBalance; // User's allocated balance at the time of insolvency
	bytes liquidationId; // Unique identifier for the liquidation event
	int256 upnl; // User's unrealized profit and loss at the time of insolvency
	int256 totalUnrealizedLoss; // Total unrealized loss of the user at the time of insolvency
	uint256[] symbolIds; // List of symbol IDs involved in the liquidation
	uint256[] prices; // Corresponding prices of the symbols involved in the liquidation
	bytes gatewaySignature; // Signature from the gateway for verification
	SchnorrSign sigs; // Schnorr signature for additional verification
}

Example Usage:

DeferredLiquidationSig memory deferredSig = /* obtain deferred liquidation signature data */;
diamond.deferredSetSymbolsPrice(partyAAddress, deferredSig);

Events Emitted:

  • SetSymbolsPrices(address liquidator, address partyA, uint256[] symbolIds, uint256[] prices, bytes liquidationId)

  • (Also emitted for backward compatibility.)


liquidatePendingPositionsPartyA()

Liquidates all pending quotes (i.e., those not yet fully executed) for Party A. This function processes each pending quote, updates their status to a liquidation state, and clears associated locked balances.

Function Signature:

function liquidatePendingPositionsPartyA(address partyA) external whenNotLiquidationPaused onlyRole(LibAccessibility.LIQUIDATOR_ROLE);

Parameters:

  • partyA: Address of Party A whose pending positions will be liquidated.

Example Usage:

diamond.liquidatePendingPositionsPartyA(partyAAddress);

Events Emitted:

  • LiquidatePendingPositionsPartyA(address liquidator, address partyA, uint256[] pendingQuoteIds, uint256[] liquidatedAmounts, bytes liquidationId)

  • (Also emitted for backward compatibility.)


liquidatePositionsPartyA()

Liquidates specific open positions for Party A, as identified by an array of quote IDs. This function processes each quote by updating its status to "LIQUIDATED".

Function Signature:

function liquidatePositionsPartyA(
    address partyA,
    uint256[] memory quoteIds
) external whenNotLiquidationPaused onlyRole(LibAccessibility.LIQUIDATOR_ROLE);

Parameters:

  • partyA: Address of Party A whose positions are to be liquidated.

  • quoteIds: Array of quote IDs representing the positions to be liquidated.

Example Usage:

uint256[] memory quotesToLiquidate = new uint256[](2);
quotesToLiquidate[0] = 101;
quotesToLiquidate[1] = 102;
diamond.liquidatePositionsPartyA(partyAAddress, quotesToLiquidate);

Events Emitted:

  • LiquidatePositionsPartyA(address liquidator, address partyA, uint256[] quoteIds, uint256[] liquidatedAmounts, uint256[] closeIds, bytes liquidationId)

  • (Backward compatibility event is also emitted.)

  • If the liquidation is disputed, the events:

    • LiquidationDisputed(address partyA, bytes liquidationId)

    • (Also a backward compatibility version) are emitted.


settlePartyALiquidation()

Settles the liquidation process for Party A by reconciling settlement amounts with one or more Party Bs. After processing, if Party A is fully liquidated, the function emits events to signal completion.

Function Signature:

function settlePartyALiquidation(address partyA, address[] memory partyBs) external whenNotLiquidationPaused;

Parameters:

  • partyA: Address of Party A.

  • partyBs: Array of Party B addresses involved in the liquidation settlement.

Example Usage:

address[] memory involvedPartyBs = new address[](2);
involvedPartyBs[0] = partyBAddress1;
involvedPartyBs[1] = partyBAddress2;
diamond.settlePartyALiquidation(partyAAddress, involvedPartyBs);

Events Emitted:

  • SettlePartyALiquidation(address partyA, address[] partyBs, int256[] settleAmounts, bytes liquidationId)

  • (Also emits a backward compatibility event.)

  • If Party A becomes fully liquidated, the events:

    • FullyLiquidatedPartyA(address partyA, bytes liquidationId)

    • (And a backward compatibility version) are emitted.


resolveLiquidationDispute()

Resolves a dispute arising from a liquidation process for Party A. Settlement amounts for each involved Party B are updated, and the dispute status is recorded.

Function Signature:

function resolveLiquidationDispute(
    address partyA,
    address[] memory partyBs,
    int256[] memory amounts,
    bool disputed
) external onlyRole(LibAccessibility.DISPUTE_ROLE);

Parameters:

  • partyA: Address of Party A.

  • partyBs: Array of Party B addresses involved in the dispute.

  • amounts: Array of settlement amounts corresponding to each Party B.

  • disputed: Boolean flag indicating whether the liquidation is disputed.

Example Usage:

address[] memory parties = new address[](2);
parties[0] = partyBAddress1;
parties[1] = partyBAddress2;
int256[] memory settlementAmounts = new int256[](2);
settlementAmounts[0] = -50; //Wei amounts
settlementAmounts[1] = 30; //Wei amounts
bool disputeFlag = true;
diamond.resolveLiquidationDispute(partyAAddress, parties, settlementAmounts, disputeFlag);

Events Emitted:

  • ResolveLiquidationDispute(address partyA, address[] partyBs, int256[] amounts, bool disputed, bytes liquidationId)

  • (And a backward compatibility event.)


liquidatePartyB()

Description: Liquidates Party B with respect to a specific Party A by verifying a UPnL signature. This function is used when Party B’s allocated balance is insufficient, and it updates Party B’s liquidation status.

Function Signature:

function liquidatePartyB(
    address partyB,
    address partyA,
    SingleUpnlSig memory upnlSig
) external whenNotLiquidationPaused notLiquidatedPartyB(partyB, partyA) notLiquidatedPartyA(partyA) onlyRole(LibAccessibility.LIQUIDATOR_ROLE);

Parameters:

  • partyB: Address of the Party B to be liquidated.

  • partyA: The associated Party A address.

  • upnlSig: A structure containing UPnL signature data for Party B.

struct SingleUpnlSig {
	bytes reqId;
	uint256 timestamp;
	int256 upnl;
	bytes gatewaySignature;
	SchnorrSign sigs;
}

Example Usage:

SingleUpnlSig memory sig = /* obtain UPnL signature data */;
diamond.liquidatePartyB(partyBAddress, partyAAddress, sig);

Events Emitted:

  • LiquidatePartyB(address liquidator, address partyB, address partyA, uint256 allocatedBalance, int256 upnl)


liquidatePositionsPartyB()

Liquidates open positions for Party B (with respect to a specific Party A) using a QuotePriceSig. This function processes an array of quote IDs, updates each quote’s status to LIQUIDATED, and adjusts balances accordingly. If Party B has no remaining positions after liquidation, a fully liquidated event is emitted.

Function Signature:

function liquidatePositionsPartyB(
    address partyB,
    address partyA,
    QuotePriceSig memory priceSig
) external whenNotLiquidationPaused onlyRole(LibAccessibility.LIQUIDATOR_ROLE);

Parameters:

  • partyB: Address of Party B whose positions are to be liquidated.

  • partyA: Associated Party A address.

  • priceSig: A structure containing:

    • quoteIds: An array of quote IDs.

    • prices: An array of corresponding prices.

    • timestamp: The signature timestamp for verification.

struct QuotePriceSig {
	bytes reqId;
	uint256 timestamp;
	uint256[] quoteIds;
	uint256[] prices;
	bytes gatewaySignature;
	SchnorrSign sigs;
}

Example Usage:

QuotePriceSig memory priceSig = /* obtain price signature data */;
diamond.liquidatePositionsPartyB(partyBAddress, partyAAddress, priceSig);

Events Emitted:

  • LiquidatePositionsPartyB(address liquidator, address partyB, address partyA, uint256[] quoteIds, uint256[] liquidatedAmounts, uint256[] closeIds)

  • (A backward compatibility event is also emitted.)

  • If Party B’s positions are fully liquidated, the event:

    • FullyLiquidatedPartyB(address partyB, address partyA) is emitted.