ZK Email KYC validation hook for Uniswap Continuous Clearing Auctions. Bidders prove KYC status from Echo or Legion using zero-knowledge proofs over their confirmation emails. No identity data touches the chain.
Cross-chain bidding powered by LI.FI — bid from any chain into auctions on Base or Arbitrum.
┌─────────────-┐ ┌──────────────┐ ┌────────────────────┐
│ Frontend │────▶│ Proving │────▶│ CCA Auction │
│ (React) │ │ Server (Bun) │ │ (Base / Arbitrum) |
└──────┬───────┘ └──────────────┘ └────────┬───────────┘
│ │
│ LI.FI SDK │ validate()
│ (cross-chain bids) ▼
│ ┌────────────────────┐
└─────────────────────────────────▶│ PalmValidationHook │
│ (Groth16 verifier) │
└────────────────────┘
Flow: User drops KYC email .eml file → proving server generates Groth16 proof (DKIM signature + KYC regex + email nullifier) → proof is ABI-encoded as hookData → CCA calls PalmValidationHook.validate() on bid submission → hook verifies proof on-chain.
Cross-chain via LI.FI: User on any chain → LI.FI getContractCallsQuote bridges funds + encodes BidAdapter.submitBid() as destination call → single tx from source chain lands a bid on the auction chain.
CCA Factory: 0xCCccCcCAE7503Cac057829BF2811De42E16e0bD5 (Base & Arbitrum)
| Chain | Auction | Validation Hook |
|---|---|---|
| Base | 0x3eb56f07... |
0x7ea690f4... |
| Base | 0x2769938... |
0x7f098def... |
| Arbitrum | 0xbee5bcc... |
0x80c90449... |
Indexer (Envio HyperIndex): https://indexer.dev.hyperindex.xyz/8427648/v1/graphql
| Package | Description |
|---|---|
packages/circuits |
Circom circuits — EmailVerifier + KYC regex + Poseidon nullifier |
packages/contracts |
PalmValidationHook (IValidationHook), BidAdapter (cross-chain entry), Groth16 verifiers |
packages/app |
React frontend + Bun proving server |
packages/indexer |
Ponder indexer for local dev |
# Install
bun install
# Clone CCA (sibling directory, required for local dev)
git clone https://github.com/Uniswap/continuous-clearing-auction ../continuous-clearing-auction
cd ../continuous-clearing-auction && git submodule update --init --recursive && cd -
# Build contracts
cd packages/contracts && forge build && cd -
# Build circuits (compiles circom, downloads ptau, generates zkey — takes a while)
cd packages/circuits && bun run build && bun run setup && cd -Optional — rapidsnark for faster proof generation (~2s vs ~60s with snarkjs):
git clone https://github.com/AztecProtocol/rapidsnark ../rapidsnark
cd ../rapidsnark && ./build_gmp.sh && mkdir -p build && cd build && cmake .. && make -j$(nproc) && cd ../../palm./dev.shStarts Anvil → deploys CCA Factory + Palm contracts + creates auction → starts Ponder indexer → starts proving server → starts Vite frontend.
| Service | URL |
|---|---|
| Frontend | http://localhost:5173 |
| Indexer (GraphQL) | http://localhost:42069 |
| Proving Server | http://localhost:3001 |
| Anvil RPC | http://localhost:8545 |
To enable KYC validation on the local auction:
ENABLE_KYC=true ./dev.shTENDERLY_RPC_URL=<your-url> ./dev-tenderly.sh# Contracts only
cd packages/contracts && forge test -vvv
# Circuits only
cd packages/circuits && bun test
# Frontend only (needs env vars)
cd packages/app && bun run dev
# Proving server only
cd packages/app && bun run server/prove.tsCross-chain bidding uses LI.FI SDK via @lifi/sdk. The useCrossChainBid hook:
- Calls
getContractCallsQuotewith the destination auction'sBidAdapter.submitBid()calldata - LI.FI finds the optimal bridge route and returns a single source-chain transaction
- User signs one tx — LI.FI bridges funds and executes the bid on the destination chain
- Hook polls
getStatusuntil the cross-chain transfer completes
Supported source chains: any EVM chain LI.FI supports. Destination chains: Base, Arbitrum.
| Provider | Email From | Verification |
|---|---|---|
| Echo | echo@echo.xyz |
DKIM + regex: "Your identity has been successfully verified" |
| Legion | mail@legion.cc |
DKIM + regex: "ID verification has been successful" |
MIT