Problem Statement

Public blockchains cannot check "does this person qualify?" without exposing who that person is.

Airdrops, grants, scholarships and DAO memberships all need two checks: is this person eligible? and have they already claimed? On a transparent ledger, every common approach breaks one of the two:

  • Put credentials or their hashes on-chain. The data is public and permanent, and the same hash links a person across every app that checks it.
  • Run an off-chain KYC server plus a whitelist. It becomes a honeypot of ID documents and a trusted gatekeeper, which is the opposite of decentralization.
  • Skip the check. Sybil farms take the rewards. In 2024, LayerZero flagged 803,093 addresses (about 13% of roughly 6 million eligible) as potential sybils in its airdrop, and it could only do so after the fact, by clustering wallets in public.

The same pattern exists off-chain: to prove three yes/no facts (age band, region, enrollment), an applicant for a youth grant uploads a document showing their full name, national ID number, address and household members.

Solution

JustEnough lets a person prove "I meet this program's rules and this is my first claim", and nothing else.

  1. An issuer vouches once. A trusted issuer (a university registrar or an e-ID provider; a demo issuer account in this MVP) vouches for the holder's attributes once and publishes only a salted hash of them. No personal value goes on the ledger.
  2. The holder proves it in zero knowledge. The holder's device (through the local Midnight proof server) builds a proof that the private credential satisfies the program's public rule, for example: age 19 to 34, lives in Seoul, and is currently enrolled.
  3. The contract verifies and records a nullifier. The Compact contract checks the proof and stores a one-time nullifier, so a second claim by the same person fails without revealing who they are. Nullifiers are derived per program, so claims in two different programs cannot be linked to each other.

Unique value: public rules, private data. Anyone can audit what a program requires; nobody can see who applied.

Prototype/MVP

  • A working dApp with three roles (issuer, applicant, programme operator) running end to end: issue credential → prove eligibility → claim accepted → second claim rejected → ineligible credential rejected → anonymous, auditable draw → selected applicant claims.
  • Try it without installing a wallet: https://ryugi62.github.io/justenough/?lang=en&preset=grant runs the full flow in simulator mode in your browser.
  • Simulator mode runs the same compiled circuit logic in the browser so you can see every accept/reject decision; real zero-knowledge proofs are generated only in the network build.
  • 118 automated tests passing in CI on every push.

Technology Stack

  • Blockchain: Midnight, a privacy-focused layer 1 with a public ledger and private, client-side state (network used: local devnet)
  • Smart contract: Compact 0.31.1 — circuits: issueCredential, registerProgram, apply, closeProgram, selectApplicant, claimBenefit
  • Client: TypeScript + Vite, compact-runtime 0.16
  • Proofs: zero-knowledge proofs generated on the user's side by the local Midnight proof server
  • Public ledger state: issuer key, salted credential hashes, programme rules, nullifiers, counters
  • Testing: Vitest on the compiled contract, Playwright, GitHub Actions

GitHub Repository

https://github.com/Ryugi62/justenough (Apache-2.0). The README opens with a 3-command setup (install, test, run) and a usage walkthrough for all three roles.

Demo

Presentation

Pitch deck, 7 slides covering problem, solution, technology, innovation, impact and future scope: https://github.com/Ryugi62/justenough/blob/main/docs/3rd-web-hack-deck.pdf. The same slides are in the image gallery.

Innovation & Uniqueness

  • Most identity projects on public chains store a credential or its hash on-chain, and that value is public and linkable. JustEnough puts no personal value on-chain: the issuer publishes salted credential hashes into a Merkle tree, and a claim proves membership without revealing which hash is yours, then stores only a nullifier that differs in every program.
  • Sybil resistance without collecting KYC data at claim time: one person, one claim, identity never revealed.
  • The rules are public and on-chain, and the data stays private and off-chain, so a program cannot quietly change who qualifies.

Impact

  • Applicants stop uploading ID documents to every program they apply to.
  • Programs, grant DAOs and airdrops carry no personal-data liability, and double claims are blocked by construction instead of by after-the-fact wallet clustering.
  • Public agencies can use the same flow for scholarship and youth-grant eligibility.

Future Scope

  • Real issuers (university registrars, national e-ID) with credential revocation and expiry.
  • A mobile wallet flow with QR hand-off between devices.
  • Richer rules (income bands, OR-conditions) and an independent audit of the circuits.

Built during the hackathon

Written from scratch starting 2026-09-24, inside the 3rd-Web-Hack submission period (Aug 22 – Sep 27, 2026). The same codebase is also our entry to the Midnight Korea Hackathon 2026; neither event's rules restrict this. For 3rd-Web-Hack we added the English interface and a "Web3 community grant" scenario.

Limitations

  • The issuer in this MVP is a demo account. A real deployment needs a trusted issuer and a revocation list.
  • The issuer knows the attributes it vouched for; the ledger and the program do not.

Built With

Share this project:

Updates

Submission history