Skip to main content

Architecture

The system provides three progressive levels of financial privacy, referred to as Public, Concealed, and Shielded:

  • Public Layer — Standard ERC-20 tokens. Balances and transfers are fully visible on-chain, as with any token contract.
  • Concealed Layer — Balances are stored as ElGamal ciphertexts on-chain. Transfer amounts are hidden, but the transaction graph (who sends to whom) remains visible.
  • Shielded Layer — Funds are deposited into a shared commitment pool and withdrawn via nullifiers. Both amounts and the transaction graph are hidden.

Each privacy layer is implemented across three tiers of software: on-chain smart contracts in Solidity that enforce state transitions and verify proofs, zero-knowledge circuits in Noir that prove correctness of private operations, and client-side libraries in TypeScript that construct transactions and manage local state.

A relayer service sits between users and the blockchain. It abstracts away gas fees and removes the need for users to submit transactions from their own addresses — which would otherwise leak their identity on-chain.

For app developers, the system ships an SDK compatible with web, iOS, and Android (via React Native). Any application wishing to integrate privacy can use the SDK directly — it exposes a high-level interface that hides the complexities of proof generation, encrypted state synchronization, and transaction construction.

┌───────────────────────────────────────────┐
│ Application │
│ (uses SDK) │
└───────────────────┬───────────────────────┘

┌───────────▼───────────┐
│ SDK │
│ (TypeScript, │
│ Noir circuits) │
└───────────┬───────────┘

┌───────────▼───────────┐
│ Partner Backend │
│ (holds SK_partner, │
│ signs requests) │
└───────────┬───────────┘

┌───────────▼───────────┐
│ ERC-4337 Bundler │
└───────────┬───────────┘

┌────────────────▼────────────────────┐
│ Paymaster + SharedAccount │
│ (gas sponsorship, graph privacy) │
└────────────────┬────────────────────┘

┌────────────────▼────────────────────┐
│ Smart Contracts │
│ (Solidity — proof verification, │
│ balance storage, state transitions)│
└─────────────────────────────────────┘

Transaction Submission

Users never submit transactions directly. The SDK constructs a UserOperation (including any ZK proofs) and sends it to the partner's backend. The partner backend signs the request with its registered key and forwards it to an ERC-4337 bundler. The bundler submits the UserOperation to a Paymaster, which sponsors the gas.

For Concealed Layer operations, the UserOperation originates from the user's smart wallet. For Shielded Layer operations (merge, shielded withdrawal), the UserOperation is routed through a SharedAccount — an ownerless smart account that hides the sender's identity on-chain. For details see Relayer.

Compliance

To comply with European regulations, the system includes a compliance component. Although technically intertwined with the Concealed and Shielded Layers — the encryption is enforced inside their circuits — it can be thought of as conceptually independent: everything works without it, and removing it would not break any privacy or correctness guarantees for end users.

The compliance mechanism relies on an auditor party that holds a special decryption key. Whenever a user makes a transaction that hides information — an amount, the origin of funds, etc. — the transaction emits an on-chain event containing that data encrypted under the auditor's public key. The auditor can then decrypt and trace funds when required by law, without any cooperation from the user.

Component Summary

Concealed Balances

Users deposit ERC-20 tokens into the contract, which stores their balance as an ElGamal ciphertext on the Grumpkin curve (encrypted via the user's keypair). Transfers update the sender's ciphertext (proved correct by a Noir circuit) and add the transfer ciphertext to the recipient's balance via on-chain point addition — no decryption needed, thanks to the homomorphic property. The recipient decrypts locally using their spending key, which requires solving a discrete log. For details see Concealed Balances.

Shielded Layer

The anonymous layer breaks the transaction graph. Users deposit from the Concealed Layer into a shared commitment pool via a shielded deposit, then later withdraw to any Concealed Layer account via a shielded withdrawal by proving knowledge of a valid commitment and revealing a nullifier — without linking the withdrawal to the original deposit. A background merge service aggregates multiple notes into one using homomorphic addition. For details see Shielded Layer.

Relayer

The relayer sponsors gas via an ERC-4337 Paymaster and submits transactions on behalf of users, so that users don't need an ETH-funded address — which would link their on-chain identity to their privacy operations. Only authenticated partners can submit requests, so the relayer is protected from abuse. For details see Relayer.

Addressing (BPK)

The system does not use EVM addresses for identifying users. Instead, each user has a Balance Public Key (BPK) — a point on the Grumpkin curve derived from their spending key. On-chain, balances are stored in a mapping keyed by the hash of the BPK, not by msg.sender. This means a user's privacy identity is entirely separate from their Ethereum account: knowing someone's EVM address reveals nothing about their encrypted balance, and vice versa. To send someone funds, you need their BPK. For details on how keys are derived, see Key Management.

SDK

The SDK handles key management, transaction construction, proof generation, balance decryption, and state synchronization behind a high-level TypeScript API. The two most platform-sensitive operations — circuit proving and discrete-log solving — are abstracted behind adapter interfaces, with native implementations for iOS (Rust via MoPro and Expo modules) and WASM fallbacks for web and Android. Key storage is similarly abstracted: MMKV on iOS, localStorage or IndexedDB in the browser, filesystem on Node.