Try the pilot
End-to-end path on Sepolia: deposit → private intent → Uniswap fill → withdraw. Pair: ETH / USDC (USDT slot on Sepolia). 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 | 0x6607…dd030x6607cE016237C3D8969B318018604c09D16fdd03 |
| NoctisExchange | 0xcF13…03620xcF13F272cdc5684c3863b589C2a9fb14A0aa0362 |
| USDC (USDT slot) | 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 0x6607…dd03, Exchange 0xcF13…0362.
- 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), swap intents are encrypted client-side, and settlement runs through Uniswap with the exchange contract as the pool counterparty. The first pair is ETH/USDT (USDC on Sepolia).
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 |
| Pre-trade swap intent (amount ciphertext) | Pool sees the Exchange address |
| 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 desk market panel shows an ETH/USDC Uniswap V2 pool chart and Uniswap V2 pool depth (AMM getAmountsOut ladder) — not a central-limit order book. Your encrypted intents 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 user signs an encrypted intent (EIP-712), including a gas refund amount quoted by the relayer.
- 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 and the gas refund are skimmed from the output to the Safe treasury.
- 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 pull pattern: the user requests a withdrawal through the encrypted debit path, and once authorized, claims the funds in a separate transaction. The recipient is the requester; encrypted destinations are on the roadmap, not in the MVP.
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 can observe intent metadata and can censor or delay, but cannot decrypt user balances and cannot move funds outside the signed paths.
Auditor handoff (threat map, residual risks, review focus): noctis-protocol/docs/B6_AUDITOR_THREAT_MODEL.md. Partner desk steps: noctis-protocol/docs/C3_DESK_RUNBOOK.md.
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.