Privacy-preserving Uniswap v4 hook with ZK-proof swaps, liquidity provision & withdrawals
Unizwap is a privacy-preserving decentralized exchange protocol that brings zero-knowledge privacy to Uniswap V4 through its hooks architecture. Unlike traditional privacy DEXes that require separate liquidity pools or off-chain sequencers, Unizwap extends Uniswap V4's existing infrastructure to enable private swaps, private liquidity provision, and cross-wallet withdrawals—all while maintaining full trustless execution on Ethereum L1.
The Problem: Current DEXes expose complete trading activity: wallet addresses, swap amounts, liquidity positions, and transaction history are all publicly visible. This creates serious privacy concerns—MEV bots exploit this transparency to frontrun trades, competitors analyze trading strategies, and users have zero protection from address-based surveillance. Existing privacy solutions either fragment liquidity into separate shielded pools, rely on trusted hardware (TEEs), or require centralized sequencers.
Our Solution: Unizwap leverages Uniswap V4's hook system to implement commitment-based privacy at the protocol level. When users swap or provide liquidity, output tokens and positions are stored by cryptographic commitments (Poseidon hashes of secret values) rather than wallet addresses. These commitments are inserted into a Merkle tree, creating an anonymity set. To withdraw funds or remove liquidity, users generate zero-knowledge proofs (using Circom circuits and Groth16) that prove ownership of a commitment without revealing their secret or linking transactions. Crucially, withdrawals can be made from completely different wallet addresses, breaking on-chain linkability.
Technical Architecture: Our implementation consists of three main components:
UnizwapHook Contract: Implements Uniswap V4 hook permissions (beforeSwap, afterSwap, beforeAddLiquidity, beforeRemoveLiquidity) to intercept operations and manage privacy. The hook captures swap outputs, stores them by commitment, and requires ZK proof verification for withdrawals.
ZK Circuits: Two Circom circuits verify commitment ownership—one for swap withdrawals and one for liquidity removal. Each circuit enforces Merkle inclusion proofs, nullifier checks (preventing double-spending), and commitment validation. Public signals include only the Merkle root, nullifier, and withdrawal parameters—no wallet addresses or secrets are revealed.
Merkle Tree with History: A 10-level Poseidon Merkle tree stores commitments with multiple root history, allowing proofs to remain valid even as new commitments are added. This prevents race conditions and maintains a robust anonymity set.
Key Innovations:
Hook-Native Privacy: First privacy solution built directly into Uniswap V4 hooks, not a separate protocol No Liquidity Fragmentation: Uses existing Uniswap V4 pools—no need for separate privacy pools Zero Trust: Pure smart contracts + ZK proofs—no TEEs, sequencers, or relayers required Cross-Wallet Withdrawals: Prove ownership from any wallet, completely breaking address linkability Router Pattern: Direct execution without pre-deposits, simplified UX compared to vault-based systems Current Status: Unizwap is fully deployed and operational on Sepolia testnet with verified contracts and real transaction evidence:
Hook Contract: 0x33a0529f481140fdc2d14a47d2ce8f2b9d1e4ac4 Complete transaction flow: Pool creation → Add liquidity → Private swap → ZK withdrawal → LP removal All operations verified on-chain with working frontend at unizwap-ktkl.vercel.app Gas costs optimized: ~250-280K gas for ZK proof verification Privacy Guarantees: What's hidden: Swap output destinations, LP position ownership, withdrawal recipients, position linkability What remains public: Input wallet addresses (router pattern), token amounts, pool activity, timing Protected against: MEV exploitation, address surveillance, trading strategy analysis, portfolio tracking This represents a practical privacy model—not perfect anonymity, but significant protection against the most common threats while maintaining on-chain transparency for regulatory compliance.
Future Roadmap: We're developing cross-chain privacy bridges, intent-based private swaps with solver networks, private limit orders with ZK-revealed execution, and scalable Merkle trees with dynamic expansion. Our goal is to make privacy the default for DeFi operations while maintaining full compatibility with Uniswap V4's ecosystem.
Unizwap demonstrates that meaningful DEX privacy is achievable today on Ethereum L1 without sacrificing trustlessness, liquidity, or user experience—paving the way for privacy-preserving DeFi at scale.
How It's Made: Technical Implementation
Unizwap combines Solidity smart contracts, zero-knowledge cryptography, and Uniswap V4's hook architecture into a fully functional privacy layer for DEX operations.
Core Smart Contract Layer (Solidity + Foundry): Our UnizwapHook.sol implements Uniswap V4's BaseHook with specific permissions: beforeSwap, afterSwap (with returnDelta), beforeAddLiquidity, and beforeRemoveLiquidity. We inherited from MerkleTreeWithHistory to manage a Poseidon-based 10-level Merkle tree directly in-contract, supporting 1024 commitments with 30-root history to prevent race conditions.
The particularly hacky part: We intercept afterSwap to "claim" output tokens before they reach users by returning a BalanceDelta, redirecting tokens to our hook contract. Instead of tokens going to msg.sender, we map them to commitment hashes: commitmentDeposits[commitment][token] = amount. This required deep understanding of Uniswap V4's unlock callback mechanism and delta accounting—a complex system we had to master for proper integration.
Uniswap V4 Integration: For liquidity privacy, the hook contract owns LP NFTs while users prove ownership via ZK proofs. Our beforeAddLiquidity intercepts to insert commitments, and beforeRemoveLiquidity verifies proofs before allowing withdrawals. The routing pattern uses SwapRouter02 with custom hookData encoding—we pack commitment hashes, addresses, and metadata into hookData bytes that get passed through the entire swap flow.
Zero-Knowledge Proof System (Circom + SnarkJS + Groth16): We built two custom Circom circuits:
Swap Withdrawal Circuit: Takes private inputs (secret, nonce, Merkle path) and enforces commitment = Poseidon(token_address, amount, Poseidon(secret, nonce)) matches a Merkle leaf, with nullifier = nonce.
LP Removal Circuit: Uses commitment = Poseidon(secret, nonce, tokenId) with nullifier = Poseidon(secret, tokenId) to prevent linkability.
The clever bit: Nested Poseidon hashing binds token metadata while keeping inner hashes reusable across operations. Circuit compilation uses Circom 2.1.6, with exported Solidity verifiers deployed separately for gas optimization (~250-280K gas per proof).
Cryptographic Consistency: Using Poseidon throughout (ZK-friendly with low constraint count) required maintaining exact consistency across circuit, Solidity, and frontend. We spent significant time ensuring identical Poseidon parameters (t=6, nRoundsF=8, nRoundsP=57) across all layers—any mismatch breaks proof verification.
Frontend & User Flow (TypeScript + Ethers.js): Built with Next.js, handling secret generation, commitment calculation, Merkle proof generation, and in-browser ZK proof generation using WASM-compiled circuits. The trickiest part: converting between BigInt (JS), uint256 (Solidity), and field elements (circuits) without precision loss—we use ethers.toBeHex with explicit 32-byte padding.
Notable Hacks & Challenges:
Hook Address Mining: Uniswap V4 hooks need addresses with specific bit flags matching permissions. We used CREATE2 salt mining—computational brute force to find compliant addresses.
Delta Accounting: Uniswap V4's delta system required careful balancing. Our afterSwap returns negative delta for output currency (claiming tokens) while ensuring user swaps succeed—this required deep diving into PoolManager's settle/take logic.
Merkle Tree Gas Optimization: On-chain trees are expensive. We optimized by: (a) only storing roots and leaf count, requiring users to maintain off-chain trees, (b) 30-root circular buffer for flexibility, (c) Poseidon instead of SHA256 for cheaper circuit verification.
Nullifier System: Each proof generates a unique nullifier preventing double-spends. For swap withdrawals, nullifier = nonce (simple), but for LP removal, nullifier = Poseidon(secret, tokenId). This prevents cross-operation replay while maintaining unlinkability.
Cross-Contract Communication: Our hook interacts with PositionManager for LP operations, requiring careful reentrancy handling. Uniswap V4's unlock mechanism creates complex call stacks—we rely on protocol guards plus nullifier checks.
Partner Technologies:

