Search projects, hackathons, sponsors and tech

    ← All projects

    Basecamp Pass

    World ID proves who you are. A soulbound Ethereum key proves you may enter. The door needs both.

    Demo

    About

    Basecamp Pass is a digital key for vacant houses (akiya) and guesthouses in Japan, built for travelers and working-holiday makers who need a home base: stay, leave luggage, travel, come back. A stranger getting the key to a home is a trust problem, and Japanese minpaku law requires an identity check and a guest register for every guest. Basecamp Pass splits the problem in two: - World ID answers "who is this person?" The guest proves a passport or My Number Card in World App (the contract holder also passes a live face check at check-in). We never see the document. - Ethereum answers "may this person enter this room right now?" The property manager issues a non-transferable (soulbound, ERC-5192) access key with a room id and a time window, and can revoke it in an emergency. The door opens only when both are true. In our production demo the same person, verified with a real My Number Card, was DENIED before a key existed, GRANTED after the key was minted on Sepolia, and DENIED again after the key was revoked. World ID succeeded every time; only the on-chain key changed. Guests need no wallet and see no crypto words, only a boarding-pass style "Digital Key: Room 101, valid until Sep 30". No personal data goes on chain: only a holder address, the room id, the time window and the status. Hosts can invite a friend, who verifies with World ID and receives a key for exactly the stay window; it expires on chain by itself. Next steps: e-contract for fixed-term leases, JPYC payment before the key is minted, and a real smart lock (SwitchBot / SESAME) behind the existing lock adapter.

    How it's made

    Next.js 16 on Vercel with Neon Postgres. World ID via IDKit 4: the server signs each request (RP signing key stays on the server), the proof is bound to a signal per moment (host check-in, invite code, door), and it is verified with the Developer Portal v4 verify API. We use the legacy document preset (passport / My Number Card) because World ID 4.0 any(passport, mnc) constraints returned credential_unavailable for a real My Number Card holder, and we request the live face check (require_user_presence) in production. The access key is our own Solidity contract (OpenZeppelin 5 ERC-721 + ERC-5192): _update reverts on any transfer and approvals revert, so keys cannot be sold or passed on. Each key stores only roomId, validFrom, validUntil and revoked, and hasValidAccess(user, roomId) is the single rule the door calls. It is compiled with solc-js and deployed and called with viem on Ethereum Sepolia. To avoid wallets for guests, the server derives one holder address per person from the World ID nullifier plus a server secret (HMAC). The same person always maps to the same address, and the address cannot be linked back to the nullifier without the secret. We tested the contract end to end on a local anvil chain with the same library the app uses (15 checks: A granted, B denied, wrong room, transfer reverts, not-yet-valid, expired, revoked), then ran the full flow in production with a real World App and My Number Card. Hacky notes: in the World staging simulator every identity returned the same nullifier, so we could not test two people in staging and reported it to the World team; the simulator also cannot do the face check, so presence is requested in production only.