Inspiration

Hiring bias starts before a single qualification is read. A name, an age, a photo — these reach the recruiter's screen first and quietly shape decisions, even unconsciously. We wanted to see if zero-knowledge proofs could remove that entirely, not just reduce it.

What it does

FairHire lets a candidate prove they meet a job's requirements — years of experience, skills matched, certifications — without ever revealing their name, age, gender, or photo to the employer. A local, transparent scoring formula calculates a match score. A Compact smart contract on Midnight then proves the candidate qualifies, using zero-knowledge cryptography, and discloses only a boolean result plus an anti-replay nullifier.

The employer's dashboard has no field that could even hold a name or photo — it physically can't leak what it never receives.

How we built it

  • Compact smart contract: attestation verification, nullifier-based anti-replay protection, and time-bound nullifier expiry (so a proof for an expired job posting is automatically rejected).
  • Real zero-knowledge proving: proofs are generated with the actual compiled circuit through @midnight-ntwrk/compact-runtime and @midnight-ntwrk/zkir-v2 — genuine PLONK proofs, not simulated ones.
  • Deployed on Midnight Preprod: the eligibility contract is live on-chain at 67502bdf1510382bcaafa156b51a4a10ddc2ed7c490190bcd9bb2b31d76f325a.
  • Payload Inspector: a split-screen view showing exactly what stays private versus what's actually disclosed on-chain — built for transparency, so anyone (including a judge) can verify the privacy claim visually, not just take our word for it.
  • Compare view: a side-by-side traditional-resume vs. FairHire screen, showing exactly which fields disappear.
  • ROI calculator: an employer-facing estimate of bias-reduction impact, grounded in published hiring-bias research.

Challenges we ran into

Deploying to a real testnet turned out to be the hardest part, not the cryptography. We hit a genuine, reproducible SDK/compiler version-skew issue, then — once that was fixed — a Preprod-specific cold-sync bug (a fresh wallet has to replay 1M+ DUST ledger events before it can spend), which we traced to a documented, known issue and fixed by making the deploy script wait for the SDK's own authoritative full-sync signal instead of an approximate one. Both issues, and their fixes, are documented in detail in the README for anyone hitting the same wall.

What we learned

That "real, not mocked" is a discipline, not a one-time decision — we found and removed a silent mock-fallback path late in the process specifically because it could have hidden a real failure during a live demo. Being deployed on an actual, verifiable Preprod contract instead of just local proof generation matters for a project whose entire pitch is "you can verify this, not just trust us."

What's next for FairHire

Multi-attestor support (separate university/employer attestations combined in one proof), a compliance/audit export for employers, and batch screening for multiple candidates against one job posting at once.

Built With

Share this project:

Updates

Submission history