ShieldedDEX

spec · config

A multi-asset shielded exchange where even the asset pair is hidden — not just order contents. Inspired by Zcash Shielded Assets (ZIP-226/227): custom tokens issued within the shielded pool inherit Zcash's privacy guarantees, making transfers of different asset types indistinguishable on-chain. Also related to Penumbra's multi-asset shielded pools and Anoma's intent-centric privacy architecture.

This is a genuinely new mechanism type, not a formalization of an existing design. It extends ZKDarkPool from single-pair to multi-pair with asset-type privacy.

How it extends ZKDarkPool

ZKDarkPool operates on a single trading pair — one buy book and one sell book. Everyone knows which market they're in; the privacy covers order contents (price, quantity, identity) but not the pair itself.

ShieldedDEX maintains one order book per pair. With two pairs (e.g., ZEC/USDC and ETH/USDC), the state looks like:

ZKDarkPool (single pair):
  buyOrders  = <<order1, order2>>
  sellOrders = <<order3>>

ShieldedDEX (multi-pair):
  buyOrders  = [ZEC/USDC ↦ <<order1>>,  ETH/USDC ↦ <<order3>>]
  sellOrders = [ZEC/USDC ↦ <<order2>>,  ETH/USDC ↦ <<order4>>]

The clearing algorithm is identical — uniform price, maximum volume — but parameterized per pair. Each pair clears independently with its own price (CrossPairIsolation verified).

The privacy extension: when a trader submits a commitment, the pair assignment is hidden. An observer sees 4 commitments arrive but cannot tell which pair each targets — they could all be for the same pair, or spread across pairs. After clearing, all order books across all pairs are destroyed. The observer never learns which pairs were active, how many orders each received, or at what prices they cleared.

This is what makes asset-targeted attacks impossible: you can't sandwich a specific pair if you can't identify which pair to target.

Implementation status

Zcash's ZSA ZIPs (226/227) define how to issue and transfer custom tokens privately, but no matching engine exists in the Zcash protocol. A ShieldedDEX would require additional protocol work:

ComponentWhat's neededStatus
Shielded custom tokensZIP-226 (issuance), ZIP-227 (transfer)Specified, not yet activated
Order commitment tx typeNew transaction type or memo-field protocol for submitting shielded ordersDoes not exist
Batch clearing logicConsensus-layer rule (new ZIP) or smart contract for clearing batchesDoes not exist
ZK proof of valid orderProver circuit: order is well-formed without revealing contents or pairDoes not exist
Clearing verificationValidators verify correct batch execution via ZK proofDoes not exist

Possible paths to implementation:

  • Consensus-layer ZIP — new transaction types for order commitments + consensus rule for batch clearing. Most secure, hardest to deploy.
  • Layer 2 / sidechain — batch clearing off-chain, settlement on Zcash via shielded transfers. Easier to deploy, weaker trust assumptions.
  • Smart contract layer — if Zcash gains programmability, ShieldedDEX could be a contract on the shielded pool.

How ShieldedDEX differs from existing systems

PropertyPenumbraAnomaShieldedDEX (this work)
Asset pair hiddenNo (public markets)Partial (solver sees)Yes
Matching methodDeterministic batchSolver-basedDeterministic batch
Solver requiredNoYes (permissionless, competitive)No
Asset-targeted attacksVulnerable (pair known)Solver-dependentResistant (pair hidden)
Formally verifiedNoNoYes (TLC, 48,065 states)
Cross-pair isolation provenNoNoYes (CrossPairIsolation invariant)
Price discovery cost quantifiedNoNoYes (CrossPairPriceConsistency counterexample)

Penumbra hides the swapper's identity but the trading pair and amounts are public (the Swap action includes the TradingPair in cleartext). An attacker can see which markets are active and target them. Anoma delegates matching to solvers who need to see intent contents to construct valid solutions — private solving is a research goal, not a deployed feature. The solver role is permissionless (anyone can run one), but a solver is structurally required for trading. ShieldedDEX occupies a design point neither system has explored: pair-hiding with solver-free deterministic clearing.

What's novel (and what isn't)

The clearing mechanism itself is a batch auction applied per-pair — not a new algorithm. The privacy model is at the mechanism design level, not the cryptographic level (we don't specify ZK circuits). What is new:

  1. Pair-hiding + deterministic clearing — no existing system combines these. Penumbra has deterministic clearing but public pairs. Anoma has privacy but trusted solvers. This is a previously unoccupied design point.
  2. Formal proof: asset-type privacy prevents asset-targeted attacks — the only mechanism in our suite to resist all 6 attack categories (6/6 vs 5/6 for ZKDarkPool/BatchedAuction). TLC-verified, not argued.
  3. Formal proof: privacy does NOT fix the impossibility triangle — a negative result with concrete counterexample (P1@1, P2@2 with no correction). The NoImmediacy invariant confirms batching still sacrifices immediacy regardless of privacy.
  4. The 4th dimension: privacy vs price discovery — extends the impossibility triangle to a tetrahedron. Full asset-type privacy eliminates cross-pair arbitrage, which means price information doesn't propagate across pairs. This tradeoff has not been formalized before.

This spec formalizes the mechanism design that Zcash's ZSA infrastructure makes possible — a blueprint for what could be built once the protocol supports it.

Use cases

ShieldedDEX is not better for everyone — it trades immediacy and price discovery for privacy and MEV resistance. It's suited for scenarios where what you're trading is as sensitive as how much.

Where ShieldedDEX wins:

  • Institutional portfolio rebalancing — a fund selling token X for token Y doesn't want the market to know which pairs they're active in. On Penumbra, observers see "someone is trading X/Y" and can front-run that market. On ShieldedDEX, they see only an opaque commitment.
  • DAO treasury operations — a DAO diversifying from token A to token B. If the pair is visible, the market front-runs the diversification before the DAO can execute.
  • Jurisdictional sensitivity — in some contexts, which asset you trade reveals more than the amount. Pair-hiding prevents asset-targeted surveillance.
  • MEV-free trading without trusting anyone — Anoma hides intents but the solver sees them. Flashbots MEV Share requires trusting the builder. ShieldedDEX has no trusted party — deterministic clearing means validators verify correctness without seeing contents or pairs.

Where other mechanisms are better:

NeedBetter choiceWhy
Trade immediatelyCLOB or AMMShieldedDEX requires waiting for the batch
Always-available liquidityAMMShieldedDEX batches can be empty
Hide order contents only (pair doesn't matter)Penumbra / ZKDarkPoolSimpler, already deployed

The short version: if you only need to hide how much you're trading, Penumbra already works. ShieldedDEX is for when you need to hide what you're trading.

Mechanism diagram

sequenceDiagram
    participant T1 as Trader 1
    participant T2 as Trader 2
    participant S as Shielded DEX
    participant O as Observer

    Note over S: COMMIT PHASE

    T1->>S: shielded commitment<br/>(pair hidden, contents hidden)
    T2->>S: shielded commitment<br/>(pair hidden, contents hidden)
    T1->>S: shielded commitment
    T2->>S: shielded commitment

    Note over O: sees: 4 commitments<br/>can't tell: which pairs,<br/>which directions, what prices

    Note over S: CLEAR PHASE (per-pair, isolated)

    S->>S: clear Pair 1 @ price 1
    S->>S: clear Pair 2 @ price 2

    Note over O: sees: clearing happened<br/>can't tell: which pairs cleared,<br/>at what prices, or how many pairs

    Note over S: DONE: all orders destroyed

    S->>T1: your fills (pair-specific)
    S->>T2: your fills (pair-specific)

    Note over O: cross-pair prices diverged<br/>(1 vs 2) but no one can<br/>see it to arbitrage

Observer information visibility

What an on-chain observer learns:

InformationCentralizedCLOBAMMBatchedAuctionZKDarkPoolShieldedDEX
Order existsYesYes (swap tx)YesYes (commitment)Yes (commitment)
Order direction (buy/sell)YesYesYesNoNo
Limit priceYesN/AYesNoNo
QuantityYesYesYesNoNo
Trader identityYesYes (address)YesNo (ZK proof)No (ZK proof)
Asset pair targetedYesYes (pool)YesYes (pair known)No (pair hidden)
Which pairs are activeYesYesYesYesNo
Number of orders per pairYesN/AYesYesNo
Clearing priceYes (trade-by-trade)Yes (reserves)YesYes (post-clear)Per-pair, hidden
Trade vs transferYesYesYesDistinguishableIndistinguishable

ShieldedDEX reveals strictly less information than every other mechanism. The rightmost column has the most No entries — this is the formal basis for the claim that it provides the strongest privacy guarantees in our suite.

The impossibility triangle is NOT fixed

ShieldedDEX still uses batch clearing, so it still sacrifices immediacy and always-on liquidity. Privacy adds a 4th dimension to the tradeoff space:

        Fairness ── privacy axis ── Privacy
           |                           |
    Immediacy ──────────────── Liquidity

The new tradeoff: privacy vs price discovery. Full asset-type privacy means no one can see cross-pair price divergence, so no one can arbitrage it. Price information doesn't propagate across pairs.

Verified properties (48,065 states)

PropertyTypeDescription
PerPairUniformPriceInvariantAll trades within each pair execute at the same price
PerPairPriceImprovementInvariantTrade price within both parties' limits, per pair
PerPairPositiveTradeQuantitiesInvariantEvery trade has quantity > 0, per pair
PerPairNoSelfTradesInvariantNo self-trades within any pair
CrossPairIsolationInvariantEach pair's clearing depends only on that pair's orders
PerPairSandwichResistantInvariantSandwich pattern yields zero profit per pair + attacker can't target a pair
PostTradeOrdersDestroyedInvariantAfter clearing, orders destroyed across ALL pairs
NoImmediacyInvariantNo trades during commit phase (triangle not fixed)
EventualClearingLivenessBatch eventually clears

Price discovery property (expected to fail)

Add as INVARIANT to see counterexample:

PropertyDescription
CrossPairPriceConsistencyClearing prices across pairs should be consistent (FAILS: P1 clears at 1, P2 clears at 2 — divergence with no correction mechanism because pair activity is hidden)