A simple zero-knowledge mixer built using Noir, Solidity, and Foundry, inspired by Tornado Cash.
This project was built alongside the Cyfrin Updraft course and its tutorial.
zkMixer enables private deposits and withdrawals of a fixed ETH amount using zero-knowledge proofs.
It ensures that users can withdraw funds without revealing which deposit belongs to them, maintaining privacy on-chain.
-
Deposit
- The user locally generates two random values: a
nullifier(to prevent double spends) and asecret(for uniqueness). - Using these, a commitment is created:
commitment = Poseidon2(nullifier, secret) - The user calls
deposit(commitment)on the contract, sending 0.001 ETH. - This commitment is inserted as an updated leaf in the on-chain Incremental Merkle Tree, representing all valid deposits.
- The Merkle root updates, but the link between the deposit and the depositor remains private.
- The user locally generates two random values: a
-
Withdraw
- When withdrawing, the user provides:
- The Merkle proof showing their commitment exists in the current tree.
- A nullifier hash (
Poseidon2(nullifier)) ensuring their deposit hasn’t been withdrawn before. - The recipient address, which can be any Ethereum account.
- A Noir circuit verifies these values off-chain and generates a zero-knowledge proof confirming validity without revealing which leaf belongs to the user.
- The smart contract verifies the proof on-chain using the Verifier contract, marks the nullifier as used, and transfers 0.001 ETH to the recipient — fully unlinking deposit and withdrawal activity.
- When withdrawing, the user provides:
- Noir for circuit creation and proof generation
- Solidity for smart contracts
- Foundry for development, deployment, and testing
- Poseidon2 hashing for Merkle tree operations
This project is for educational purposes only. Do not deploy it on mainnet or use with real funds.