Try the pilot
End-to-end path on Sepolia: deposit → private intent → Uniswap fill → withdraw. Pair: Registered tokens / USDC. Protocol fee 0.05%.
- 01
Connect on Sepolia
Open the desk, switch the header to Sepolia, and connect a wallet with test ETH and USDC.
- 02
Deposit
Deposit into the vault. The on-chain deposit tx is public; the resulting vault balance is an FHE ciphertext only you can userDecrypt.
- 03
Private swap intent
Sign an encrypted amount (EIP-712). The relayer submits the meta-tx; your wallet is not the Uniswap sender.
- 04
Settle & withdraw
After gateway decryption proofs, the exchange fills on Uniswap V2. Net output credits your encrypted balance — then withdraw via the pull path.
In the desk, use Reveal trades for private userDecrypt of your history (browser-only cleartext). Activity indexes orders without a public trader field.
Deployed contracts
Single source of truth: noctis-protocol/deployments/sepolia.json. Addresses below match the live desk env.
| Contract | Address |
|---|---|
| NoctisVault | 0xe8a8…a8c70xe8a8f4B3900C0B7565e1177B5CA2E6CDd816a8c7 |
| NoctisExchange | 0x04FC…1e4d0x04FCF0DD74A6e958A75774e4f042CB32EFB81e4d |
| USDC (quote token) | 0x1c7D…7238 |
| Fee | 5 bps (0.05%) → Safe treasury |
| Subgraph | Studio query v0.8.0 |
Ops: Safe admin, dedicated RELAYER_ROLE, on-contract pause, TimelockController on sensitive exchange params. External audit planned before uncapped mainnet TVL.
Complementary to Confidential RFQ
Zama Confidential RFQ is a confidential swap venue. Noctis is a desk that keeps vault balances and intents encrypted, then settles against existing Uniswap V2 liquidity. Same FHE stack; different product surface.
| Confidential RFQ | Noctis | |
|---|---|---|
| Role | Confidential venue | Private AMM desk |
| Liquidity | RFQ market makers | Uniswap V2 pools |
| Encrypted | Trade size & direction | Vault balances + intents |
| Clear at fill | Per RFQ design | Uniswap fill size (honest boundary) |
| Business | Protocol venue | 0.05% desk fee · B2B desks |
One line: RFQ proves confidential execution; Noctis brings confidential accounting to the Uniswap liquidity traders already use.
For reviewers
Fast path if you are evaluating Noctis for the Zama ecosystem (Startup / Builder tracks):
- Run the desk walkthrough above on Sepolia (wallet + test funds).
- Verify contracts on Etherscan: Vault 0xe8a8…a8c7, Exchange 0x04FC…1e4d.
- Read Privacy boundary — we document what is encrypted and what is not.
- Source monorepo: https://github.com/Noctis-Protocol/noctis (protocol, frontend, keeper, subgraph).
- Security: CEI, ReentrancyGuard, SafeERC20, pull withdrawals, FHE.select sufficiency, gateway-signed cleartext, Safe + timelock ops.
Contact via the Startup Track application or GitHub issues on the public repo. We can run a live Sepolia office-hours demo on request.
Overview
Noctis is a privacy layer on Uniswap: a vault contract, an exchange contract, a single relayer, and this desk UI. Vault balances are stored as FHE ciphertexts (euint128), orders are relayer-submitted so the trader address never appears on-chain, and settlement runs through Uniswap with the exchange contract as the pool counterparty. Pairs are registered base tokens traded against USDC.
Noctis is not a mixer, not an internal order-book matcher, and not a multi-DEX aggregator. It does not claim complete privacy: the boundary below is exact.
Privacy boundary
| Encrypted | Clear at settlement |
|---|---|
| Vault balances | Uniswap fill size |
| Order size, end to end (browser-encrypted FHE input — opaque to the relayer and to calldata) | Pair, direction and a one-time vaultId in relayed calldata |
| Desk trade history (FHE userDecrypt — Reveal trades) | Deposit and withdraw transactions, attributable on-chain |
Activity keeps swap sizes as 🔒 until you reveal them with a wallet signature. That cleartext stays in your browser only. Your trades appear in Recent activity via on-chain getMyOrder (the subgraph indexes orders anonymously — no trader field). Amount ciphertexts sit on-chain as opaque FHE handles, not plaintext. Flashbots reduces mempool MEV; it does not hide the Uniswap fill after inclusion.
The order size is encrypted end to end. Your browser encrypts the amount with the Zama SDK (FHE ciphertext + ZK input proof) before anything leaves the page: the relayer, the transaction calldata and the on-chain order all carry an opaque handle, never the plaintext. The size only becomes public at settlement, where the Uniswap fill reveals it anyway. The vaultId in calldata is a one-time pseudonym: it rotates every time an order fills or cancels, so your orders never cluster under one id. Withdrawal payouts are batched into time windows to break fill-to-payout timing, and support stealth exits: the payout destination is encrypted in your browser and revealed on-chain only when the payout executes, so funds can land on a fresh address with no prior link to you. The payout is unlinkable to the request: the request event is anonymous, request ids are pseudo-random, and the keeper — not your wallet — signs the execution at the batch window boundary. Residual metadata: the pair and direction stay visible in relayed calldata. The relayer can censor or delay, but cannot read amounts, alter the EIP-712-signed parameters, or decrypt vault balances.
The desk market panel shows the selected pair's Uniswap V2 pool chart and pool depth (AMM getAmountsOut ladder) — not a central-limit order book. Your orders never appear on that ladder.
Architecture
Six components, one settlement path. The wallet talks to the vault directly for deposits; swaps go through the relayer as meta-transactions.
Swap lifecycle
The canonical private market swap, end to end:
- 01The browser encrypts the order amount (Zama FHE input + ZK proof) and the user signs the resulting handle (EIP-712), including a gas refund amount quoted by the relayer. The relayer never sees the size.
- 02The relayer verifies the signature off-chain and creates the order on the exchange contract.
- 03The exchange requests decryption of the amount, and of balance sufficiency on sells, through the Zama Gateway.
- 04With the decryption proof verified on-chain, the exchange swaps on Uniswap as a proxy.
- 05At settlement, the 0.05% fee goes to the Safe treasury and the gas refund goes to the relayer wallet, both skimmed from the output.
- 06The net output is credited back to the user's encrypted vault balance.
Honest limit: the fill size is clear when Uniswap executes, and the pool sees the exchange contract. Your Activity feed can still show encrypted sizes until you reveal them privately (ACL + userDecrypt). The relayer's gas is repaid in kind from the swap output, capped on-chain; if the fee plus refund would consume the output, settlement reverts.
Deposits & withdrawals
Deposits go straight from the wallet to the vault, no relayer involved. The amount and sender are public; the resulting vault balance is encrypted. Rate limit: one deposit per block, per user, per asset.
| Asset | Min | Max |
|---|---|---|
| ETH | 0.005 | 100 |
| USDT / USDC | 10 | 1,000,000 |
Withdrawals follow a two-step pattern: the user requests a withdrawal through the encrypted debit path, and the keeper automatically executes the payout at the next batch window — the requester's wallet never signs the payout path. The destination can be an encrypted stealth address — hidden on-chain until the payout itself — with ETH pushed directly so the fresh address never needs gas to receive it.
Security model
The contracts follow standard hardening patterns throughout:
- Checks-Effects-Interactions ordering and reentrancy guards on every state-changing entrypoint.
- Balance sufficiency enforced with FHE.select before any encrypted subtraction, so a failed check can never underflow a balance.
- Gateway signatures verified on-chain before any cleartext deduction or withdrawal, with hard caps on amounts.
- Chainlink oracle with deviation bounds and slippage floors on swaps.
- Role-scoped access control (relayer, pauser, params) with a timelock on sensitive admin changes, and an emergency pause.
- Pull-based claims for withdrawals rather than push transfers.
Trust model
Decryption relies on the Zama Gateway and its KMS. We do not claim this is trustless. Defense in depth compensates: deposit and withdrawal caps, on-chain balance checks, emergency pause, suspicious-value events, and a timelock on admin surfaces. The single relayer sees the trader identity, pair and direction of the orders it relays — but not the size (encrypted end to end). It can censor or delay, but cannot decrypt balances or amounts, cannot alter signed parameters, and cannot move funds outside the signed paths.
Privacy hygiene (not mixer tech): avoid size-matching a deposit to the next fill, hold vault inventory across swaps, prefer partial withdraws.
Fees
The protocol fee is set on-chain at 5 basis points (0.05%) at launch, capped at 30 basis points, and changeable only through the params role behind the timelock. Fees accrue to a Safe treasury. The relayer's gas is repaid from the swap output at settlement, quoted before signing and hard-capped on-chain.
Stack
| Network | Sepolia live · Mainnet Phase D (switch in header) |
| FHE contracts | @fhevm/solidity 0.11.1 |
| Client SDK | @zama-fhe/relayer-sdk 0.4.1 |
| Hardhat plugin | @fhevm/hardhat-plugin 0.4.2 |
| Frontend | Next.js, wagmi, Tailwind |
| Relayer | Node / Express, Docker Compose |
| Indexing | The Graph |
For the product story and what Noctis protects in practice, see the about page.