I’ve built a privacy-preserving collateralized lending protocol on the Midnight Network using Compact 0.28.0 and midnight-js 3.0.0.
The protocol allows users to:
-
Deposit tNight as collateral
-
Mint a synthetic stablecoin (pUSD) against that collateral
-
Maintain a minimum 150% collateral ratio
-
Repay debt and withdraw collateral
-
Liquidate undercollateralized positions
All collateral and debt balances are private, enforced via zero-knowledge circuits, while global protocol totals remain public for solvency verification.
Conceptually similar to MakerDAO, but fully adapted to Midnight’s ZK-first architecture.
What I Have Successfully Built
Compact ZK Smart Contract
-
Written in
lending.compact -
5 circuits:
-
depositCollateral -
mintPUSD -
repayPUSD -
withdrawCollateral -
liquidate
-
-
Collateral ratio enforced via multiplication constraints:
collateral × 100 ≥ debt × 150 -
30 unit tests passing using an in-memory LendingSimulator
-
ZK keys + bindings generated via
npm run compact
Full Backend (REST API – Express)
Located in lending-api/
Wallet Endpoints
-
Initialize / restore wallet
-
Get balances and addresses
-
Wait for funds
-
Register DUST
-
Get DUST balance
Contract Endpoints
-
Deploy new lending contract
-
Join existing contract
State Endpoints
-
Public protocol state
-
Private position state
-
Health check endpoint
Action Endpoints
-
Deposit collateral
-
Mint pUSD
-
Repay pUSD
-
Withdraw collateral
-
Liquidate position
BigInt values are serialized properly, errors categorized with errorType.
React Web Frontend
Located in lending-ui/
Pages:
-
Setup (wallet + deploy/join)
-
Dashboard (public protocol state)
-
My Position (private state + ratio health)
-
Actions (deposit/mint/repay/withdraw/liquidate)
UX features:
-
Live ratio preview while typing
-
Color-coded health indicator
-
ZK proof loading feedback
-
Auto-refresh
-
Error classification
-
Dark themed UI
Frontend communicates with the backend via typed API client.
CLI Interface
Fully functional terminal version with:
-
Wallet creation / restore
-
Contract deploy/join
-
DUST monitoring
-
All 5 lending operations
-
Private position view
-
Public protocol state view
Works in:
-
Standalone mode (Docker local stack)
-
Preview
-
Preprod
Proof Server Integration
Using:
midnightntwrk/proof-server:7.0.0
Via:
docker compose -f proof-server.yml up
System expects proof server on:
localhost:6300
Current Blocker
The entire system works locally in standalone mode and via CLI, and the UI + API also run correctly in dev.
However, I am currently stuck at:
-
Proper backend deployment (API server)
-
Proper proof server deployment
-
Understanding best practices for:
-
Hosting proof server in production
-
Connecting deployed backend to proof server
-
Handling ZK key files in production
-
Network configuration for Preview/Preprod in hosted environment
-
I want guidance specifically on:
-
How to deploy the backend properly
-
How to deploy or host the proof server correctly
-
How production architecture should look for a Midnight ZK dApp
That’s the current state of the project.