Docs

Hush, on the record.

Hush has two parts. A shielded pool on Robinhood Chain takes your deposit and pays your exit through a Uniswap swap. A planner on Venice turns your sentence into a route and keeps no copy of it. Read the threat model before you deposit, since it lists what each party sees.

Pools
0.05 · 0.5 · 5 ETH
One pool per size
Relayer fee
0.15% floor
15 bps, paid in ETH
Protocol fee
None
Hush takes no cut
Proof
Groth16 · BN254
Poseidon, 7 public signals
Tree
20 levels
1,048,576 notes per pool
Planner
zai-org-glm-5-2
On Venice, zero retention
01The short version

Overview

A plain swap on Robinhood Chain is one transaction from your wallet. A stranger with the explorer open can see what you bought and when, with your balance one click away. Ask a typical AI assistant to plan that swap, and the chat, address included, sits on the provider's servers.

Hush splits the job in two. On chain, your wallet deposits a fixed amount into a pool. At a time you choose, a relayer withdraws that amount through a Uniswap swap and pays a fresh address. Off chain, a model on Venice reads your sentence and Venice keeps no copy.

An observer sees the deposit and the exit, with no public field to join them. Venice sees one sentence for a few seconds, and our server strips any address from it before the call.

02Who sees what

Threat model

Six parties touch a Hush swap, and each one sees a different slice of it.

Chain observer
Sees your wallet send 0.05, 0.5 or 5 ETH into a pool. At some later block it sees a relayer submit a withdrawal that swaps and pays a fresh address. Each pool takes one note size, so the observer can't pair deposit and exit by amount. In a thin pool a patient observer can pair them by timing, and the roadmap lists the planned defense.
Relayer
Receives your proof, the nullifier hash, the recipient and the exit parameters. It learns that someone holds a valid note and where the output goes, and it can't tell which deposit the note came from. If it edits a bound field, the pool rejects the proof.
Venice
Receives the sentence you typed, minus anything shaped like an address, for the seconds a reply takes. Venice says it stores neither prompts nor completions, and its TEE mode makes that claim attestable for the models served that way. Hush calls a standard model today.
This site
Runs no analytics and keeps no database. Your browser pulls prices from DexScreener and quotes from the Uniswap quoter contracts on chain 4663. Two routes run on our server: the planner forwards your sentence to Venice, and the relayer takes a finished proof and submits it. Neither route asks for your wallet address. The relayer learns the recipient, which the exit transaction makes public.
Your wallet
Signs the deposits. You connect through Privy or an injected wallet such as MetaMask or Rabby. Privy knows the login you used, and neither one sees your notes, which your browser keeps in local storage next to the copy you save.
Your network
Your ISP sees that you visited this site, DexScreener and the chain's RPC endpoints. Use a VPN or Tor if you want to hide the visit.
03On chain

Layer 1 · the pool

The pool follows the commitment-and-nullifier design that Ethereum's shielded pools share, down to the incremental Merkle tree from Tornado Cash. We kept the cryptography standard on purpose. Hush adds one thing: the pool swaps on the way out.

Deposit

Your browser draws two random 31-byte numbers, a nullifier and a secret, and hashes them with Poseidon into a commitment. Your wallet sends deposit(commitment) with the pool's denomination as the value. The contract appends the commitment as the next leaf of a 20-level tree and keeps the last 30 roots, so a proof you made against a recent root verifies after new deposits land.

Commitment and note
commitment    = Poseidon(nullifier, secret)nullifierHash = Poseidon(nullifier)note          = hush-eth-<wei>-<nullifier, 62 hex>-<secret, 62 hex>

The note string carries both numbers. Hold it and you can withdraw the deposit from any browser; lose it and the deposit stays in the pool for good. The app saves a copy in your browser and asks you to keep another outside it.

Withdraw and swap

To spend a note, your browser rebuilds the tree from getLeaves and proves in zero knowledge that it knows a nullifier and secret whose commitment sits under a known root. The proof reveals nullifierHash. The contract records that hash and rejects it the second time, so you can spend each note once.

The proof commits to seven public signals, in this order:

SignalBinds
rootA Merkle root from the pool's last 30
nullifierHashPoseidon(nullifier), the note's spent marker
recipientThe address that receives the output
relayerThe address that receives the fee
feeThe relayer's cut in wei, paid in ETH
tokenOutThe token the exit buys, or zero for plain ETH
minOutThe smallest output the swap may return

Change any of them after proving and the verifier rejects the proof. The venue and the pool tier sit outside the proof, so a relayer may route through a different pool, and minOut sets the floor that route has to clear.

HushPool.withdraw
enum Venue { None, V4, V3 }struct Exit { Venue venue; address tokenOut; uint256 minOut; uint24 fee; int24 tickSpacing; address hooks; } function withdraw(  uint256[2] a, uint256[2][2] b, uint256[2] c,   // Groth16 proof  bytes32 root,  bytes32 nullifierHash,  address payable recipient,  address payable relayer,  uint256 fee,                                    // paid to the relayer in ETH  Exit calldata exit                              // venue, token, floor, pool key) external;

The contract verifies the proof and marks the nullifier spent. It pays fee in ETH to the relayer and sends denomination - fee through one of three exits:

None
Plain ETH to the recipient. tokenOut has to be zero.
V4
The pool calls PoolManager.unlock and swaps native ETH in the Uniswap v4 pool with key (ETH, tokenOut, fee, tickSpacing, hooks).
V3
The pool wraps the ETH into WETH and swaps in the pool the v3 factory returns for (WETH, tokenOut, fee).

If the swap returns less than minOut, the transaction reverts and the note stays unspent. The whole exit fits in one transaction, and anyone holding the proof can submit it.

Fixed denominations

Each pool accepts one size: 0.05, 0.5 or 5 ETH. An observer can pair an odd-sized deposit with its withdrawal at a glance, so the contract rejects any other value.

The app splits a larger amount into notes, largest first, and you deposit and withdraw each note on its own. Each extra note costs one more gas payment and one more relayer fee. Anything under 0.05 ETH stays in your wallet.

AmountNotesCountLeft in your wallet
0.3 ETH6 × 0.05 ETH60
1.5 ETH3 × 0.5 ETH30
2.72 ETH5 × 0.5 + 4 × 0.05 ETH90.02 ETH
7.2 ETH1 × 5 + 4 × 0.5 + 4 × 0.05 ETH90
04Off chain

Layer 2 · the agent

The agent turns a sentence into a plan you can check field by field. Our server and a language model read your intent. Your browser does the rest with data from chain 4663.

  1. 01
    Strip

    The /api/plan route removes anything shaped like an address (0x followed by 40 hex characters) and caps the text at 400 characters.

  2. 02
    Parse

    It sends the sentence to zai-org-glm-5-2 on Venice and gets back a JSON intent: amount, source token, target token and slippage.

  3. 03
    Fall back

    If Venice errors or the server has no key, a local parser reads the sentence. The response names the parser that answered.

  4. 04
    Quote

    Your browser asks Uniswap QuoterV2 about the v3 WETH pools and V4Quoter about the native-ETH v4 pools, across the four fee tiers, and keeps the best output.

  5. 05
    Split

    The app cuts the amount into notes, takes the relayer fee off each and shows the minOut each proof will bind.

The server route forwards your sentence without logging it, and the Venice API key stays in the server environment.

The case for Venice

Zero retention
Venice says it stores neither prompts nor completions. Your sentence exists in your tab and, for one request, in Venice's memory. Venice also offers TEE and end-to-end encrypted inference, where that claim is attestable in hardware. The Hush planner calls a standard model today, and the roadmap moves it to an attested one.
Open weights
Venice serves open-weight models with no moderation layer on top. A multi-step plan about a private swap won't stall on the word “private”, and no reviewer reads a queue of your chats.
DIEM
Stake VVV on Venice and you mint DIEM; each DIEM buys a dollar of inference per day. An agent that holds DIEM pays for its own calls, with no card on file.

The planner talks to Venice's OpenAI-compatible API, and you can swap the model with the VENICE_MODEL variable. Hush pays Venice like any other customer. Venice has not endorsed Hush. Read Venice's own description of its agent features at venice.ai/agents.

051.5 ETH into USDG

A swap, end to end

Take the example the app ships with: “1.5 ETH into USDG, quietest route”. Two of the five steps reach the chain.

  1. 01
    Say it

    You type “1.5 ETH into USDG, quietest route” or fill in the form the sentence parses into.

  2. 02
    Plan

    The agent reads 1.5 ETH to USDG. Your browser quotes the USDG pools on Uniswap v3 and v4, and the app cuts the amount into three 0.5 ETH notes. Venice keeps none of it.

  3. 03
    ShieldOn chain

    Your wallet makes three deposits of 0.5 ETH, each with its own commitment. These are the last transactions your wallet signs in the flow.

  4. 04
    Prove

    For each note, your browser builds a Groth16 proof in a few seconds and hands it to the relayer with the recipient and the exit parameters. Leave hours between the three exits, since three withdrawals in one minute read as one trade.

  5. 05
    ExitOn chain

    The relayer submits each proof. The pool checks it and swaps 0.5 ETH minus the fee into USDG for your fresh address. The explorer shows three deposits and three relayed exits, with no field that joins them.

In the app, the planner and the in-tab proof work today, and the dry run checks each proof against a local tree with the real verification key. Deposit and the relayed exit switch on when the pools launch.

06What you pay

Fees

ItemRatePaid to
Uniswap pool fee0.01%, 0.05%, 0.3% or 1%Liquidity providers in the pool the route uses, by tier
Relayer fee0.15% floor · 15 bpsThe relayer, in ETH, to cover gas and reverted submits
Protocol feenoneHush takes no cut
Gasnetwork rateThe relayer, or your wallet if you submit yourself

The relayer takes its fee in ETH from the note before the swap, and the pool swaps the rest. At the floor, the numbers per pool come out like this:

PoolRelayer fee at the floorSwapped
0.05 ETH0.000075 ETH0.049925 ETH
0.5 ETH0.00075 ETH0.49925 ETH
5 ETH0.0075 ETH4.9925 ETH

You can skip the relayer and submit from a connected wallet, and that wallet pays the gas and shows up on the exit. Pick one with no history tied to the wallet that deposited.

07What runs today

Status

The home page shows the same board, and we update this list first when a piece ships.

PieceState
Site, docs and appBuilt
Live quotes from chain 4663Built
Circuit · Groth16, Poseidon, 20 levelsBuilt
Browser proverBuilt
Venice plannerBuilt
MCP serverBuilt
Pool contractsWritten, tested on chain 4663 bytecode
RelayerBuilt · switches on with the pools
Trusted setupDev ceremony · public ceremony before launch
Pools on chainLaunching soon
$HUSH tokenLaunching soon
Last updated 2026-09-11.
08Chain 4663

The contracts

At launch we will deploy a Poseidon hasher, a Groth16 verifier and one HushPool per denomination. The contracts have no owner and no upgrade path, so we can't pause a pool or redirect a note.

ContractAddress on chain 4663
Poseidon hasherLaunching soon
Groth16 verifierLaunching soon
HushPool · 0.05 ETHLaunching soon
HushPool · 0.5 ETHLaunching soon
HushPool · 5 ETHLaunching soon
$HUSH tokenLaunching soon
We post each address here and on X at deployment. Treat any address that shows up somewhere else first as fake.
MerkleTreeWithHistory
Tornado Cash's incremental tree, with Poseidon in place of MiMC. Its constructor derives the zero values from keccak256("hush") mod p, and the tree keeps 30 roots.
Groth16Verifier
The verifier snarkjs exports for the withdraw circuit, with seven public inputs.
HushPool
One fixed denomination of native ETH. It holds the tree, the spent nullifiers and the three exits.
HushPool, the rest of the interface
function deposit(bytes32 commitment) external payable;   // msg.value == denominationfunction getLeaves(uint256 from, uint256 count) external view returns (uint256[] memory);function leafCount() external view returns (uint256);function isSpent(bytes32 nullifierHash) external view returns (bool);function isKnownRoot(bytes32 root) external view returns (bool);function getLastRoot() external view returns (bytes32); event Deposit(bytes32 indexed commitment, uint32 leafIndex, uint256 timestamp);event Withdrawal(address to, bytes32 nullifierHash, address indexed relayer, uint256 fee, address tokenOut, uint256 amountOut);

Your browser and the MCP server rebuild the tree with getLeaves over eth_call, so a withdrawal needs no event logs and works against the public RPCs.

Third-party contracts

The pools and the app call these Uniswap, WETH and token contracts on chain 4663. They exist today, and you can check each one on Blockscout.

ContractRoleAddress
Uniswap v4 PoolManagerSwap venue for V4 exits0x8366a39cc670b4001a1121b8f6a443a643e40951
Uniswap V4QuoterQuotes the native-ETH pools0x8dc178efb8111bb0973dd9d722ebeff267c98f94
Uniswap v3 factoryFinds the WETH pool for V3 exits0x1f7d7550b1b028f7571e69a784071f0205fd2efa
Uniswap QuoterV2Quotes the v3 pools0x33e885ed0ec9bf04ecfb19341582aadcb4c8a9e7
WETHThe pool wraps into it for V3 exits0x0bd7d308f8e1639fab988df18a8011f41eacad73
USDGExit token · Global Dollar0x5fc5360d0400a0fd4f2af552add042d716f1d168
TSLAExit token · Tesla, Robinhood Token0x322F0929c4625eD5bAd873c95208D54E1c003b2d
PONSExit token0x39dBED3a2bd333467115dE45665cC57F813C4571
Multicall3Batches the app's reads0xcA11bde05977b3631167028862bE2a173976CA11

Tests and gas

The contract suite has 28 tests. It runs the pools against Uniswap bytecode from chain 4663 and feeds them real Groth16 proofs from the circuit your browser loads.

CallGas
deposit884,960
withdraw, plain ETH334,223
withdraw and swap, v4404,309
withdraw and swap, v3436,297
Measured by the contract test suite (28 tests) on 2026-09-11.
09Groth16

The trusted setup

Groth16 needs a ceremony for each circuit. The proving key the app uses today comes from a development ceremony with one contributor. We generated the powers of tau ourselves at size 2¹³ and finished each phase with the hash of Robinhood Chain block 60,376,679 as the beacon. The withdraw circuit compiles to 5,318 constraints.

That contributor could forge a withdrawal from any pool that trusts this key. We accept that risk for dry runs and refuse it for real deposits.

Before the pools launch, we will run a public multi-party ceremony and redeploy the verifier with the new key. The new key stays safe as long as one participant destroys their share of the randomness. We will publish the transcript and update this section that day.

ParameterValue
Proof systemGroth16 on BN254
HashPoseidon
Tree20 levels · 1,048,576 notes per pool
Public signals7
Constraints5,318
Powers of tau2¹³ = 8,192
BeaconHash of block 60,376,679 · chain 4663
Contributors1 (development)
Toolingcircom 2.2.3 · snarkjs 0.7.6
10stdio · six tools

For agents: the MCP server

The MCP server gives an agent the flow the app has. It runs on your machine over stdio, and Claude Code, Cursor or any other MCP client can drive it. The note secrets stay inside that process. The agent can see calldata, hashes and the finished proof, and the proof leaves your machine when you hand it to the relayer.

ToolGives your agent
poolsPool sizes, notes deposited, ETH held, relayer status and the $HUSH contract (launching soon).
quoteThe note split for an amount, the output after fees and the minOut each proof will bind.
planAn intent from the Venice planner, plus a quote. The planner receives the sentence and nothing else.
depositA new note, stored in ~/.hush/notes.json, and an unsigned deposit for your wallet to sign.
notesYour local notes and their state on chain: not deposited, unspent or spent.
withdrawA Groth16 proof made on your machine, then a relayer receipt or an unsigned withdraw transaction.

Install

The server ships as one file. Download it, then point your client at it.

Download
curl -O https://hushtrade.xyz/mcp/hush-mcp.mjs
Check the file
curl -O https://hushtrade.xyz/mcp/hush-mcp.mjs.sha256 && sha256sum -c hush-mcp.mjs.sha256
Claude Code
claude mcp add hush -- node /path/to/hush-mcp.mjs
Cursor · ~/.cursor/mcp.json
{  "mcpServers": {    "hush": { "command": "node", "args": ["/path/to/hush-mcp.mjs"] }  }}

The server needs Node 20 or newer. On the first withdrawal it downloads the proving key and the circuit wasm (5.2 MB) from the site and caches them for later runs.

VariableDefaultSets
HUSH_SITEhttps://hushtrade.xyzThe deployment it calls for plans, relays and zk files
HUSH_HOME~/.hushThe folder that holds notes.json and the cached zk files
HUSH_ZK_DIRunsetA folder that already holds withdraw.wasm, withdraw_final.zkey and verification_key.json. The server reads them there and downloads nothing

The server holds no private key. deposit hands back an unsigned transaction for your wallet, and so does withdraw with the relayer off. With the relayer on, withdraw posts the proof to /api/relay, the same route the app calls.

11Next

Roadmap

Public ceremony
A multi-party ceremony for the zkey and a verifier redeploy, before the first deposit.
Pools on chain
Deploy the three pools and post their addresses here and on X. The relayer switches on with them.
$HUSH
The token contract launches soon. We will post the address on X first.
Open relayers
One relayer at launch, run by us, with a 0.15% floor. After that, an open set of relayers that compete on fee.
Timing defense
Random delays in the client between deposit and exit, and a minimum pool size before the app lets you spend a note.
Planner source
Publish the planner prompt and parser so you can check the address stripping against the code.

Last updated 2026-09-11