This repository demonstrates a complete privacy protocol built using:
- Solidity smart contracts
- Noir zero-knowledge circuits
- Aztec Barretenberg (UltraHonkBackend)
- Incremental Poseidon Merkle Trees
PrivateBank allows users to deposit ETH and later withdraw it without linking the withdrawal to the original deposit.
The contract verifies a zero-knowledge proof that:
“I know a secret commitment inside the Merkle tree and I have not withdrawn before — without revealing which deposit is mine.”
PrivateBank integrates Solidity, Noir, and Barretenberg into a full end-to-end privacy pipeline:
- User generates random (nullifier, secret) off-chain.
- A commitment Poseidon(nullifier, secret) is computed.
- User deposits exactly 1 ETH with the commitment.
- Commitment is inserted into an on-chain incremental Merkle tree.
- Later, user generates a zero-knowledge proof off-chain proving:
- Their commitment exists in the tree.
- Their nullifier matches the public nullifier hash.
- User submits proof + root + nullifier hash + recipient.
- Contract verifies proof via HonkVerifier.
- If valid and unused nullifier → 1 ETH is transferred privately.
zk-private-bank/ ├── src/ │ ├── bank.sol # PrivateBank contract │ ├── imtree.sol # Incremental Merkle Tree │ └── verifier.sol # HonkVerifier │ ├── circuits/ │ └── main.nr # Noir circuit │ ├── js-scripts/ │ ├── generateCommit.ts # Creates (commit, nullifier, secret) │ ├── generateProof.ts # Generates withdrawal proof │ └── merkleTree.js # Off-chain Poseidon Merkle tree │ ├── test/ │ └── BankTest.t.sol # Foundry integration test │ └── README.md
Deposit Privacy — Yes
Withdrawal Unlinkability — Yes
Double Spend Prevention — Yes
Fixed Denomination Pool — Yes
Merkle Membership Proof — Yes
ZK On-Chain Verification — Yes
ERRORS- Unsolved ProofLength Mismatch errors hindered more tests. Try different proving backends and tag me on X if you solve the error
b0a5491c85c1eac8671adbc7b877dde974ebc0dc60fd250b51601c606a0444, 0x000000000000000000000000006217c47ffa5eb3f3c92247fffe22ad998242c5]) [staticcall]
│ └─ ← [Revert] ProofLengthWrongWithLogN(11, 6272, 7104)
└─ ← [Revert] ProofLengthWrongWithLogN(11, 6272, 7104)
Backtrace:
at HonkVerifier.verify
at BankTest.testMakeWithdrawal
Suite result: FAILED. 0 passed; 1 failed; 0 skipped; finished in 61.68s (49.84ms CPU time)
Ran 1 test suite in 61.73s (61.68s CPU time): 0 tests passed, 1 failed, 0 skipped (1 total tests)
Failing tests:
Encountered 1 failing test in test/bank.t.sol:BankTest
[FAIL: ProofLengthWrongWithLogN(11, 6272, 7104)] testMakeWithdrawal() (gas: 6332964)
Encountered a total of 1 failing tests, 0 tests succeeded
Tip: Run `forge test --rerun` to retry only the 1 failed test
This project aims to teach ZK proof systems in an end to end flow only! and is only used for educational and demo purposes. We do not condone violation of financial regulations.
USE THE CODEBASE AT YOUR OWN PERIL