Skip to content
ZCash <> Aztec Bridge

ZCash <> Aztec Bridge

Bi-directional privacy preserving bridge (PoC)

Created on 3rd December 2025

ZCash <> Aztec Bridge

ZCash <> Aztec Bridge

Bi-directional privacy preserving bridge (PoC)

The problem ZCash <> Aztec Bridge solves

The bridge enables users to deposit ZEC to the bridge address (shielded transfer) and receive Bridged ZEC (bZEC) tokens privately minted to their wallet on Aztec network. They can also request withdrawal by privately burning the bZEC tokens on Aztec to get back ZEC on ZCash network all without leaking any private information related to the interacting parties.

How it works (100ft view):

  • Users create a private commitment/intent on Aztec and add the derived ticket ID in a shielded Zcash deposit as memo.
  • The operator sees that deposit, registers a ticket tied to the user’s intent indicating that a deposit is really made on ZCash network for the given ticket ID.
  • The user self-claims bZEC privately using their secret that was used to create the commitment.
  • For exits, users burn bZEC privately and leave a

    WithdrawalRequest

    note that encodes a Zcash unified address; the operator settles that out on Zcash.

All bridge accounting on Aztec uses private notes and private token mints/burns, and the on-chain logic enforces that the operator can’t redirect funds away from the intended Aztec recipient.

Challenges I ran into

I'm new to both ZCash and Aztec ecosystem so I faced several issues when building this project.

I had challenges in every step as I moved forward.

On the ZEC side, there aren't much resources/documentation to get started. I ended up spinning up some rust scripts to generate shielded addresses to be used for Bridge deposits, decoding memos sent to the wallet using the Viewing Key, syncing wallet balance and sending shielded transfer to a ZEC address.

On the Aztec side, the documentation was helpful but I couldn't get the examples working as they were pointing to a different version I guess, so I kept running into issues. Once I resolved it, there were a bit if hiccups in accessing private state variables. For ex, PublicMutable has different interface compared to PrivateImmutable. Private notes can only be written by their owner. We split state into two private maps (operator registration note and user claim) because the operator can’t mutate a user-owned note. This required redesigning the storage model. I spent a lot of time debugging the compilation issues over state access. Also it took a lot of attempts for me to realize that the scripts provided in the "aztec-starter" github repo will recreate/overwrite the pxe. So whenever I try to run scripts to test the flow, I got some generic "!self.is_some()" error message which was not useful to understand the root cause. Once I fixed the PXE, the issues went away. Also faced issues in storing the ZCash recipient (UA) address in Noir as there are no data types that supports storing such a large address (~180 bytes) - so I ended up splitting them into chunks before storing.

Tracks Applied (4)

Cross-Chain Privacy Solutions

Built privacy preserving bi-directional Aztec ZEC Bridge
Axelar Network

Axelar Network

Cross-Chain Privacy Solutions

Built privacy preserving bi-directional Aztec ZEC Bridge
Aztec

Aztec

Cross-Chain Privacy Solutions

Built the bi-directional privacy preserving bridge between ZCash Aztec
Osmosis

Osmosis

General Bounty

Built privacy preserving bi-directional Aztec ZEC Bridge

Project Tachyon

Discussion

Builders also viewed

See more projects on Devfolio