All projects
Proof of Presence — Bot-proof, privacy-preserving attendance for Web3 events
Bot-proof, privacy-preserving event attendance tracking using World ID ZK proofs and Chainlink CRE.
Privacy Risk & Compliance World
What it is
What it is:
Proof of Presence (PoP) is a privacy-preserving event attendance registry that leverages zero-knowledge proofs to verify that attendees are unique humans without revealing their identity. Attendees check in via World ID (Tier 1: Orb-verified) or Privy (Tier 2: email/phone), and their attendance is recorded anonymously on-chain using only a nullifierHash — never their wallet address or identity.
How it works:
- Attendee submits check-in → proves uniqueness via World ID ZK proof or Privy email
- Chainlink CRE Workflow (running in a secure enclave) receives the proof → verifies it against World ID API inside the enclave → calls recordAttendance() on the Sepolia contract via Keystone Forwarder
- ProofOfPresence contract stores the record indexed by anonymous nullifierHash → mints a non-transferable ERC-721 Soulbound Badge(POPB)
- CCIP automatically bridges the attendance record to Base Sepolia and Optimism Sepolia cross-chain
Problem it solves:
- Privacy in attendance tracking: No wallet address ever stored on-chain. Events can verify attendance without exposing attendee identity.
- Sybil-resistance: World ID ZK proofs prove uniqueness without identity.
- Decentralized proof of presence: Records live on-chain across multiple blockchains via CCIP; no centralized company controls attendance data.
- Cross-chain portability: One check-in, attendance recorded on 3 chains automatically (Sepolia, Base, Optimism).
Pitch Deck: https://docs.google.com/presentation/d/1_11vtRN-ifEk24ousRe02EeF-wnXo673/edit?usp=sharing&ouid=102851583388467822955&rtpof=true&sd=true
How it Works
How is it built?
Tech Stack:
- Identity: World ID (ZK Orb proof) + Privy (email/phone fallback)
- Automation: Chainlink CRE (Confidential Runtime Environment) with Keystone Forwarder for secure off-chain→on-chain bridge
- Cross-chain: Chainlink CCIP for automatic message bridging
- Smart Contracts: Solidity 0.8.20 (ProofOfPresence + PoP_CCIP_Receiver)
- Frontend: Next.js 15, Tailwind CSS, MiniKit SDK
- Test Network: Ethereum Sepolia (primary), Base Sepolia, Optimism Sepolia
User Flow
Browser/World App → World ID ZK Proof
↓
Next.js Frontend (/checkin, /processing, /credential, /vault)
↓
Chainlink CRE Workflow (4 nodes)
• HTTP Trigger (receives nullifierHash + proof)
• Confidential HTTP (verifies against World ID API in TEE enclave)
• ABI encoding (prepares attestation)
• EVMClient.writeReport() → Keystone Forwarder
↓
ProofOfPresence.sol (Sepolia)
• onReport() (via IReceiver interface)
• Records registry[nullifierHash][eventId]
• Mints ERC-721 SBT badge
• Sends CCIP messages
↓
PoP_CCIP_Receiver.sol (Base + Optimism)
• _ccipReceive() mirrors records
Key Contracts Deployed:
- ProofOfPresence (Sepolia): 0xbA985984B1319451968f42281b1a92Ca709cF820
- PoP_CCIP_Receiver (Base Sepolia): 0x508eC020139E6fcdA3878B18898F0E372D906b1a
- PoP_CCIP_Receiver (Optimism Sepolia): 0xd01fac0953530D7833bA8eB0cc3CcCa2433BCD0b
Links
Created by
- Shane Joans V