A ZKP-powered privacy pool for anonymous ERC20 deposits and withdrawals.
zkEther is a privacy-preserving protocol for ERC20 tokens that functions as a non-custodial mixer, enabling anonymous deposits and withdrawals. Users deposit a fixed amount of tokens by submitting a cryptographic commitment, which is added to an on-chain Merkle tree. To withdraw to a new address, the user generates a zero-knowledge proof of ownership off-chain.
A key feature of the project is its use of mopro, a mobile-first proving stack, allowing these computationally intensive ZK proofs to be generated directly on a user's phone. The system's security is rooted in a robust off-chain note generation process using X25519 (ECDH) for key exchange and the ZK-friendly Poseidon hash for commitments. By validating these proofs on-chain, zkEther effectively severs the link between the deposit and withdrawal addresses, restoring financial privacy on the blockchain.
zkEther is a privacy-preserving protocol designed to enable anonymous transactions for ERC20 tokens on the Ethereum blockchain. It functions as a non-custodial "mixer" where users can deposit tokens and withdraw them to a different address without creating a discernible on-chain link. The system's privacy guarantees are built on a sophisticated combination of off-chain cryptography and on-chain zero-knowledge proof verification.
At its core, the protocol uses Elliptic Curve Diffie-Hellman (X25519) for secure key exchange, HKDF-SHA256 for deriving cryptographic secrets, and the ZK-friendly Poseidon2 Hash to generate commitments that are then proven in a circuit. For off-chain proving, the system leverages mopro, a development stack designed to bring ZK proof generation to mobile devices.
Core Problem By default, all transactions on public blockchains are transparent and traceable. This allows anyone to link a user's address to their entire transaction history, compromising financial privacy. zkEther directly addresses this by creating a privacy shield that cryptographically severs the link between the depositor and the withdrawer.
How Privacy is Achieved: The Off-Chain Note System Before any on-chain interaction, a user creates a secure, private "note." This process establishes the cryptographic data needed for both the deposit and the subsequent private withdrawal.
Shared Secret Generation (ECDH): The depositor (let's call her Alice) generates a temporary, one-time keypair. Using her new ephemeral private key and the recipient's public key, she computes a shared secret via the X25519 key exchange algorithm.
Key Derivation (HKDF): Alice uses HKDF-SHA256 (a Key Derivation Function) to expand the shared secret into two independent values:
Secret: A private value that forms the core of the deposit's ownership.
Nullifier: A unique value used to prevent the same note from being spent twice.
Commitment Creation (Poseidon Hash): To publicly register the deposit without revealing the underlying data, Alice hashes the Secret and Nullifier together using the Poseidon2 hash function. The output is a public Commitment.
Commitment = Poseidon2Hash(Secret, Nullifier)
This Commitment is the only piece of data from this process that is made public on the blockchain.
System Architecture & Core Components The project features a modular, multi-contract architecture:
zPool.sol (The Mixer Core) This is the central smart contract orchestrating the privacy mechanism. It stores commitments in an Incremental Merkle Tree and uses a Verifier.sol contract to validate ZK proofs submitted during a withdrawal.
Minter.sol (The Token Wrapper) This utility contract acts as a bridge between underlying ERC20 tokens and their wrapped "zToken" counterparts, handling the minting (on deposit) and burning (on withdrawal) of these tokens.
ZFactory.sol (The Deployment Manager) This factory contract is responsible for deploying and managing the ecosystem of zPool and Minter contracts, allowing for the creation of separate, isolated privacy pools for different ERC20 tokens.
Architectural Flow Deposit Process Off-Chain Note Creation: A user generates a Commitment by following the off-chain note creation process described above (ECDH → HKDF → Poseidon).
On-Chain Transaction: The user calls the deposit function on the zPool contract, submitting the Commitment, the fixed token amount (DENOMINATION), and a small Ether fee.
Token Management & Commitment Storage: The zPool pulls the ERC20 tokens, instructs the Minter to mint zTokens, and inserts the user's Commitment into its on-chain Merkle tree.
Withdrawal Process Off-Chain Proof Generation with mopro: To withdraw, the user must generate a zero-knowledge proof. This computationally intensive task is handled by mopro, an open-source development stack designed to run ZK provers efficiently on mobile devices (iOS and Android). By leveraging mopro, zkEther allows users to generate proofs directly on their phones, eliminating the need for a powerful server or desktop computer. The mopro stack compiles the ZK circuits (built with frameworks like Arkworks in Rust) into a mobile-native library, enabling a seamless and private user experience on the go.
Circuit Logic: The user's device runs the circuit, taking their private Secret and Nullifier as inputs. The circuit verifies that Poseidon2(Secret, Nullifier) matches the public Commitment and generates a valid ZK proof of this fact without revealing the private inputs.
On-Chain Transaction: The user calls the withdraw function on the zPool, submitting the mopro-generated proof, the Merkle tree _root, the _nullifierHash, and the recipient's address.
Proof Verification & Fund Release: The zPool's verifier contract validates the proof. If valid, it marks the nullifier as spent and instructs the Minter to release the underlying ERC20 tokens to the recipient.