The problem
Everything on Solana is public. Every balance, every payment, every counterparty, forever. That is what makes the chain verifiable — and it is also why a salary paid on-chain tells your colleagues what you earn, a donation tells the world your politics, and a treasury's every move is front-run before it lands.
The usual answers move the problem somewhere else. A privacy rollup asks you to trust a sequencer and a bridge. An MPC network asks you to trust that its operators never collude. Confidential token extensions hide amounts but leave the graph of who-pays-whom intact. Each one adds a system beside Solana, and each of those systems has someone who can halt it, censor it, or be compelled to.
Profitable privacy
And privacy, where it exists, has always cost money. A shielded pool protects you better the longer your funds stay in it — time is what separates a deposit from the withdrawal it funds — yet money sitting in a pool has earned nothing. Privacy was paid for in forgone yield, so people stayed as briefly as they could, which made every pool worse for everyone in it.
zkSVM removes the cost. When you shield, your SOL is staked with Jito on the way in, in the same instruction, and what you hold inside the pool is jitoSOL, which appreciates against SOL every epoch. The balance nobody can see grows by itself. The yield is not paid in a reward token and needs no accounting inside the pool: the yield is the asset. On the way out, the pool redeems the jitoSOL with the stake pool and the recipient receives SOL.
The incentive now points the right way. Staying is what makes a pool private, and staying is what pays — for you, and for everyone you are hidden among. It also blunts the oldest leak there is: a round number of SOL goes in, and a different number comes out, later, at a different rate.
What zkSVM is
zkSVM is a shielded pool that is a single Solana program. There is no rollup, no sequencer, no bridge and no operator. There is one program, one tree account and one vault, and the only thing deciding whether funds move is a zero-knowledge proof that the chain itself verifies.
Value in the pool is held as notes — think of sealed envelopes. Each note records an amount and an owner, but only a cryptographic commitment to it ever appears on-chain. The commitments are appended to a Merkle tree that never removes anything.
To spend a note you publish a nullifier — a one-time serial number that says "some note has now been spent" without revealing which — together with a Groth16 proof that you own a real note in the tree, that the nullifier is the right one for it, and that no value was created or destroyed. The program checks the proof using Solana's native elliptic-curve syscalls, records the nullifier, and appends the new notes. Nothing else is learned.
How the yield fits
Notes carry a private asset id, so the pool holds SOL and SPL tokens in one tree, and a transfer never shows which it moved: the two hide each other. Earning needed no new circuit. One instruction deposits into the stake pool by CPI and shields what comes back; its mirror image spends a note and redeems the tokens for SOL, paid to a recipient bound into the proof.
A shield needs no proof because the program, not the depositor, decides what a note is worth. Here it measures what the stake pool actually minted, and refuses a note that claims a single base unit more.
Four operations
| Operation | What the chain records | What stays hidden |
|---|---|---|
| Shield | The depositor and the amount | Who owns the resulting note |
| Transfer | A fee, and whoever submitted the transaction | Sender, recipient and amount |
| Claim | The address that spent | Which note, how much, and to whom |
| Unshield | The recipient and the amount | Which note the funds came from |
Shielding and unshielding are public by design — real SOL crosses the boundary. The privacy is in the link: nobody can connect a deposit to a later withdrawal, and nothing that happens between them is visible at all.
Why this works on Solana, now
Verifying a zero-knowledge proof is far too heavy to run as ordinary program code. It became possible when Solana exposed two things as syscalls: alt_bn128 curve arithmetic and pairings, and a circom-compatible Poseidon hash. With those, a full private transfer — proof verification, two nullifiers, two tree insertions — costs about 172,000 compute units, an eighth of what a transaction may use, and fits in 1,168 of the 1,232 bytes a transaction may carry.
Those are not estimates. They are printed by a test that loads the compiled program into an SVM and replays real proofs through the real syscalls.
Double spends are prevented by the account model itself. A spent note is a program-derived account whose address is the nullifier. Spending creates that account, and the system program refuses to create an account twice. There is no set to search and no flag to forget to check.
The new part: notes that belong to addresses
Every shielded pool to date mints its own keys. To receive privately you must first generate a shielded address and hand it to the sender. Programs cannot take part at all, because a program has no secret to prove knowledge of.
zkSVM adds a second kind of owner: a plain Solana address. Such a note's owner field is simply a hash of the address's 32 bytes. It is spent with claim, and the authorization is nothing more than that address signing the transaction. The proof ties the note to the address; the Solana runtime — which has already verified every signature before the program starts — supplies the consent. No key material enters the circuit.
On most chains this trade is unavailable, because checking an account signature inside a circuit costs millions of constraints. On Solana it is free, and three things follow:
- Anyone can be paid privately, with no setup. The sender needs an address and nothing else. The account need not exist or hold any SOL. Sender and amount are hidden, and — unlike a withdrawal — the value arrives still shielded.
- Programs can hold shielded value. A PDA signs through its program's
invoke_signed, so a DAO treasury, an escrow or a payroll program can own notes and pay out of them. Everyone can see that it paid. Nobody can see whom, or how much. - Multisigs work unchanged. Anything that can sign on Solana can own a note.
The cost is stated plainly: a claim names its owner in public, and whoever created the note can recognize the moment it is claimed. For a treasury that is the point. A person who wants to receive without ever being seen should hand out a shielded address instead.
Three things built on it
Payments that come back. Paying an address has one sharp edge: the recipient needs the note's opening, and if it is lost, so is the money — a pool cannot tell a lost note from a slow recipient. A returnable note is owned by a condition instead of a key or an address: this address, at any time — or the sender, after this date. It is one more way to fill the owner field, and two small circuits that open it. Both ways out spend the same nullifier, so only one can ever land. The sender keeps nothing: the right to take the note back is rebuilt from the chain.
Proof of funds that means now. attest shows that a note holds at least some amount, and nothing else — not which note, not how much more, not whose. The obvious construction is wrong: a note that left the pool last year is still in the tree, and a circuit cannot see whether it was spent. So the note is spent and recreated in the same transaction, and its nullifier going on record is what makes the statement current. The holder appears under a pseudonym that is stable for one verifier and meaningless to every other.
Receipts. A payer can show that a note in the pool pays a given recipient at least a given amount, for a stated purpose, without opening the note. Nothing goes on-chain. A receipt proves the payment, not the payer — the payee could have written the same one — and the documentation says so.
$ZKSVM
The protocol has a token, $ZKSVM, with a supply of one billion. It is not what the pool pays its users in — that is jitoSOL appreciating, which needs no token — so the supply is not spent on attracting deposits.
Its value comes from the pool being used. The protocol takes a fee on earning balances, never on private transfers, and part of that fee buys $ZKSVM back on the open market and burns it. Supply starts at a billion and only falls. People who stake $ZKSVM earn a rate above the pool's base yield.
The loop has one input. More value shielded, for longer, means more fees, more bought back and more burned — and it is also exactly what makes the pool more private. The token's incentive and the pool's privacy point the same way.
Staking is public and the pool is not: a staked position and a shielded balance cannot be connected. The fee schedule, the share that goes to buybacks, the staking terms, the allocation and the mint address are published together before launch.
What you are trusting
Four things, and the list is complete.
- The trusted setup. Groth16 requires a ceremony. If every contributor colluded, they could mint value out of the pool undetectably. One honest contributor is enough, and the ceremony is open: anyone can be that contributor.
- The upgrade authority. The verifying keys are compiled into the program, so whoever can upgrade the program can replace them. It belongs behind a multisig, and eventually burned.
- The circuits. A constraint bug is a mint bug. The circuits are small — the largest is 34,000 constraints, the smallest 1,300 — and they are meant to be read.
- Solana, for ordering, liveness and correct syscalls.
There is no admin key, no pause switch, no allowlist and no configuration. initialize takes no parameters and grants nothing to whoever calls it.
Using it well
A pool hides you among the other people using it, so privacy grows with the crowd. The habits that matter are simple: let time pass between shielding and unshielding, avoid withdrawing the exact amount you deposited, and keep value moving inside the pool — transfers between notes show nothing at all.
The wallet that submits a transaction is visible as its fee payer. The protocol is built for relayers — the fee is paid from inside the pool to whoever submits — so a payment can be carried by someone else entirely.
Notes hold SOL or any SPL token, and a transfer never shows which.
Status
| Program | Anchor, Solana L1, 490 KB compiled |
| Circuits | transfer, unshield, claim, redeem, reclaim, attest, and receipt off-chain — Groth16 over BN254, depth-26 Poseidon tree |
| Verified | Unit, cross-language and end-to-end tests with real proofs on the compiled program |
| Yield | SOL staked as jitoSOL on the way in, redeemed for SOL on the way out; verified against Jito's live stake pool |
| Token | $ZKSVM — one billion supply, fees that buy back and burn, a higher rate for stakers; terms and mint address published before launch |
| Next | The multi-party ceremony, a relayer network |
Read Overview for the constructions and why they are sound, Protocol for the exact wire format, and Privacy model for exactly what each operation shows.