Skip to content
U

Umbra

Bringing Zcash privacy to Mina programmable zkapp.

Created on 1st December 2025

U

Umbra

Bringing Zcash privacy to Mina programmable zkapp.

The problem Umbra solves

It allows users to move Zcash into Mina's ecosystem to access DeFi applications (like lending or trading) without sacrificing the privacy of their original assets. Unlike traditional bridges that rely on centralized custodians (which are prone to hacks), this bridge uses zero-knowledge proofs to cryptographically verify transactions, making it trustless and secure. Additionally, Mina's lightweight architecture makes this verification efficient enough to run in a browser or mobile app, lowering the barrier for privacy-preserving financial tools.

Challenges I ran into

i ran into myriads of challenges, below i highlighted some of them

challenge 1: Timestamp Mismatch & Timelock Verification

The biggest hurdle was a critical "Invalid Witness" and rangeCheckN error during the burn flow. The bridge enforces a 24-hour timelock for withdrawals, but the demo environment's simulated blockchain (LocalBlockchain) defaulted to a timestamp of 0, while the offchain logic used the real system time (Date.now()). This caused a mismatch where the onchain contract believed the request happened in the distant past (or future), causing the cryptographic witness verification and timelock checks to fail.

Solution: i implemented a synchronized time management system for the demo. Instead of relying on system time, modified the demo server to fetch the authoritative timestamp directly from the simulated blockchain network. i also implemented a mechanism to manually "fast-forward" the blockchain state (using incrementGlobalSlot) to simulate the passing of the 24-hour timelock period instantly. This ensured that the onchain state and offchain proofs were perfectly aligned, allowing the burn transaction to verify successfully.

challenge 2: Railway Deployment Constraints deploying the demo to Railway was difficult because compiling the zero-knowledge circuits (ZkPrograms) is extremely memory-intensive. The build process would frequently crash the server or time out due to Railway's resource limits on the free tier.

solution: i optimized the build pipeline by pre-compiling the TS code locally and only running the lightweight server logic on Railway. i also added a SKIP_ZKPROGRAM_COMPILE environment variable to bypass the heavy circuit compilation in the cloud environment, using mock proofs for the live demo to ensure stability and speed.

challenge 3: Preventing Double-Spending A core risk in any bridge is "double-spending" where a user mints tokens on Mina using the same Zcash deposit multiple times. Since Zcash is private, we can't just check a public address balance.

Solution: i implemented a Nullifier Tracking System using a Merkle Map. Every valid Zcash deposit includes a unique "nullifier" (a cryptographic tag). When a deposit is bridged, its nullifier is recorded in the bridge's onchain state. The smart contract checks this set before every mint; if the nullifier already exists, the transaction is rejected. This guarantees that each Zcash deposit can be used to mint zkZEC exactly once, preserving privacy without sacrificing security.

Tracks Applied (2)

Cross-Chain Privacy Solutions

i built a privacy preserving bridge for zcash and mina
Mina Protocol

Mina Protocol

General Bounty

Project Tachyon

Discussion

Builders also viewed

See more projects on Devfolio