Protocol flow
ConfidentialSwap is a request-for-quote (RFQ) swap protocol where the trade amounts stay encrypted on-chain end to end, using Zama's FHEVM (fully homomorphic encryption on the EVM). A user posts an intent on one of the registered token pairs, but the amounts (both the input and the minimum output) and the trade direction stay encrypted; market makers compete to fill it; the best quote settles. An observer only ever sees that a swap happened on that pair, never the amounts, the price, or the direction.
The actors
- User (intent maker). Anyone. Creates an intent with encrypted amounts for a registered token pair. (The contract supports an optional maker gateway to gate intent creation; the current Sepolia deployment leaves it open — no gating.)
- Market makers. A whitelisted set (
MARKET_MAKER_ROLE) that submit encrypted quotes and settle the winning one. See the live list on Addresses. - Compliance address. Granted decryption rights over intents for oversight.
- Admin. Manages pairs, fees, the market-maker set, and contract upgrades. A pauser role can pause trading (the admin unpauses).
Lifecycle of a swap
- Create intent. The user encrypts three values in the browser (the input
amount, the minimum acceptable output, i.e. their slippage floor, and the swap
direction) and calls
createIntentfor a registered pair. The input funds are pulled into a per-intent escrow. Each intent snapshots its own quoting and settlement windows (measured in blocks). - Quoting window. Market makers call
quoteIntentwith an encrypted output amount. The contract homomorphically tracks the running best quote without decrypting any of them. A market maker may quote more than once (only its highest is kept), and quotes cannot be cancelled. The user's slippage floor is never shared with market makers. - Resolve. After quoting closes, the best quote is selected (still encrypted) and the winning market maker is determined.
- Settle. The winning market maker calls
settleIntent: the contract pulls the market maker's output tokens, pays the user their output minus the protocol fee, and releases the user's input to the market maker, all as confidential ERC-7984 transfers. If a transfer can't cover the amount, the encrypted success flag stays false and the swap is treated as not filled rather than partially settling; the intent isn't finalized, so the market maker can top up its confidential balance and callsettleIntentagain while the settlement window is still open. - Reclaim. If the intent isn't filled, the user calls
reclaimExpiredIntentto recover the escrowed funds. The timing depends on whether anyone quoted: with no quotes, reclaim opens as soon as the quoting window closes; if any quote was submitted (even one that never cleared the slippage floor, or a winner that never settled), the user must wait until the settlement window expires. Funds are always recoverable, though note that a quoted-but-unfilled intent cannot be reclaimed before that window ends.
Confidentiality model
- Amounts (
euint64) and direction (ebool) are encrypted; the chain stores ciphertext handles, not values. - Decryption rights are granted narrowly via the FHE access-control list: the user can decrypt their own result; the relevant market maker sees only what it needs to quote (the direction and input amount), not the slippage floor; the compliance address can decrypt for oversight.
- The settlement / reclaim verdict is a publicly decryptable boolean, so anyone can tell whether an intent settled or expired. The amounts exchanged stay encrypted: only the parties involved (and the compliance address) can decrypt them.
- Protocol-level analytics can be revealed in aggregate on a fixed interval; by design this is coarse and not intended to deanonymize individual trades.
Escrow & fees
- Input funds live in partitioned escrow wallets managed by the contract, not in users' wallets, for the duration of an intent.
- Each pair carries a fee shift: the protocol fee is
amount >> feeShift(so a larger shift means a smaller fee). The fee is snapshotted onto the intent at creation, so changing a pair's fee never affects in-flight intents. Accrued fees are collected by the configured fee recipient.
Contract architecture
ConfidentialSwapis a UUPS-upgradeable proxy. To stay under the contract-size limit, the heavy lifecycle logic lives in an externalIntentLifecycleLibreached by delegatecall; the proxy keeps the guards (reentrancy, pausable, role checks).- Storage uses ERC-7201 namespaced slots, so upgrades can add state safely.
- Confidential balances are initialized once per token per user (a
wrap(user, 0)no-op) before trading; the dapp batches this through aConfidentialBalanceInitializerhelper.
For the concrete deployment (proxy, helper, tokens, and the market-maker set) see Addresses.