zkLoan - Devpost submission

Project name

zkLoan

Elevator pitch (tagline)

Prove you qualify for a loan without revealing a single number. zkLoan turns a lender's policy into a zero-knowledge proof on Midnight, so they get a yes or no, never your income, credit score, debts, or collateral.


Project Story

Inspiration

Every time you apply for a loan you hand over your entire financial life - income, credit score, existing debts, bank statements - just to get a single yes or no. The lender only ever needed the answer, but now they hold the raw data forever. They become a breach target, they can sell it, a court can subpoena it, and you can never take it back.

In India the tension is sharper. The RBI's Digital Lending Directions and the Account Aggregator framework push hard for consent and data minimization, yet the default across the industry is still "collect everything, then promise to protect it." A promise is not a guarantee.

We kept coming back to one question: what if the lender could verify that you qualify without ever seeing the numbers? Zero-knowledge proofs make that literal, and Midnight's Compact language makes it something you can actually build in a weekend.

What it does

A lender writes their lending policy in plain English. Claude compiles it into exact circuit thresholds. The applicant, holding bank-signed credentials in their wallet, generates a zero-knowledge proof on their own device that they clear every threshold. The lender receives one proof and six pass/fail booleans - income, CIBIL, FOIR, LTV, employment, and defaults - and nothing else. Claude then writes the decision and the adverse-action reason from those booleans alone.

No raw applicant number ever touches the AI model or the lender's servers. The verdict crosses the wire, never the evidence.

How we built it

The heart of zkLoan is a Compact circuit, proveEligibility, that takes the applicant's private financials as witnesses and the lender's thresholds as public inputs. Because a ZK circuit has no floating point, every ratio is expressed as an integer cross-multiplication so that no division ever appears in the proof.

The circuit writes a nullifier to the ledger, which is what makes it emit a real SNARK (proof: true, with a roughly 2.8 MB prover key) rather than a mock.

Around the circuit we built:

  • A Next.js 16 / React 19 / Tailwind v4 frontend with an interactive, on-page proof demo.
  • Two real Claude calls: a policy compiler that only ever receives policy text, and a decision writer that only ever receives the six booleans.
  • A real Midnight Lace wallet connector (window.midnight.mnLace) with a labelled demo fallback so the app works in any browser.
  • Ed25519-signed mock credentials from a bank and a payroll issuer.
  • An RBI compliance guardrail that checks a compiled policy against the machine-verifiable slice of RBI's rules (data minimization, consent, CIBIL range, FOIR ceiling, LTV cap, Key Fact Statement, fair practices).

The math

FOIR (fixed-obligation-to-income ratio) and LTV (loan-to-value) are checked as pure integer inequalities:

$$ (\text{existingEmi} + \text{newEmi}) \times 1200 \le \text{maxFoirPct} \times \text{income} $$

$$ \text{loanAmount} \times 100 \le \text{maxLtvPct} \times \text{collateralValue} $$

Replay is prevented with a nullifier derived from the applicant's secret key and the policy id:

$$ \text{nullifier} = H(\text{localSecretKey} \,\Vert\, \text{policyId}) $$

where \( H \) is a persistent hash. The factor of \( 1200 \) folds a monthly-to-annual conversion (\( \times 12 \)) and a percentage conversion (\( \times 100 \)) into a single integer comparison, so there is no division and no floating point anywhere in the circuit.

Challenges we ran into

  • Making the proof real. A Compact circuit only generates a SNARK when it writes to the ledger. Our first read-and-disclose design compiled to proof: false with no keys at all. We redesigned it to write a nullifier-to-qualified mapping, which flipped it to proof: true with real prover and verifier keys.
  • No floats, no overflow. Ratios had to be cross-multiplied, and multiplying two Uint<128> values overflows to Uint<256>. We kept operands as Uint<64> and let the products auto-widen.
  • Keeping the AI blind. The policy compiler must only see policy text, and the decision writer must only see booleans. We enforced that boundary in the API routes and made it visible in the interface so it is not just a claim.
  • Design. We rebuilt the whole interface into a warm, editorial, DeepJudge-inspired language, pulling the real design tokens (bone canvas, serif display headlines, a single violet accent) from the reference site rather than guessing.

What we learned

  • How to think inside a ZK circuit: integer-only math, the difference between a circuit that proves and one that merely computes, and nullifiers for replay protection.
  • Midnight and Compact end to end: witnesses, the ledger, the proof server, and the Lace connector API.
  • That "private AI" is an architecture, not a promise. If the model never receives the number, there is nothing to leak.
  • Real RBI-context underwriting: FOIR, LTV, CIBIL, collateral, employment tenure, and the Account Aggregator consent model.

What's next for zkLoan

  • Bind the credential's Ed25519 signature check directly inside the circuit (today it is verified in the app around it).
  • Integrate the real Account Aggregator flow for live, consented bank data.
  • Deploy the proof server and ship a hosted public demo.

Built with (tags)

midnight compact zero-knowledge zk-snarks zkproofs typescript next.js react tailwind-css node.js claude anthropic ai lace-wallet ed25519 motion docker vercel fintech lending privacy account-aggregator cibil rbi web3

(25 tags)

Try it out links

Project media

  • assets/hero.png - landing hero
  • assets/landing-full.png - full landing page
  • assets/dashboard.png - applicant dashboard
  • (additional screens captured for the demo video: applicant flow, offers, credentials, wallet)

Built With

  • account-aggregator
  • ai
  • anthropic
  • cibil
  • claude
  • compact
  • docker
  • ed25519
  • fintech
  • lace-wallet
  • lending
  • midnight
  • motion
  • next.js
  • node.js
  • privacy
  • rbi
  • react
  • tailwind-css
  • typescript
  • vercel
  • web3
  • zero-knowledge
  • zk-snarks
  • zkproofs
Share this project:

Updates

Submission history