A Tornado Cash implementation as a Uniswap v4 hook.
The project implements both the privacy-preserving mechanism of Tornado Cash and the AMM design of Uniswap v4.
It provides three key benefits:
- Privacy: Mixes users' funds to hide their identity.
- Yield: Users earn fees by providing liquidity, while mixing their funds.
- Liquidity: A larger TVL for traders.
This project relies on an updated Circom circuit of Tornado Cash (using Poseidon hashing with some small optimizations) and Noir for zk-verification.
Due to limitations of the PoolManager contract, deposits and withdrawals should be performed through the TornadoHookEntry contract.
The contracts can be found in the packages/foundry/ directory.
The project is deployed on Unichain and Unichain Sepolia.
| Contract | Unichain | Unichain Sepolia |
|---|---|---|
| Hook | 0xb09470fad3b3b46fe0e8ec598e799664fe0bcd03 |
0x84Ad671111481c0FcCDDD232df1092C0B1CC4D03 |
| Entry | 0x529c072C3C5979886eDb4E8253C11586Cd8f59dE |
0x37398add74fE0e5c7007Ea67644723BEfe8818A3 |
The frontend: https://tornadohook.vercel.app/
The actual nullifier and secret are computed as keccak256(input) % FIELD_SIZE,
where input is a string from the frontend and FIELD_SIZE = 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001.
To create a proof, first install snarkjs, then follow these steps:
- Open
packages/circuits/circom/main_js/input.jsonand fill it with your inputs. - Go to
cd packages/circuits/circom/main_js. - Then run
node generate_witness.js main.wasm input.json witness.wtns. - And run
snarkjs groth16 prove main_0001.zkey ./main_js/witness.wtns proof.json public.json. - You'll have your proof in
proof.json, thenabi.encodeit to send to the contract.
Check packages/foundry/test/TornadoHook.t.sol for more details.
To create a proof, first install bb, then follow these steps:
- Open
packages/circuits/noir/Prover.tomland fill it with your inputs. - Go to
cd packages/circuits/noir. - Then run
bb prove -b ./target/noir.json -w ./target/noir.gz -o ./target --oracle_hash keccak --output_format bytes_and_fields. - You'll have your proof in
./target/proofand./target/proof_fields.json.
Check packages/foundry/test/TornadoHook.t.sol for more details.
To run tests, simply go to cd packages/foundry and run forge test -vvv.
Unfortunately, there are no withdrawal fuzz tests, because for every deposit you need to create a proof, which can't be done in Solidity.
To run Tornado Hook locally, follow the steps below:
- Install dependencies if it was skipped in CLI:
yarn install
- Run a local network in the first terminal:
yarn chain
This command starts a local Ethereum network using Foundry. The network runs on your local machine and can be used for testing. You can customize the network configuration in packages/foundry/foundry.toml.
- On a second terminal, deploy the contracts:
yarn deploy
This command deploys the smart contracts to the local network. The contracts are located in packages/foundry/contracts. The yarn deploy command uses the deploy script located in packages/foundry/script to deploy the contract to the network.
- On a third terminal, start the NextJS app:
yarn start
Visit the app on: http://localhost:3000. You can interact with the smart contracts using the Debug Contracts page. You can tweak the app config in packages/nextjs/scaffold.config.ts.