Inspiration: Services like Spotify Premium Student, Amazon Prime Student, and GitHub's Student Developer Pack all gate a discount behind proof of enrollment. In practice, that usually means uploading a transcript, a student ID photo, or enrollment documents to a third-party verification service, which then stores that personal information indefinitely. The user gets a discount; in exchange, they hand over far more of themselves than the moment actually required. We wanted to build the smallest possible example of a different answer: prove exactly one fact, "I am currently a verified student," and reveal nothing else, not even which student.

What it does: An issuer, for example a university, publishes a one-time discount code to a verified student, privately. On-chain, only a hash commitment of that code is recorded; the code itself never touches the ledger. The student later proves they know the matching code, without ever revealing it, using a zero-knowledge circuit. The chain only ever sees a single true or false result. Once a code is used successfully, it is permanently burned, so it cannot be shared or reused. The same mechanic generalizes directly to any "prove you belong to a group, without saying which member you are" check: student discounts, employee verification, age gates, membership perks.

How I built it: Built on Midnight using Compact for the zero-knowledge circuit, with a small Express server and a plain HTML and JavaScript frontend, wired together through the Midnight.js SDK against a local Midnight devnet. The circuit hashes a private code with persistentHash, compares it against a public commitment, and discloses only the boolean match, never the code itself. A second ledger field tracks whether a code has already been redeemed, enforcing single use.

Challenges we ran into: Getting single-use logic right took several iterations. Combining a witness-derived comparison with existing public ledger state inside one disclose() call repeatedly triggered the compiler's disclosure checks, and the fix was learning to separate exactly which values needed to be disclosed, and at which step, rather than disclosing an entire compound expression at once. Environment setup was also a real part of the challenge: this was built entirely on Windows 11 via WSL2, and getting Docker, the Compact toolchain, and a local proof server all talking to each other correctly took genuine troubleshooting before a single line of contract code was written.

Accomplishments that I'm proud of: Bringing my inspiration to life and going from limited blockchain experience to a fully working, end-to-end zero-knowledge application in one weekend.

What I learned: It was learning Compact's privacy-by-default model: every circuit input is private unless explicitly wrapped in disclose(), and the compiler enforces this at compile time rather than trusting the developer to remember. That caught several accidental-leak mistakes before they ever became runtime bugs, which is a genuinely different way of thinking about writing code compared to a typical web app.

What's next for Redacted: A real integration path: any service currently outsourcing student, employee, or age verification to a third-party document-collection vendor could plug in a check like this one instead, replacing "upload your documents" with "prove the fact, disclose nothing else."

Built With

Share this project:

Updates

Submission history