ZK KYC Pass Explorer
A live demo of privacy-preserving KYC for a tokenized real-world asset on Base Sepolia. A holder proves, in zero knowledge, that they hold a valid credential from an approved issuer — without revealing which issuer or any identifying data — and the token gates every transfer on that proof. On chain there is only a Merkle root and a set of spent nullifiers: no identity list to enumerate.
Base Sepolia · testnet only
Everything below is live and readable without a wallet — connect one only to send a transaction, and see the compliance gate decide whether it goes through.
Registry 0xF27e…4e65 · Token 0x882B…668D · Verifier 0x754b…8a22 · Source on GitHub
How it works
An approved issuer publishes a Merkle root over credential commitments. A holder builds a Groth16 proof that their leaf is in the tree, binds it to their own address (so a stolen proof is useless), and redeems it — becoming verified until their credential expires. The circuit reveals nothing but a one-time nullifier, the root, the caller, and the expiry. The token then treats verification exactly like a whitelist, except the whitelist is a proof, not a list.
Live on chain
Live data unavailable — showing the last known values.
- Token supply5000 ACME
- Credential root0xb556ee…4b9a
- Block44562958
The token (ACME RWA Share, ACME) has 18 decimals. The credential root is the issuer’s published Merkle root; rotating it re-issues the credential set. Notice what is not here: no list of who is verified. Verification is proven, spent as a nullifier, and never enumerable.
The compliance story
Five transactions, already on chain, tell the whole story. The last is the point of the demo: an ordinary, correctly-formed ERC-20 transfer that the token itself refuses, because the recipient never redeemed a credential proof.
| Step | Outcome | Transaction |
|---|---|---|
| Deployer redeems a ZK credential proof and becomes verified | Success | 0x165a…ed84 |
| Investor A redeems a ZK credential proof and becomes verified | Success | 0xaba6…10d3 |
| Mint 5,000 ACME to verified Investor A | Success | 0xd77d…6532 |
| Investor A → deployer, 1,000 ACME (both verified) | Success | 0xbd3d…3366 |
| Investor A → Investor B, 500 ACME (B never redeemed a proof) | Reverted | 0x5512…437f |
Interact
Everything above is readable without a wallet. To send a transaction, connect one — it signs and broadcasts on your machine. Pigfox never holds, receives, or proxies a private key.
Not connected.
Check your compliance status
Reads whether your connected address is currently verified (and until when) and how many ACME it holds. A public visitor has never redeemed a proof — which is exactly why the transfer below will be refused.
Connect a wallet to check.
Transfer tokens
Redeeming a credential proof is done off chain with the kycctl issuer/prover CLI (in the repository), not from this page — a browser has no credential secret to prove. Publishing the root and minting are agent-only actions the deployer performed during setup; there is deliberately no such affordance here.
About this demo
Testnet only. The token holds no value; the credential, the issuer, and the seeded holders are all for the demo. The trusted setup’s phase 2 is demo-grade (documented). The contracts are hand-rolled (no OpenZeppelin), 100% covered, and checked by Slither and Echidna; the circuit reuses the zk-escrow Groth16 toolchain.
Pigfox never holds, receives, or proxies a private key. This page reads the chain and nothing more; anything that changes state is signed by your own wallet.
The full threat model, invariants, trusted-setup provenance, and tooling results are in the security notes, and the circuit, contracts, and deploy provenance are in the source repository.