project screenshot 1
project screenshot 2
project screenshot 3
project screenshot 4

POAPrivacy

Mint POAPs to stealth addresses. Prove attendance without doxxing your physical location.

POAPrivacy

Created At

ETHGlobal Cannes

Winner of

ENS

ENS - Most Creative Use Case 2nd place

ETHGlobal

ETHGlobal - 🏆 ETHGlobal Cannes 2025 Finalist

Project Description

Private POAPs with Stealth Addresses

The Problem

Standard POAPs create a public, on-chain link between an identity (e.g., "name.eth"`) and a physical location. This is a privacy risk. Anyone can track your attendance at events, which can compromise personal security.

The Solution

This project severs that link. It mints a POAP to a new, single-use stealth address. On-chain, the transaction appears to go to a random, unlinked account. Only the intended recipient can find and control this address.


The Process

1. One-Time Setup: User Registration (ERC-6538)

A user performs a one-time setup.

  • Key Generation: The wallet creates two key pairs: a spending key (controls the POAP) and a viewing key (finds the POAP).
  • Meta-Address Creation: The corresponding public keys form the stealth meta-address.
  • Registration: The user registers this meta-address in the public ERC-6538 Registry. The registry connects an identity like "name.eth" to the meta-address for lookup.

2. The Mint: Issuing the POAP (ERC-5564)

The process for a POAP issuer is direct. The user scans a QR code to claim an NFT. The link opens in their browser. They can choose a stealth address or their ENS to receive the POAP to. If they choose their ENS, the POAP is automatically sent to one of the stealth addresses that the user owns.

  • Lookup: The issuer gets the user's identifier ("name.eth"`) and queries the ERC-6538 Registry to get their stealth meta-address.
  • Generate Address: The issuer's system uses the user's meta-address and a new, temporary key ("ephemeral address") to compute the unique stealth address.
  • Mint: The system mints the POAP (an ERC-721 token) to this new stealth address.
  • Announce: The issuer publishes an "Announcement" on the main ERC-5564 Announcer contract. This event contains the data needed for the recipient to find the transaction.

3. Discovery and Access: Viewing the POAP

The recipient finds their POAP by opening the website.

  • Scan: The recipient's private viewing key is used to scan all Announcement events on the ERC-5564 contract.
  • Check: A "view tag" in the announcement allows the wallet to discard most non-matching events with minimal computation.
  • Derive Key: When the wallet finds a match, it uses the user's spending private key to calculate the private key for the stealth address.
  • Control: The user now controls the POAP. They can import the private key associated with that account in any wallet in order to control their POAP balance and any other currency on that address. The link to their public identity is broken.

How it's Made

How It's Made

PPOAP (Privacy-Preserving Proof of Attendance Protocol) solves a privacy issue in POAPs. Public on-chain data can reveal a person's location. We mint POAPs to single-use, anonymous stealth addresses. This breaks the link between a user's public identity and their event attendance.

The project is a Next.js application built with TypeScript.


Core Technologies

  1. Frontend: The UI uses Next.js and React. Styling is done with Tailwind CSS. Asynchronous state, like fetching POAP data, is managed by TanStack Query.

  2. Authentication (Privy): Privy is the authentication layer. It handles user login and wallet connections. This provides a known public identity (e.g., name.eth) for registry lookups while enabling the private stealth flow.

  3. Privacy Engine (Stealth Addresses):

    • ERC-5564: This is the foundation for the privacy mechanism. The logic in app/utils/stealth-address.js implements the cryptographic flow. A sender uses the recipient's stealth meta-address to compute a new stealth address that only the recipient can control.
    • ERC-6538: This standard defines the Stealth Meta-Address Registry, an on-chain directory. A user can link their public address to their stealth meta-address. The application includes ABIs and functions (getMetaAddress.js, setMetaAddress.js) to use this registry.
  4. POAP API Integration: The application uses the official POAP APIs. It uses the Collectors API to validate claims and fetch metadata. It uses the Minting API to execute the mint to the generated stealth address.


Passkeys for Key Generation

Handling raw private keys is a poor user experience and a security risk. Our solution uses Passkeys (WebAuthn) to generate these keys deterministically, without direct user interaction with the keys. The app/utils/pass-keys.js module contains this logic.

The flow is:

  1. Credential Creation: A user creates a Passkey for the app. The device generates a PublicKeyCredential secured by biometrics.
  2. Deterministic Signing: To generate keys, the user authenticates with the Passkey. This signs a static message (e.g., "cannes-love-poap").
  3. Key Derivation (HKDF): The signature is used as input for a Key Derivation Function (HKDF). We use ERC-5564 salts (EIP-5564-spending-key, EIP-5564-viewing-key) to derive the 32-byte spending and viewing private keys.
  4. Meta-Address Generation: The system uses these private keys and the @noble/secp256k1 library to compute compressed public keys and construct the final stealth meta-address.

This method provides cryptographic privacy through a biometric login. The same Passkey generates the same stealth keys. The keys are not stored; they are derived on-the-fly.

The User Journey

  1. User scans QR code or NFC.
  2. User opens a PPOAP claim page (e.g., /claim/ethcannes).
  3. The frontend fetches POAP details from the POAP API.
  4. The user selects "Get Anon Address". This starts the Passkey flow (initializeStealthAddress) and derives the stealth meta-address.
  5. The generateStealthAddress function computes the final, single-use stealthAddress.
  6. This address appears in a disabled input field.
  7. The user selects "Mint Now". The app sends a request to the POAP API to mint the POAP to the stealthAddress.
  8. The on-chain transaction shows a mint to an anonymous address. The user's privacy is protected.
background image mobile

Join the mailing list

Get the latest news and updates