Inspiration
Assessments exist to answer one simple question: did you clear the bar? But most systems answer that by handing over everything else too — your precise score, your full response history, exactly where you fell short. That level of detail can trail a hiring candidate for years, attach itself permanently to a doctor's licensing record, or reveal far more from a psychological screening than a simple result was ever meant to. We built ScoreVault to pull those two things apart: proving the outcome without exposing everything behind it.
What it does
ScoreVault is a zero-knowledge assessment verification platform built on Midnight. An organizer issues an exam with a threshold (say, 7 out of 10) locked into a Compact contract circuit. A candidate answers privately in the browser — their raw responses never leave the device. On submission, a zero-knowledge proof is generated locally, and only a boolean pass/fail is committed to the Midnight ledger. A verifier — an employer, a licensing board, a clearance office — can independently confirm the result through our CLI without ever seeing the candidate's actual answers or score.
How we built it
The contract is written in Compact: a private witness function scores the candidate's answers against the organizer's threshold, and a circuit enforces that the result was computed correctly against the real answer key before anything is written to the ledger. Proof generation runs through Midnight's proof server (Dockerized), using HALO2 over the BLS12-381 curve. The frontend is React + TypeScript, and the whole stack — proof server, local network, and app — runs in Docker for reproducibility.
The product has a three-sided story: an organizer configures the exam and threshold directly in the contract, a candidate takes the assessment through the UI, and a verifier checks the resulting proof independently through a CLI tool — with no dependency on trusting ScoreVault's own frontend.
Challenges we ran into
The biggest challenge we ran into was a submission bug. When testing the exam flow, hitting submit would immediately return an error: Insufficient Funds, could not balance dust. Dust is Midnight's fee token, generated over time from Night tokens, so our first assumption was that this was just the normal wait period after registering a new wallet before dust starts generating. We waited it out. The error persisted.
That's when we went into the wallet code itself instead of continuing to assume it was a timing issue. It turned out the browser wallet was attempting to pay the transaction fee the moment submit was pressed, without first checking whether the wallet had actually finished syncing. It's similar to trying to pay with a debit card before an ATM has finished loading the account balance. Even if the funds are there, the request fails before it's ever properly checked. The CLI never ran into this problem because it always waited for a full sync before attempting payment. The browser version simply lacked that same safeguard.
Once we identified the actual cause, the fix was straightforward: we added the same sync wait to the browser wallet that the CLI already had. We chose to fix the underlying cause rather than add a longer timeout or a retry loop to mask the symptom, since that approach would have only delayed the same failure rather than resolving it.
Accomplishments that we're proud of
We're most proud of actually finding the real bug behind the dust sync error instead of just slapping a timeout on it and moving on. It would have been easy to paper over it, but we wanted to understand why it was happening. And honestly, getting the full zero knowledge pipeline working end to end felt like the biggest win. The Compact circuit, the HALO2 proof over BLS12 381, the pass or fail result written on chain, none of it is mocked or faked for the demo. It's the real thing running.
What we learned
Working on Midnight clarified how differently privacy has to be approached when it is built into the platform itself, rather than layered on afterward through encryption or access controls. The witness function and circuit model required some adjustment initially, but understanding it reshaped our approach to the entire architecture. Rather than building an application that stores sensitive data and relies on policy to protect it, we built one where that data has no structural path to exposure in the first place. A candidate's answers exist only as a witness inside the circuit computation. They are never persisted, never transmitted, and never something the ledger is capable of revealing, regardless of intent.
We also developed a much stronger understanding of Midnight's wallet and dust system than we started with. Debugging the sync issue required us to understand how dust generation and wallet syncing actually function, rather than treating them as an abstraction to call functions against. This gave us a clearer sense of how much of Midnight's security model depends on a wallet accurately reflecting its own state before it is permitted to act.
Compact itself was a strong development experience. Writing the circuit and witness function felt closer to writing a specification than writing conventional application code, which required us to think precisely about what needed to be provable before implementation began. This is a meaningfully different development model than most blockchain work we had done previously, and it is well suited to assessment and verification applications specifically.
The broader takeaway from this project is that the interesting problem in zero knowledge is not simply hiding data. It is precision about what actually needs to be revealed, and building a system that is structurally incapable of revealing anything beyond that. Midnight's architecture made that level of precision achievable in a way that would be difficult to replicate with a conventional server architecture and a policy commitment not to inspect the data.
What's next for ScoreVault
The current implementation proves a single exam against a single threshold hardcoded at compile time, but the underlying pattern generalizes well beyond this hackathon build. The most immediate next step is turning the organizer side into a configurable interface rather than a value baked directly into the contract, so any organization could define its own answer key and passing threshold without needing to write or compile Compact code. That would open the door to real deployment scenarios: technical interview screening, professional licensing exams, medical certification, and security clearance testing, all running on the same underlying circuit with organization specific parameters rather than a separate build for each use case.
Beyond a single pass or fail outcome, we would like to extend the circuit to support tiered results and percentile bands, so an organization could verify not just that a candidate cleared a bar, but that they cleared it at a specific level, without disclosing the underlying score. This matters particularly for licensing and certification contexts, where tiered credentials already exist in practice but currently require full score disclosure to communicate.
We also see significant value in making the proof itself portable. Right now, a candidate generates a proof for a specific verifier at a specific point in time. A more mature version of ScoreVault would let a candidate hold a single proof and present it to multiple verifiers over time, similar to how a physical credential functions today, without retaking the assessment or generating a new proof for every organization requesting confirmation. That shifts ScoreVault from a single use verification tool into reusable credential infrastructure, where the value compounds the more organizations recognize the same proof.
On the technical side, we want to move verification beyond the CLI into a proper verifier facing interface, and revisit deployment against Midnight's public network once the sync limitations encountered during this build are resolved upstream. Longer term, we see an opportunity to package the organizer side as a toolkit other teams building on Midnight could adopt directly, allowing any assessment style use case to plug into a privacy preserving verification layer without building the zero knowledge tooling from the ground up.
Built With
- blockchain
- compact
- css
- docker
- halo2
- javascript
- midnight
- node.js
- react
- typescript
- vite
- web3
- zero-knowledge-proofs

Log in or sign up for Devpost to join the conversation.