Inspiration
Every time someone applies for a loan or rents a flat in India, they may hand over salary slips, bank statements, and Aadhaar — their entire financial life — just so a lender can answer one yes/no question. That's massive over-disclosure. It creates data-breach risk at every organization that stores those documents, and it can also disadvantage gig workers and freelancers who have real income but no traditional payslip.
We wanted to flip this: prove "my income is above ₹50,000" without revealing the actual figure to the verifier, backend, or blockchain.
What it does
Umbra Verify lets applicants generate a zero-knowledge proof of financial eligibility. The applicant's financial value is treated as a private witness, while the resulting proof establishes whether it satisfies a threshold without exposing the underlying value.
Applicants connect their Lace wallet on Midnight Preview, enter their financial value locally, and generate a cryptographic proof. A verifier can use a shareable verification link or QR code to check the result without receiving the applicant's raw financial information.
The deployed Midnight Preview contract stores only the information required for verification, rather than the underlying financial value.
How I built it
Smart Contract (Compact / Midnight):
EligibilityVaultcontains three circuits —submitEligibilityProofuses private witnesses to prove that a value satisfies the required threshold without placing the raw value in ledger state;verifyEligibilitychecks the resulting commitment and verification state; andrevokeProofsupports proof revocation. The ledger stores commitment-based verification state rather than the raw financial value.Backend (Node.js + Express + TypeScript): Handles witness/proof preparation, commitment registry, verification requests, and audit logging. Raw financial values are explicitly cleared from memory and are not logged or persisted. The backend uses a
ContractBackendabstraction so the application can operate against different contract implementations.Frontend (Next.js + Tailwind + TypeScript): Provides applicant and verifier flows, Lace wallet integration through the Midnight DApp Connector API, QR-code generation, shareable verification links, and verification status UI.
Infrastructure: Docker Compose is used for PostgreSQL and the Midnight proof server.
Midnight Preview deployment: The
EligibilityVaultcontract was deployed to Midnight Preview using a real Lace-funded wallet. The deployed contract was independently verified through the Preview indexer, confirming that its ledger state can be read from the live deployment.
Challenges I ran into
The biggest challenge was working with an evolving Midnight development toolchain. During the initial development and hackathon submission, the complete contract compilation and deployment workflow was not available in the standard development environment, so we built the application around a clean contract-backend abstraction and an in-memory implementation that allowed the application and proof flows to be developed and tested without pretending that they were on-chain.
After the initial submission, we were able to deploy the compiled EligibilityVault contract to Midnight Preview and verify the live contract state through the Preview indexer. This allowed us to replace the backend's read path with a real Midnight contract backend without changing the contract itself.
The second challenge was enforcing true non-disclosure across every layer. The raw financial value had to remain private throughout the witness-generation flow and never appear in logs, API responses, or persistent database state. This required deliberate separation between private witness data, commitments, and publicly verifiable state.
The third challenge was Lace wallet integration. The Midnight DApp Connector API can expose wallet functionality differently across versions, so we built wallet discovery and connection logic designed to tolerate those differences.
Accomplishments that I'm proud of
- A Compact
EligibilityVaultcontract deployed and verified on the Midnight Preview network. - A real Lace-funded deployment with the contract address and transaction recorded in the project repository.
- Live read-only verification against the deployed contract through the Midnight Preview indexer.
- A zero-knowledge architecture where the underlying financial value is treated as a private witness rather than ledger data.
- A backend designed around a
ContractBackendinterface, allowing the simulated development backend to be replaced by the real Midnight contract backend without rewriting the application architecture. - A verifier experience that exposes the eligibility result without requiring the applicant to disclose their underlying financial value.
- Explicit privacy protections preventing raw financial values from being logged or persisted by the backend.
What I learned
- Midnight's witness model makes selective disclosure possible by separating private inputs from public ledger state.
- A privacy guarantee has to be enforced across the entire application architecture — not just inside the ZK circuit.
- Designing a backend around an explicit contract interface makes it much easier to move from simulation to a real blockchain deployment.
- Deploying to a live Preview network exposed integration issues that cannot be discovered through an in-memory simulation alone, particularly around contract runtime compatibility, wallet signing, and network-specific reads and writes.
- Zero-knowledge proofs are useful far beyond DeFi: financial eligibility, employment verification, credit tiers, account-age proofs, and other "prove something without revealing everything" use cases follow the same fundamental pattern.
What's next for Umbra Verify
- Complete the on-chain write path for
submitEligibilityProofandrevokeProof, including wallet-signed transactions from the applicant's Lace wallet. - Move the remaining proof submission and revocation flow from the development/in-memory path to the deployed Midnight Preview contract.
- Add additional claim types such as employment proof, credit tier, balance-above-threshold, and account-age verification.
- Enable multi-verifier reuse so one proof can be presented to multiple lenders, landlords, and platforms without repeatedly submitting sensitive documents.
Built With
- compact
- docker
- express.js
- lace-wallet
- midnight
- midnight-dapp-connector-api
- next.js
- node.js
- postgresql
- react
- tailwind-css
- typescript
- zero-knowledge-proofs
Log in or sign up for Devpost to join the conversation.