Notes and proofs
When you deposit, the pool records a note: a hash of the token, the amount and an owner tag. Only the hash goes on chain. Your browser keeps the amount and the secret that opens it, encrypted to your own key inside the same transaction, so any device with your key can find it again.
To spend, your browser builds a Groth16 zero-knowledge proof. It shows that the notes you spend are in the tree, that you hold their key, that they have not been spent before, and that inputs equal outputs plus whatever leaves the pool. It does not show which notes they were.
Your key comes from one wallet signature. The same wallet always gives the same key, and the key never leaves the tab: reload the page and you sign again.
pk = Poseidon(sk) ownerTag = Poseidon(pk, blinding) fresh for every note and position commitment = Poseidon(token, amount, ownerTag) nullifier = Poseidon(sk, commitment, leafIndex) published when spent
Who sees what
Darkpool hides who. It does not hide how much once value meets a pool or the vault, because they have to price it. Read this table before you rely on it.
| Item | Public | Notes |
|---|---|---|
| Deposit: wallet, token, amount, time | Yes | The way in is public. |
| Withdrawal: address, token, amount, time | Yes | Use a fresh address and a round amount. |
| Your private balance | No | Only note hashes are on chain. |
| Private send between users: who, how much | No | Both sides stay inside the pool. |
| Swap: pool, size in and out | Yes | The wallet behind it is not. |
| Position: market, side, size, entry | Yes | Needed so anyone can close it out. Owner is a one-time tag. |
| Pool or vault share size | Yes | Owner is a one-time tag. |
| Which wallet paid for any of the above | No | The relayer sends and pays gas. |
| Your IP address | To the relayer and our server | Use a VPN or Tor if that matters to you. |
What can still link you
- Depositing a rare amount and withdrawing it minutes later.
- Opening a position right after a deposit of the same size, when few people are trading.
- Withdrawing to the wallet you deposited from.
- Paying gas from your own wallet instead of the relayer.
Spot
Each stock token has a constant-product pool against USDG inside the pool contract. A swap spends your USDG (or token) notes, the pool prices it, and the output is minted as a new private note to a fresh tag. Fee 0.25%, paid to the pool's providers. You set the minimum you accept; below it, nothing happens.
Pool prices can drift from the stock's real price. The trade ticket shows the gap against the oracle before you send.
Perps
Long or short a stock token's price at 1x to 3x, with USDG margin from your private balance. The vault takes the other side.
| Price | Oracle price pushed by our relay from Hyperliquid's 24/7 stock markets, with Chainlink's stock feeds on Robinhood Chain shown next to it as a reference. |
| Trading fee | 0.10% of size when you open and again when you close. |
| Borrow fee | 0.002% of size per hour. |
| Closed out | When margin plus profit minus fees falls under 10% of size. Anyone can do it and earns up to 0.5% of size. |
| Profit cap | 100% of size per position. The vault keeps that much free for every open position. |
| Market hours | Prices move around the clock, also when US exchanges are closed. Weekend prices can differ from Monday's open. |
Closing needs a proof that you own the position's tag. The payout lands as a new private note.
Pools and vault
Add one token from your private balance and Darkpool swaps half so both sides match, then records your share under a tag. To leave, prove the tag and get both tokens back as private notes. The first deposit into an empty pool sets its price and comes from a wallet, so it is public.
The vault holds USDG. It earns trading fees, borrow fees and traders' losses, and pays traders' profits. Its share price does not count open profit and loss until positions close.
Relayer
If your wallet sent the proof, the chain would show your wallet as the sender. So a relayer sends it and pays the gas. Its fee and address are inside the proof: it cannot raise the fee, change the recipient or keep your money. If it refuses, nothing is lost; you can send the same proof yourself (and give up the wallet privacy). On testnet the relayer fee is zero.
Circuits
| joinsplit | 2 notes in, 2 notes out, one token, Merkle depth 20 (about one million notes). 26,431 constraints. About 3 seconds in a laptop browser. |
| ownership | Proves you know the key behind a position, pool share or vault share tag. About 0.5 seconds. |
Circom 2.2.2 with circomlib Poseidon, Groth16 over BN254, verified on chain by contracts generated from the keys. The trusted setup is a single-party testnet ceremony: whoever ran it could, in theory, forge proofs. A mainnet version needs a public multi-party ceremony first.
Keys: joinsplit.vkey.json ยท ownership.vkey.json
Contracts
Robinhood Chain testnet. The pool has no admin and no pause; its module list was set once at deployment and can never change.
| Loading addresses... |
| Contract | Can | Cannot |
|---|---|---|
| TacitPool | Hold every token, keep the note tree, verify proofs, pay modules out of their own ledger. | Move a note without a valid proof. Be paused or upgraded. |
| TacitSpot | Price swaps, record pool shares. | Hold or move tokens; it pays out only what its ledger holds. |
| TacitPerps | Open, close and liquidate positions, run the vault. | Touch a healthy position. |
| OracleAdapter | Accept prices from the approved relay inside fixed bounds (1 to 100,000 USD, 7 days old at most). | Move funds. |
Risks
- Not audited. Contracts and circuits were tested (24 contract tests, an end-to-end run with real proofs) but nobody independent has reviewed them.
- Testnet setup. The proving keys come from a single-party ceremony.
- Leverage. At 3x a 23% move against you closes the position and you lose the margin.
- Oracle. One relay pushes prices. If it stops, opening and closing positions stops until a fresh price lands.
- Pools. Providers can get back a different mix of tokens than they put in.
- Your key. Anyone who gets the signature from the Darkpool key message can spend your notes. Sign it only on this site.
- Stock tokens. They follow a stock's price and are not shares.
API
The same public data the app reads. No keys, no accounts.
| GET /api/config | Chain, contract addresses, tokens, relayer, parameters. |
| GET /api/events?from=N | Every pool, spot and perps event from position N, decoded. Scan it with your key to rebuild your notes. |
| GET /api/markets | Oracle, pool and reference prices, reserves, open interest, vault. |
| GET /api/candles?symbol=TSLA&res=60 | Price candles (15, 60, 240, D). |
| GET /api/positions | Every open position as the chain shows it. |
| POST /api/relay | Send a finished proof: { fn: "transact" | "ownerAction", args }. |
| POST /rpc | Read-only JSON-RPC to Robinhood Chain testnet, plus sendRawTransaction. |
Terms
Darkpool is experimental software on a test network. Test tokens have no value. Nothing here is investment advice or an offer of securities. Darkpool is an independent project and is not affiliated with Robinhood, Chainlink or the companies behind the stock tokens. The server keeps no accounts and runs no analytics; it logs relayed transaction hashes and rate-limit counters.