HHamza Yassine
All work
Nought logo
LIVE · 2026

Nought

Trade stocks and crypto off the public record

A zero-knowledge shielded pool on Robinhood Chain. You deposit tokenized stocks, stablecoins or ETH, move them privately inside one shared pool, and withdraw to a fresh address nothing on chain connects back to you. I built the whole product for a client: circuits, contracts, an in-browser prover, a staked relayer network and the indexer behind it.

Live app Website Docs Full product · for a client
Nought brand
34,248
circuit constraints
12
trusted setup contributors
724
tests across the stack
Context

A public ledger never forgets

Robinhood Chain puts tokenized stocks on a public ledger. Trading them from a fresh wallet feels private, but it is only pseudonymous: every trade that wallet makes is public forever, and one link to an identified source, like an exchange withdrawal, unmasks the whole history at once.

The usual fix is encrypting balances. That hides the numbers, but the accounts and the transaction graph stay public, and the graph is usually enough to identify someone. The client wanted the links themselves gone, so there is nothing left to follow, and hired me to build the whole thing.

The idea

Break the links, not just hide the numbers

Nought is a Zcash-style shielded pool. When you deposit, the chain stores a Poseidon commitment in a Merkle tree, not a balance. To spend a note you publish its nullifier and a Groth16 proof that you own some note in the tree and that value in equals value out. The proof never says which note, so the deposit and the withdrawal have nothing in common that anyone can see.

Withdrawals go to a fresh address through a relayer that pays the gas, because a wallet paying its own gas would give the game away. The recipient, amount and fee are locked inside the proof, so the relayer can submit your transaction but cannot redirect or change it.

Nought landing page: 'Leave nought behind' with a book of tokenized stock positions shown as hidden

nought.cash. Tokenized stocks, stablecoins and ETH in one shielded pool.

Highlights

What makes it interesting

A privacy protocol is a system, not one contract. I built every layer. The parts I'm proudest of:

One pool for every asset

Each note carries its asset ID inside the commitment, and the circuit proves value is conserved per asset. Stocks, stablecoins and ETH share one crowd instead of splitting it into a thin pool per token.

Proofs built in your browser

The app generates Groth16 proofs client-side, so keys and notes never touch a server. Notes are found by trial-decrypting encrypted outputs on chain, which means a wallet can be rebuilt from chain data alone.

Relayers that can't drop you quietly

Relayers bond $NOUGHT and sign an EIP-712 receipt for every job they take. Miss the deadline and anyone holding the receipt can slash a quarter of their stake. The registry has no admin and every parameter is immutable.

Honest about the crowd

Privacy comes from other people holding the same asset. The app reads the live pool and tells you when you would be alone in it, because then shielding hides nothing.

Circuits

Zero-knowledge, constraint by constraint

The main circuit is a 2-in, 2-out join-split written in Circom: two notes in, two notes out, over a Merkle tree 26 levels deep with 248-bit amounts and eight public inputs. It compiles to 34,248 constraints on BN254. The circom compiler is pinned and hash-verified on install, because a different compiler can emit a different circuit and silently invalidate every proof.

The details that matter are small. A range check on the Merkle path bits is what stops one note from producing several valid nullifiers. Trees rotate when they fill, and a sealed tree's final root stays valid forever, so a full tree can never strand a balance.

Nought app: the shield form next to a live panel listing what the chain can see about the transaction

Shielding in the app. The right side shows exactly what the chain learns, and the warning shows up whenever nobody else holds the asset yet.

Trusted setup

A proving key built by twelve people

Groth16 needs a trusted setup, and whoever holds its leftover secret could forge proofs and drain the pool without a trace. So the key was built in a chain of contributions: 12 people across two phases of six, with nobody in both. Forging a proof would need every contributor in both groups to have kept their secret and colluded.

The deploy script is strict about what it ships. It refuses to spend gas until the verifier it is about to deploy is byte-for-byte the one exported from the ceremony key, and after deploying it pushes a real proof through the live verifier before anything else happens.

Nought trusted setup page: 12 contributors, split six and six across two phases, none in both

The trusted setup page. Every contributor, both beacons and a script that re-derives the key are public.

Security

Reviewed in the open, round after round

Nought was reviewed by an independent Robinhood contributor in an AI-assisted security review using OpenAI Codex, at a fixed commit. It's a point-in-time review, not a warranty or a formal certification, and one documented nullifier and tree-rotation risk remains accepted by the project. The full report is public with its hashes.

The review ran over dozens of rounds and raised one critical and five high-severity findings among many smaller ones, all closed at the reviewed commit. I fix a finding first, then write a test that fails when the fix is reverted, then break the guarantee on purpose to prove that test catches it. That habit is how the codebase got to 724 tests across contracts, scripts, app and API. Every Solidity contract is verified on Blockscout and Sourcify.

Launch

Live on Robinhood Chain

The pool launched on mainnet closed. Assets were admitted, governance was handed to a cold wallet, and only that wallet could open deposits. Every path was then run against the live pool with real money: shield, a shielded send, an exit through a bonded relayer, an exit with no relayer at all, and a wallet rebuilt from chain data alone. Every amount matched to the wei.

Shielding is free, and there is no code path that could ever charge for it. Unshielding costs 0.8%, the bytecode caps it at 1%, and any increase has to be announced seven days ahead so people can leave at the old rate.

Circom 2.2.3snarkjsGroth16PoseidonSolidity 0.8.24HardhatReactViteTypeScriptethersNode.jsExpressEIP-712VercelRailway