The Story of DEcaFI
Inspiration
For any online shopper, it can be scary to give away your sensitive financial data. But over 61 million Americans had fraudulent charges on their card within the past year itself. The system we rely on to transact is fundamentally broken, built on safety assumptions that no longer hold true in the digital age. Every time we check out, we are forced to play a high-stakes game of financial roulette. But the world of blockchain has completely changed how we think of security and safety for online transactions.
This project was inspired by a real credit card fraud incident: a stolen card number from a single online checkout, followed by the realization that no one should actually need your real card details just to verify that a purchase is authorized. When you look at the options available today, they all present critical vulnerabilities:
- Exposure: Every online purchase hands your real card number directly to a stranger's server. You are forced to trust the cybersecurity of every single brand you buy from. One data breach or unpatched database exploit, and your financial identity is listed on the dark web.
- Trust: Centralized virtual card tools just relocate the risk. Instead of trusting the merchant, you trust a fintech middleman. They hold your bank details, your identity, and your full, uncensored transaction history. You’ve traded merchant exposure for centralized surveillance.
- Transparency: Public blockchains remove the middleman but expose everything else in plain view for anyone watching the chain. On a public ledger, your balances and habits are broadcasted to the world. It’s like buying groceries with your entire bank statement taped to your back.
No one has been able to give users both verifiable, non-custodial payments and real confidentiality. What we need is a payment system that delivers the decentralization of blockchain, the convenience of virtual cards, and the absolute privacy of zero-knowledge proofs.
That is why we built DEcaFI.
What it does
DEcaFI (Decentralized, Confidential Authorization, Finance) lets users instantly mint zero-knowledge virtual cards with custom spend limits and built-in expiration windows (e.g., 24 hours).
Our application separates what is provable from what is private:
- On-chain (Public): We store only the cryptographic card commitment (a hash), a nullifier set, and the pass/fail outcomes of checkout attempts.
- Off-chain (Private): The user's wallet retains the real card number, the virtual-to-real card mapping, and the transaction history.
When a user initiates a checkout on our mock merchant sandbox, the application builds a client-side zero-knowledge proof. This proof verifies that:
- The card commitment exists on the ledger.
- The transaction amount is within the card's authorized spend limit.
- The card hasn't expired.
- The card has not already been spent (verified via a unique nullifier).
The smart contract processes this proof and returns a simple approval or denial. The merchant receives verification that the payment is legitimate, but never learns the user's real card details or spending history. Once the transaction completes, the card's nullifier is added to the public spent-set, causing the card to "self-destruct" and preventing any replay attacks or unauthorized recurring charges.
How we built it
DEcaFI was built from the ground up during the Midnight Hackathon using a hybrid on-chain/off-chain architecture:
- Smart Contracts in Compact: We authored our zero-knowledge circuits using Compact, Midnight's TypeScript-based ZK DSL. The contract manages the ledger state of commitments and nullifiers, and defines the
mintCardandspendcircuits. - Midnight JS SDK & Providers: We wired the smart contract logic into our application using the
@midnight-ntwrklibraries. This included:midnight-js-level-private-state-providerfor securing the user's private keys and transaction mappings locally.midnight-js-http-client-proof-providerto communicate with the proof server.midnight-js-indexer-public-data-providerto query public commitments and nullifiers.
- Lace Wallet Integration: We integrated the Beta/testnet version of the Lace Wallet using the dApp Connector API. Lace acts as the secure host for user keys, managing gas payments in tNIGHT and executing transaction balancing/signing.
- Client-Side Proof Generation: We utilized a local Docker container running the Midnight Proof Server to generate ZK proofs during development, before deploying the contract to the hosted Midnight testnet endpoints.
- Interactive UI: The frontend is a retro-brutalist web terminal built with React and Tailwind CSS. Designed to feel like a high-security tactical operating system (
SYS_INIT: DEcaFI.exe), it houses the Virtual Card Terminal side-by-side with a Merchant Sandbox so that developers and users can see the ZK proving process execute in real time.
Challenges we ran into
Building a zero-knowledge application in 48 hours is no small feat, and we hit several major roadblocks along the way:
- Lace Wallet & Transaction Balancing: Integrating the dApp Connector API and managing transaction balancing via
laceWallet.balanceUnsealedTransactionwas highly complex. Coordinating gas fees, the tDUST tank, and signing transactions while maintaining a completely non-custodial architecture took hours of trial and error. - ZK Circuit Debugging & Commitment Mismatches: We repeatedly ran into "Commitment mismatch: invalid proof data" errors. Debugging Compact contracts requires an exact alignment between the off-chain serialized JS arguments and the on-chain circuit's expected types (e.g.,
Uint<64>formatting vs native JS numbers). Tracing how commitment hashes were derived on the client and verified in the proof server was a major hurdle. - Proving Latency: Zero-knowledge proof generation is mathematically intensive. Tuning the performance of client-side proving so it doesn't freeze the UI during mock checkout was a challenge.
- Resource Constraints: Getting the testnet tDUST tank initialized and funded under the testnet rate limits slowed down our testing cycles, requiring careful coordination of wallet states.
Accomplishments that we're proud of
- End-to-End ZK Payment Verification: We successfully implemented a live checkout flow where a ZK proof is compiled on the client, verified on-chain, and processed by the merchant sandbox—all while keeping the card details entirely hidden from the ledger.
- Tactile Crypto UX: We turned abstract cryptography into something visual. Our dashboard displays the Lace wallet on the side alongside the tDUST tank, bringing the inner workings of Midnight to life.
- Robust Failure Modes: We didn't just build the happy path. We successfully programmed and demonstrated the circuit rejecting transactions that exceeded the authorized limit or occurred after the expiration window, proving that security logic can be verified without leaking details of the failure.
- Testnet Deployment: Deploying our Compact contracts live to the Midnight testnet network.
What we learned
- State Separation in Web3: We learned how to think in terms of public vs. private state. Understanding what belongs on a public ledger (verifiable commitments) and what must remain client-held (private keys, spending history) is the core of zero-knowledge engineering.
- Developing with Compact: We gained deep familiarity with Compact, learning how to structure circuits, enforce assertions, and compile ZK smart contracts.
- The Power of Midnight: We learned how Midnight's dual-state model resolves the age-old conflict between auditability and confidentiality in decentralized finance.
What's next for DEcaFI
We view this hackathon build as just the starting point. Our roadmap for DEcaFI includes:
- Cardano Interoperability: Utilizing Midnight's cross-chain architecture to allow card-backed balances to be settled against Cardano-native assets.
- Chrome Extension Wrapper: Wrapping our minting and proving engine in a Manifest V3 browser extension. This extension will scan DOM elements on real ecommerce sites, autofilling temporary virtual cards on standard checkout pages.
- Partial-Spends & Running Balances: Extending our Compact contract to support cards with a running balance (e.g., spend up to $100 over multiple checkouts) rather than strict single-use expiration.
- Merchant SDK: Building a plug-and-play merchant-side verifier widget that allows standard online payment processors (like Stripe or Shopify plugins) to accept and verify DEcaFI zero-knowledge payment proofs directly.
Built With
- cardano
- compact
- docker
- lace-dapp
- lace-wallet
- level-db
- midnight
- node-zk
- testnet
- typescript
Log in or sign up for Devpost to join the conversation.