Muon Architecture

Muon is the off-chain computation layer that provides cryptographically signed data to Symmio. All critical operation in the protocol — opening positions, closing positions, liquidations, deallocations — requires a valid Muon signature proving the current state of prices and unrealized PnL.

Why Symmio Needs an Oracle

Symmio is a bilateral derivatives protocol. At any moment, the protocol needs to know:

  • Current prices for all trading symbols

  • Unrealized PnL (uPnL) for PartyA and PartyB

  • Whether a party is solvent and can execute their requested action

Calculating uPnL on-chain would require iterating through all open positions and fetching current prices — prohibitively expensive on most chains. Muon solves this by performing calculations off-chain and delivering signed attestations that the contracts can verify cheaply.

Dual-Layer Signature Verification

Symmio doesn't trust a single signer. Every Muon signature passes through two independent verification layers before the contract accepts it.

Layer 1: TSS (Threshold Signature Scheme)

Muon operates a distributed network of nodes. When a signature request comes in, multiple nodes independently:

  1. Fetch price data from exchanges

  2. Calculate the requested values (uPnL, solvency, etc.)

  3. Contribute to a threshold signature

The result is a Schnorr signature that proves a threshold of nodes agreed on the data. The contract verifies this against the stored muonPublicKey in MuonStorage.

// Verification happens in LibMuonV04ClientBase.muonVerify()
// Checks Schnorr signature against muonLayout.muonPublicKey

Layer 2: Gateway ECDSA

After TSS verification, the contract performs a second check: it recovers the signer from a standard ECDSA signature and verifies it matches the registered validGateway address.

What Gets Signed

Different operations require different signature types. Each includes specific data fields that get hashed and signed.

SingleUpnlSig

Used for: deallocate(), sendQuote()

Contains:

  • partyA address

  • nonce (replay protection)

  • uPnL value

  • timestamp

  • chainId

SingleUpnlAndPriceSig

Used for: sendQuote() (with price validation)

Contains everything in SingleUpnlSig plus:

  • symbolId

  • price for that symbol

PairUpnlSig

Used for: openPosition(), fillCloseRequest()

Contains:

  • partyA address

  • partyB address

  • partyA nonce

  • partyB nonce

  • partyA uPnL

  • partyB uPnL

  • timestamp

  • chainId

PairUpnlAndPriceSig

Used for: Position operations requiring price verification

Contains everything in PairUpnlSig plus:

  • symbolId

  • price

LiquidationSig

Used for: liquidatePartyA(), liquidatePartyB()

Contains:

  • Party addresses

  • Nonces

  • Liquidation prices for all relevant symbols

  • Total uPnL

  • Symbol IDs array

  • timestamp

  • chainId

Replay Protection via Nonces

Muon signatures include two distinct identifiers that serve different purposes:

reqId (Muon Request ID)

Each Muon request generates a unique reqId. This is included in the signed hash:

The reqId serves as request identification within the Muon network

Contract Nonces (On-Chain State Binding)

The contract maintains nonce counters in AccountStorage:

This nonce is included in the signed hash. The contract then verifies the signature was made with the current nonce value:

How Replay Protection Works

  1. Muon reads current on-chain nonce (e.g., 5)

  2. Muon signs data including that nonce

  3. User submits signature to contract

  4. Contract verifies signature hash includes current nonce (5) ✓

  5. State changes → nonce increments to 6


Signature Expiration

Signatures have a limited validity window defined by upnlValidTime in MuonStorage:

This prevents old signatures from being used after market conditions have changed significantly.

Last updated