Anyone can deposit. Stolen funds hide among honest ones, exchanges flag every withdrawal, and honest users carry the risk.
Privacy pools on Solana
Private transfers that can prove they’re clean.
Deposit into a shielded pool, withdraw to any fresh wallet, and prove in zero knowledge that your funds come from a clean set, without revealing which deposit was yours.
- Groth16 on BN254 · verified on-chain
- Poseidon commitments · depth-26 tree
- Ragequit: exit to origin, always
Privacy without the dirty money.
Withdrawals carry a proof that the deposit belongs to a set that excludes flagged sources. Your history stays private. The hacker’s doesn’t.
How a clean withdrawal works.
- Deposit
- Association sets
- Prove
- Relay
- Verify
Deposit.
Your browser draws a random nullifier and secret and computes
commitment = Poseidon(nullifier, secret, asset, amount)Only the commitment goes on-chain, as a new leaf in the pool’s depth-26 incremental Merkle tree. The note (nullifier + secret) never leaves your device.
Association sets.
Association Set Providers publish a Merkle root of approved deposits every epoch, under a public policy. The default policy excludes deposits traced to known exploits, drainers and sanctioned addresses.
Prove.
To withdraw, your browser generates a Groth16 proof that you know the secret of a leaf in the pool tree, that the same leaf is in the association set you chose, and that the nullifier hash is new. No leaf index, no deposit address.
Relay.
A relayer submits the withdrawal and pays the fee, so the fresh recipient wallet doesn’t need SOL beforehand. The proof binds the recipient and the fee, so a relayer can’t redirect funds.
Verify.
The Solana program checks the proof with the alt_bn128 syscalls, marks the nullifier spent, and pays the recipient. The protocol fee buys back $CLEAN.
Proof Studio.
Everything cryptographic happens in your browser. Nothing secret is sent anywhere.
- Generate
- Back up
- Sign
Fixed amounts keep every deposit in a pool identical, so none stands out.
Back up your note. Both steps are required before you sign.
- commitment
- Poseidon(nullifier, secret, asset, amount)
- nullifier_hash
- Poseidon(nullifier)
- note
- cleanpools-<asset>-<amount>-<base64url(nullifier‖secret)>
- asset
- wSOL mint as a field element
- amount
- base units
Scope. The address’s last 100 transactions, one hop: a match means a listed address took part in the same transaction. Read from public Solana RPC nodes, straight from your browser.
0 sources in this list, each tied to a public incident report.
Ragequit skips the association set. The deposit goes back to the address that made it, in full and in public.
The key is derived from this note’s nullifier, so it covers this one deposit. It can’t spend the funds and says nothing about your other notes.
- viewing_key
- Poseidon(nullifier, "view")
- reveals
- one deposit: its commitment, its nullifier hash, asset and amount
- keeps private
- your other deposits, balances and addresses
Clean Pools does not accept funds from flagged sources into clean sets. You are responsible for following the law where you live.
Association sets.
Privacy is the default. The set you prove against is your choice.
Default policy v1
- Exploits and drainers. Addresses named in public incident reports are excluded, each with a link to its report.
- Sanctions. Addresses on official sanctions lists are excluded.
- One hop. Addresses funded directly by any excluded address are excluded too.
- Every epoch. The set is rebuilt each Solana epoch. The root and the full list are published together.
- Appeals. The depositing address can sign an appeal. If it’s upheld, the deposit rejoins at the next epoch. Ragequit stays open either way.
computing…A set is a provider key, a policy document and one root per epoch. Each withdrawal names the set it proves against, and the program checks the proof’s association root against that set’s published roots.
hash(provider key, policy hash)public JSON, versionedone per epoch, depth 26every withdrawalNo one can lock you in.
If no association set accepts your deposit, you can always withdraw it back to the address it came from. Publicly, without privacy, but with nothing lost.
Built on Solana’s own primitives.
Syscall. The same BN254 Poseidon the circuit uses, computed by the runtime.
alt_bn128 syscalls, one transaction: point addition, scalar multiplication and the pairing check.
Depth 26 · 67,108,864 deposits per pool.
A and C in G1, B in G2. Small enough for one instruction.
One account per spent note. A second spend can’t create it again.
Fixed denominations make the anonymity set uniform: every deposit in a pool is the same size, so amounts can’t link a withdrawal to a deposit.
Prove your history when you want to.
Export a viewing key for a single withdrawal and hand it to an exchange or an auditor. It shows which deposit the withdrawal came from, and nothing else in your history.
Threat model.
What an attacker can try, and what stops it.
The recipient is a public input of the proof. A copied transaction can only pay the same recipient.
Each withdrawal creates a PDA derived from its nullifier hash. A second withdrawal of the same note fails because that account already exists.
The fee and the recipient are bound in the proof. A relayer can submit the transaction or drop it, never change where the funds go or what it earns.
Groth16 needs a circuit-specific setup. The design requires a multi-party ceremony with a published transcript, so one honest participant is enough.
A withdrawal right after a deposit narrows the set. Wait several epochs and use common denominations. Once the pool is live, the interface shows the current anonymity set size, read from the chain.
The note is the only key to the deposit. Nobody can recover it, including Clean Pools. Back it up before you sign.
$CLEAN.
Every withdrawal pays a 0.25% protocol fee. The fee buys back $CLEAN on the open market.
Relayer fees go to the relayers that submit withdrawals.
$CLEAN is launching on pump.fun
The contract address appears here, in the header and in the footer the moment it exists.
Waiting for the first trades. Stats refresh every 30 seconds.
Questions.
Is Clean Pools a mixer?
It’s a privacy pool with proofs of association. A mixer hides everyone together. Clean Pools lets honest users prove their funds came from a clean set, and keeps flagged deposits out of those sets.
Who decides what’s clean?
Association Set Providers, under published policies. You choose which set to prove against, and you can always ragequit.
Can anyone see my deposit?
Everyone sees that an address deposited a fixed amount. No one can link it to a withdrawal.
What if my deposit is flagged by mistake?
Every policy has an appeal path, and ragequit returns your funds to the original address.
What do I need to keep?
Your note. It’s the only key to the deposit. Clean Pools never sees it.
Is this legal where I live?
Privacy tools are treated differently by different jurisdictions. Check your local rules before you use any privacy protocol.
Where do fees go?
0.25% of every withdrawal buys back $CLEAN. Relayers earn the relayer fee.