Introduction
Privé is a zero-knowledge shielded pool for USDG on Robinhood Chain. You deposit USDG, you hold a private note in your browser, and you withdraw to any address by proving in zero knowledge that you own an unspent note. The deposit and the withdrawal are not linkable on-chain. Everything on this page describes a testnet deployment: the contracts are not audited and there is no mainnet.
The problem
A stablecoin transfer on a public chain is a permanent, world-readable record. Anyone with your address can reconstruct your salary, your suppliers, your runway, your counterparties and your balance, forever, without asking you. That is fine for a public treasury and unacceptable for payroll, for invoices, for a personal wallet. Today the only common workarounds are custodial: move funds through an exchange and trust an intermediary with both the privacy and the money.
Privé removes the intermediary. Confidentiality comes from cryptography, not from a company promising to keep quiet, and you never give up custody of your funds.
The mental model
There is one contract, the pool, and it holds USDG for everyone. When you deposit, the pool does not record “this address owns this balance”. It records a commitment: a Poseidon hash of your amount, a pool-assigned label and a precommitment derived from two random secrets (a nullifier and a secret) that only your browser knows. That commitment is appended as a leaf to an on-chain Merkle tree. The secrets stay local. They are your note.
To withdraw, your browser builds a Groth16 proof, locally, with snarkjs. The proof says: I know the secrets behind some leaf in this tree, that leaf has at least this much value, and here is the nullifier hash of the note I am spending. It never says which leaf. The on-chain verifier checks the proof, the pool checks the nullifier hash has not been used before, marks it spent, inserts a fresh change note for the remainder, and pays out. Spending the same note twice is impossible because the nullifier hash is deterministic and the pool remembers it. Linking your withdrawal back to your deposit is impossible because the proof reveals nothing about which leaf you used.
Why this is not a mixer
A mixer is indiscriminate by design: everything that goes in comes out equally clean, and there is no way for an honest user to distinguish themselves from a sanctioned one. Privé follows the Privacy Pools direction instead. The intended end state is that a withdrawal proves membership of a screened association set, published by an Association Set Provider (ASP), so an honest user can demonstrate that their funds originate from a set of deposits that passed screening, without revealing which deposit is theirs. Privacy for the individual, an auditable statement for everyone else.
Be clear about the present tense: that layer is Planned, not live. The withdraw circuit deployed on testnet today constrains a single Merkle tree, the state tree, and nothing else. Its own source comment says as much: “NO ASP”. There is no deposit screening, no approved-set root and no proof of innocence enforced in-protocol right now. In-protocol enforcement is scheduled to land alongside the mainnet audit. Until then, treat Privé as an unaudited privacy primitive on a testnet, not as a compliance product.
Live today vs planned
| Capability | Status | Notes |
|---|---|---|
| Shielded USDG deposits | Live | Commitment inserted into an on-chain LeanIMT. |
| ZK withdrawals | Live | Groth16 proof built in the browser, checked on-chain. |
| Sender / receiver unlinkability | Live | Nullifier hashes prevent double spends without revealing the note. |
| Partial withdrawals | Live | Withdraw any amount. The remainder returns as a change note. |
| Encrypted note backup and restore | Live | PBKDF2 then AES-GCM, passphrase only, done client-side. |
| Claim links | Live | Send a note to someone with no wallet yet. Secret rides in the URL fragment. |
| Gasless relayer | Live | /api/relay submits your withdrawal and takes a fee in USDG. |
| ASP screening and approved-set root | Live | Recomputable attestation from public data. See Compliance model. |
| In-circuit membership enforcement | Planned | The withdraw circuit has no ASP constraint yet. |
| Published TypeScript SDK | Planned | The SDK exists in the repo. It is not on npm yet. |
| Mainnet and audit | Planned | Testnet only. Contracts are unaudited. |
The current deployment
Privé runs on Robinhood Chain Testnet, an EVM chain (Arbitrum Orbit L2) with chain id 46630 and ETH as the gas token. The asset is USDG, the Global Dollar, with 6 decimals. On testnet it is a mock USDG with an open mint, so the faucet in the app can hand you as much as you need. It has no value.
| Contract | Address |
|---|---|
| PrivacyPool | 0xd62C837a70b9552637C8ee1681fb09b459648181 |
| WithdrawVerifier | 0xBAFE6434C40e5582b11bA90cFd6cA1f5ebd904BF |
| MockUSDG | 0xF47593cac046C3a4C15B495eDAd59DE5868B6BbB |
Your notes live in your browser. They are never sent to a server, not to ours and not to anyone else’s. That also means the failure mode is yours: lose the notes and lose the funds. Use the encrypted backup.
Where to next
- How it works: the deposit, proof and withdraw flow, step by step.
- Architecture: circuits, the commitment scheme, the Merkle tree, the relayer.
- Contracts: deployed addresses, the ABI surface and the events to index.
- Testnet guide: add the network, get testnet ETH and USDG, and run a full deposit and withdraw.
- Risk: what can go wrong, and what is not protected.