Inspiration

Credit and reputation systems today force an impossible tradeoff: to prove you're trustworthy — a good tenant, a reliable borrower, a dependable gig worker — you have to hand over your entire financial history to whoever's asking. A landlord doesn't need your bank balance; they need to know you won't default. A lender doesn't need your full credit history; they need to know your score clears a bar. Every existing system leaks far more data than the question actually requires.

Midnight's combination of a public ledger with private, provable state felt like the first real answer to this. We wanted to build something concrete: a "credit passport" where a Holder can prove specific claims about their financial reputation — "my score is above 700," "I've never defaulted," "my score is between X and Y" — without ever revealing the underlying number to anyone, including the verifier.

What it does

CreditProof lets an Issuer (a bank or gig platform) commit a Holder's reputation score to the Midnight blockchain as a cryptographic commitment — the raw score never touches the chain. The Holder can then generate zero-knowledge proofs against that commitment to answer specific yes/no questions for a Verifier (a lender, a landlord):

  • prove_score_above(threshold) — proves the score clears a bar, reveals nothing else
  • prove_no_default() — proves zero defaults, reveals nothing else
  • prove_score_range(min, max) — proves the score falls in a band, reveals nothing else

Every proof is verified on-chain and the verification result (pass/fail only) is recorded publicly, so a Verifier has an auditable, tamper-proof answer — without ever seeing the number behind it. Credentials can also be revoked by the Issuer if reputation data changes.

How we built it

The core is a Compact smart contract (credit_passport.compact) that defines the public ledger state (commitment, issuer identity, revocation flag, verification maps) and a set of ZK circuits that recompute a Holder's private witnesses — score, default count, issuance timestamp, and a nonce — hash them, and check the result against the on-chain commitment before disclosing only a boolean.

On top of the contract, we built:

  • A Node/Express backend that acts as a proof relay and credential signing service, orchestrating requests between Holder, Issuer, and Verifier flows.
  • A React + Vite frontend (React Router, TypeScript) giving each actor role — Issuer, Holder, Verifier — its own interface to issue credentials, generate proofs, and verify claims.
  • Deploy tooling to compile the Compact contract, spin up a local Midnight network (node, indexer, proof server) via Docker, and push the contract on-chain.

Because the @midnight-ntwrk SDK packages are still evolving in preview, we also built a simulation layer that mirrors the exact behavior, delays, and cryptographic hashes of the real SDK, so the full user flow — issuing a credential, proving a claim, verifying it — can be demoed end-to-end even while wallet/network infrastructure catches up.

Challenges we ran into

The biggest challenge was infrastructure instability at the edges of a very new ecosystem. The public Preprod faucet's ZK prover was crashing server-side on every request and imposing 24-hour IP rate limits, which meant we couldn't reliably get tNIGHT/DUST to pay gas for a real on-chain deploy. We pivoted to running Midnight's own local "undeployed" network via Docker, which ships with a pre-funded genesis wallet — no faucet required.

That surfaced a second challenge: the @midnight-ntwrk JS/TS SDK is moving fast, and package versions in active development diverge quickly from documentation and examples — provider constructors became factory functions, config shapes changed, and the contract execution layer moved to an Effect-based API requiring compiled contracts to be wrapped with explicit witness implementations. Chasing a moving-target SDK under a hackathon clock was the real test of the weekend.

What we learned

We came away with a much deeper appreciation for the mechanics of ZK proof systems — specifically how a single commitment plus a set of private witnesses can support many different disclosure circuits, each revealing exactly one bit of information and nothing more. We also learned a lot about designing for infrastructure that's still stabilizing: building a faithful simulation layer alongside the real integration turned out to be essential, not just for demos under time pressure, but for iterating on the app's UX independently of network/tooling flakiness.

What's next for CreditProof

  • Complete the real on-chain deployment against Midnight's SDK as the Effect-based contract execution APIs stabilize.
  • Add issuer attestation chains, so multiple issuers (bank, gig platform, utility provider) can contribute to one Holder's passport.
  • Expand the proof vocabulary (income bands, employment tenure, rental history) beyond credit score and default status.
  • Explore selective credential revocation and expiry, so passports age out gracefully without a full re-issuance.

Built With

Share this project:

Updates

Submission history