CORE FEATURE

Privacy Swaps

Swap any amount of tokens privately. The adapter withdraws from DustPoolV2, swaps on a vanilla Uniswap V4 pool, and re-deposits the output as a new UTXO note — all in one atomic transaction.

DEX Fingerprinting

Even after privately receiving ETH through stealth transfers, swapping reveals a pattern. The amount you send to a DEX and the timing form a unique fingerprint. An on-chain analyst can cluster multiple stealth wallets as belonging to the same user just by watching who swaps similar amounts at similar times.

Privacy Swaps V2 (DustSwapAdapterV2) solve this with an adapter pattern. The adapter contract atomically withdraws from DustPoolV2 (proving UTXO ownership via ZK proof), executes a swap on a standard Uniswap V4 pool with no custom hooks, and re-deposits the swap output back into DustPoolV2 as a new UTXO note. The on-chain record never links a specific depositor to a specific swap output.

How Privacy Swaps Work

  1. 01

    Prove ownership of UTXO notes in DustPoolV2

    Your browser generates a FFLONK proof using the standard DustV2Transaction circuit (~12,400 constraints). The proof demonstrates you own valid notes in the pool without revealing which ones. Public signals: merkleRoot, null0, null1, outC0, outC1, pubAmount, pubAsset, recipient, chainId. The recipient is set to the adapter contract address, not a user wallet — the adapter receives the withdrawn funds to execute the swap.
  2. 02

    Choose swap parameters

    Select the token pair (e.g., ETH to USDC), the amount to swap, and a minimum output amount for slippage protection. Unlike V1's fixed denominations, you can swap any arbitrary amount. The adapter will use a vanilla Uniswap V4 pool — no custom hooks or special pool contracts needed.
  3. 03

    Submit to relayer

    The proof and swap parameters are sent to the relayer (same-origin Next.js API at /api/v2/swap). The relayer validates the proof format, verifies the chain ID matches, confirms the proof recipient is the adapter contract, and checks nullifier freshness. It then submits the transaction to DustSwapAdapterV2.executeSwap().
  4. 04

    Atomic execution: withdraw → swap → re-deposit

    The adapter contract performs three operations in a single transaction: (1) calls DustPoolV2.withdraw() with the ZK proof to release funds, (2) swaps the withdrawn tokens on the vanilla Uniswap V4 pool via the V4 PoolManager, (3) computes a Poseidon commitment for the swap output and deposits it back into DustPoolV2. If any step fails, the entire transaction reverts — there is no intermediate state.
  5. 05

    Receive new UTXO note

    The swap output is a fresh UTXO note in DustPoolV2 with a new Poseidon commitment. Your browser stores this note (encrypted with AES-256-GCM in IndexedDB). You can later withdraw, transfer, or swap this note again — it is indistinguishable from any other note in the pool.

Architecture

User browser └─ generates FFLONK proof ──► Relayer (/api/v2/swap) (9 public signals: └─ validates proof + chainId merkleRoot, null0, └─ DustSwapAdapterV2.executeSwap() null1, outC0, outC1, │ pubAmount, pubAsset, ├─ (1) DustPoolV2.withdraw(proof) recipient=adapter, │ └─ verifies FFLONK proof chainId) │ └─ marks nullifiers spent │ └─ releases funds to adapter │ ├─ (2) Uniswap V4 PoolManager.swap() │ └─ vanilla pool (no hooks) │ └─ ETH ↔ USDC at market rate │ └─ (3) DustPoolV2.deposit(newCommitment) └─ Poseidon commitment for output └─ new UTXO note in pool

V2 vs V1 Architecture

PropertyV1V2
Swap amountsFixed denominations onlyArbitrary amounts
Pool typeCustom DustSwapPool contractsVanilla Uniswap V4 pool
HookDustSwapHook (beforeSwap/afterSwap)No hooks — standalone adapter
Proof systemGroth16 (PrivateSwap.circom)FFLONK (reuses DustV2Transaction)
Deposit stepSeparate deposit into DustSwapPoolUses existing DustPoolV2 notes
OutputTokens to stealth addressNew UTXO note in DustPoolV2
ContractsDustSwapPool + DustSwapHook + DustSwapRouterDustSwapAdapterV2 (single contract)
Wait period50-block minimum waitNone required

Key Properties

Arbitrary amounts

No fixed denominations. Swap any amount from your DustPoolV2 notes. The UTXO model handles change automatically via the 2-in-2-out circuit.

Atomic three-step execution

Withdraw, swap, and re-deposit happen in a single transaction. There is no intermediate state where funds are exposed or linkable.

Vanilla Uniswap V4 pool

Swaps execute on a standard Uniswap V4 pool with no custom hooks. This means better liquidity, no hook-specific attack surface, and compatibility with any V4 pool.

Reuses DustV2Transaction circuit

No separate swap-specific circuit. The adapter reuses the same FFLONK proof from DustPoolV2 withdrawals, reducing proving complexity and audit surface.

Output stays in the pool

Swap output is re-deposited as a new UTXO note in DustPoolV2. Funds never touch an external address during the swap, maximizing privacy.

Slippage protection

The adapter enforces a minimum output amount (minAmountOut). If the Uniswap V4 swap returns less than this threshold, the entire transaction reverts.

Chain ID binding

The chain ID is a public signal in the FFLONK proof. A proof generated on Ethereum Sepolia cannot be replayed on Thanos Sepolia or any other chain.

Relayer-based submission

A same-origin relayer submits the transaction, paying gas on behalf of the user. The relayer fee is capped at 500 bps and validated before submission.

UTXO notes are local

Your deposit notes are encrypted and stored in IndexedDB. If you clear browser data or switch devices, you lose the ability to generate withdrawal proofs. Export and back up your notes from the Settings page.

Gas cost

A privacy swap costs approximately 580,000 to 900,000 gas — covering FFLONK proof verification, the Uniswap V4 swap, Poseidon commitment computation, and the re-deposit into DustPoolV2.
FFLONKDustV2TransactionUniswap V4BN254Adapter PatternArbitrary AmountsChain ID BindingSlippage Protection