Shield every transfer.
Leave zero trace.
Deposit SOL anonymously into a shielded cryptographic pool. Generate Groth16 zero-knowledge proofs completely in-browser. Withdraw to any address with zero on-chain link.
Deposit SOL anonymously into a shielded cryptographic pool. Generate Groth16 zero-knowledge proofs completely in-browser. Withdraw to any address with zero on-chain link.
// Cryptographic log console
> Waiting for shield initialization...
Your deposit is hashed into a Poseidon commitment leaf in an on-chain depth-4 Merkle tree.
Groth16 ZK
Proving Engine
Poseidon
Hash Function
BN254
Elliptic Curve
Solana
Chain
WASM
Proof Runtime
Deposit SOL. A Poseidon commitment is computed from a browser-generated secret note and registered as a leaf in the on-chain Merkle tree.
Deposit StageA Groth16 zero-knowledge proof is computed locally in WASM, attesting you own a valid note in the Merkle tree without revealing which one.
Proving StageSubmit the proof and a one-time nullifier on-chain. Funds are released to any address, blocking double-spends while remaining completely untraceable.
Withdrawal StageDiscover how Veil makes private transfers simple and verifiable.
Zero wallet links, zero trace. All proofs verified on-chain.
Every proof is generated locally in your browser using WebAssembly. Nothing private ever leaves your device. The on-chain contract only sees a cryptographic proof, never your wallet address, deposit amount, or note.
256-bit
Cryptographic security
<2s
Proof generation time
0
Wallet links on-chain
Groth16
ZK proof system
Every deposit updates a public Merkle tree. Zero-knowledge proofs verify path elements and valid secrets completely in-memory, leaving zero trace in transaction graphs.
Commitment hash: Verifiable publicly, yet completely unlinkable to your wallet.
Merkle Root Update: Registers your token without listing keys or amounts.
ZK Proof Verification: Attests tree membership while disclosing zero indices.
Double-Spend Nullifier: Prevents duplicate spends with zero reference to deposits.
| 1 | template Withdrawal(levels) { |
| 2 | // Private - never broadcast on-chain |
| 3 | signal private secret; |
| 4 | signal private pathElements[levels]; |
| 5 | |
| 6 | // Commitment = Poseidon(secret) |
| 7 | component h = Poseidon(1); |
| 8 | h.inputs[0] <== secret; |
| 9 | signal commitment <== h.out; |
| 10 | |
| 11 | // Verify Merkle path membership |
| 12 | component tree = MerkleProof(levels); |
| 13 | tree.leaf <== commitment; |
| 14 | tree.root === merkleRoot; // Public |
| 15 | |
| 16 | // Nullifier prevents double-spend |
| 17 | component n = Poseidon(2); |
| 18 | n.inputs[0] <== secret; |
| 19 | n.out === nullifier; // Public |
| 20 | } |