立刻保护您的项目
借助最大的web3安全提供商来增强您的项目。
CertiK 安全专家将审核您的请求,并尽快与您联系。

Hiding in Plain Sight: zERC20 and zk-Proof-of-Burn

技术博客 ·教育 ·
Hiding in Plain Sight: zERC20 and zk-Proof-of-Burn

Introduction

The blockchain is a dark forest, but it is illuminated by floodlights. Every transaction, every wallet interaction, and every token transfer is permanently recorded on a public ledger. This level of transparency guarantees trust, but it costs us a fundamental human right: privacy.

As Vitalik Buterin argued in a 2025 post, “Privacy is freedom, privacy is order, privacy is progress.” In a hyper-transparent digital ecosystem, privacy is the only way to prevent systemic chaos, protect user agency, and enable real institutional adoption. True privacy is not about hiding malicious acts; it is about having the freedom to choose what you reveal.

But how do we engineer this freedom on the EVM?

For years, the industry has struggled with this exact question. In this article, we are going to dive deep into an emerging privacy solution: zERC20. zERC20 is a pragmatic, immediate implementation of a concept known as plausible deniability (originally proposed in EIP-7503), which means the cryptographic evidence of an action equally supports a completely innocent explanation. For zERC20, depositing funds into the privacy protocol is mathematically indistinguishable from a user accidentally sending tokens to a dead address.

By the end of this deep dive, you will understand exactly how zERC20 works under the hood, and how it elegantly overcomes the limitations of traditional privacy protocols.

Privacy Pools vs. EIP-7503

To understand zERC20 and its underlying EIP-7503, we will first examine the fundamental limitations in traditional privacy solutions, such as Tornado Cash.

1. Opt-In Issue of Privacy Pools

Traditional solutions rely on a Privacy Pool model, where users deposit funds into a highly visible smart contract. While the underlying ZK cryptography works to hide the connection between sender and receiver, the architecture itself creates an operation security nightmare. Interacting with a known mixer is an explicit opt-in signal. Compliance and chain analysis tools immediately flag your address as tainted. You successfully hide the recipient, but you permanently broadcast the act of hiding it. This completely destroys any plausible deniability.

2. EIP-7503 (zk-Proof-of-Burn)

EIP-7503 abandons the centralized smart contract pool entirely with the zk-Proof-of-Burn protocol. Instead of depositing into a contract, it hashes a private secret and recipient address to generate a dead account: an address with no known private key or contract code. The sender then simply transfers native ETH (or ERC20 tokens) to this dead account.

On the blockchain, this is completely indistinguishable from an everyday transfer to a newly created address. No privacy smart contracts are triggered; no fingerprints are left behind.

To retrieve the funds, the receiver submits a Zero-Knowledge Proof to the network, proving they know the secret that generated that specific dead address. Upon verification, the network mints the equivalent funds to the recipient address. By shifting the anonymity set from mixer users to every fresh address on Ethereum, EIP-7503 achieves true plausible deniability.

zERC20 Workflow

While EIP-7503 provides the theoretical foundation for Proof-of-Burn privacy, natively implementing it requires an Ethereum hard fork. zERC20 takes a more pragmatic path: it bridges this zk-Wormhole logic to the application layer.

So, how does it actually work in production? Let's break down the exact cryptographic workflow:

1. Generating Stealth Address

A stealth address is a randomly generated address intended for one-time use. Unlike the simple random hash used in the original EIP-7503 proposal, zERC20 explicitly encodes cross-chain routing and withdrawal strategies directly into the stealth address. The receiver first computes a recipient commitment using standard SHA-256:

digest = sha256(recipient_chain_id, recipient_address, tweak)

To safely fit this digest within the scalar field of SNARK-friendly curves (like BN254) and allow for future upgrades, the protocol applies a masking technique. It keeps the lower 248 bits of the hash and embeds an 8-bit Version ID in the highest bits:

recipient = [VERSION (8 bits)] || [masked_digest (248 bits)]

Then, this versioned commitment is hashed with a blinding secret to derive the final EVM address. Crucially, the ZK circuit uses a three-input Poseidon3 hash with a fixed domain separator ("burn"):

burn_address = truncate_160(poseidon3("burn", recipient, secret))

2. Silent Transfer (Deposit)

The sender receives this burn_address. To the sender and the blockchain, this is just a standard ERC-20 transfer(). The tokens are sent and locked in this dead account. No privacy-preserving smart contracts are called. No mixer fingerprints are left behind.

3. Rebirth (Withdrawal)

To get the funds back on the destination chain, the receiver does not call the token contract directly. Instead, they interact with the Verifier Contract.

They provide a Zero-Knowledge Proof showing: "I know the secret and the exact recipient payload that generated this specific burn_address which has received funds."

Once verified, the Verifier contract mints an equivalent amount of zERC20 tokens to the clean recipient_address.

Chart 1

Unpacking ZK Magic and the Two-Circuit Architecture

In the previous section, we mentioned that the receiver uses a Zero-Knowledge Proof (ZKP) to rebirth the tokens. Before we dive into the performance of zERC20, let’s briefly clarify this.

1. Magic of Zero-Knowledge Proofs

A Zero-Knowledge Proof allows you to prove that a statement is true without revealing the underlying data.

In zERC20, the receiver needs to prove to the smart contract: "I own the secret for a specific burn_address that recently received funds."

By using a ZKP, the receiver cryptographically proves the ownership, but leaves zero trace of which specific burn_address he/she is claiming from. The link between the sender and receiver is completely removed.

2. 900k Gas Bottleneck

In legacy privacy protocols like Tornado Cash, the smart contract maintains a Sparse Merkle Tree (SMT) on-chain to track deposits. Every time someone makes a deposit, the contract must recalculate and update this tree. Inside the EVM, this is brutally expensive—costing upwards of 900,000 gas.

zERC20 solves this by using a lightweight on-chain transfer_hash_chain (~47k gas) and delegating the heavy lifting of SMT construction to two specialized off-chain ZK circuits using Nova IVC.

3. Two Gears: Root Transition vs. Withdraw Circuits

To securely bridge the simple on-chain Hash Chain with the complex off-chain SMT, zERC20 defines two distinct circuits.

Before diving into their mechanics, it is crucial to clarify the terminology. In the realm of Zero-Knowledge Proofs, any logic you wish to prove cannot be written as standard code; it must be mathematically formalized into a set of arithmetic constraints, collectively known as a Circuit.

Furthermore, zERC20 leverages the Nova proof system, which specializes in Incrementally Verifiable Computation (IVC). Instead of generating one massive, expensive proof for a monolithic computation, Nova proves continuous state updates step-by-step, folding the previous proof into the new one. This is exactly why the foundational circuits described below are designated as Step Circuits—they define the strict logic for a single, repeatable step in the state transition. (Note: To make these folded proofs cheap enough for EVM verification, they are eventually compressed into a final Decider Proof, which we will discuss later.)

A. Root Transition Step Circuit (State Sync)

This circuit is the engine behind the Nova folding scheme for deposits. Its job is to prove that the off-chain Merkle Tree correctly reflects the sequential deposits accumulated in the on-chain Hash Chain.

  • Public Inputs/Outputs: It takes the previous transfer_root (e.g., prev_transfer_root), on-chain transfer_hash_chain (e.g., prev_hash_chain), as well as the insertion position, and outputs the updated new_transfer_root and new_hash_chain.
  • Private Inputs: the transaction address from and to, the amount value, and the Merkle inclusion proof of transfer tree for the insertion position.
  • Logic: The circuit enforces a cryptographic binding between the log and the tree using the shared private witnesses to and value. First, it verifies that hashing from , to and value into the prev_hash_chain correctly results in the public new_hash_chain. Simultaneously, it inserts the exact same from ,to and value into the prev_transfer_root using the provided merkle proof, producing the new_transfer_root. This guarantees that every Merkle Tree update is strictly derived from valid on-chain deposits.

Chart 2

B. Withdraw Circuit (Claim)

This circuit handles user withdrawals and proves ownership of specific deposits without revealing their exact origins. Notably, zERC20 does not use traditional nullifiers to prevent double-spending; instead, it uses an ingenious cumulative value tracking mechanism.

  • Public Inputs/Outputs: It takes the recipient , transfer_root, prev_index_with_offset, and prev_total_value as public inputs. It outputs the updated new_total_value and new_index_with_offset.
  • Private Inputs (Witness): The receiver’s secret, the deposit value, the sender's address from, the leaf index of that transfer, and the Merkle inclusion proof.
  • Core Logic: The circuit uses the recipient and secret to reconstruct the burn_address. It then verifies that this address, holding the specific value, is validly included in the transfer_root at the given index using the merkle_proof. To aggregate multiple withdrawals in one Nova proof, the circuit enforces a strictly increasing index (preventing double withdrawals within the same proof) and adds the value to the prev_total_value to output the new_total_value.
  • Double-Spend Prevention (On-Chain): Instead of maintaining a costly nullifier tree, the Verifier contract simply records totalTeleported[recipient]. When a user submits the proof, the contract computes delta = proof.new_total_value - totalTeleported[recipient]. If delta > 0, it mints exactly that difference, making double-spending mathematically impossible.

By decoupling State Synchronization (Root Transition) from User Claims (Withdraw), zERC20 achieves robust privacy at a fraction of the traditional cost. The circuit logic detailed above captures the core engineering implementation found in the zkp/src/circuits directory. Note that some low-level constraints have been simplified here for narrative clarity; for the exact specifications, we encourage readers to inspect the source code directly.

Omnichain Architecture

The true power of zERC20 lies in its Omnichain nature. Based on the official smart contract source code and architecture specifications, this is achieved through three highly specialized components working in harmony.

1. zERC20 Contract

Deployed on every supported chain, this contract (zERC20.sol) acts as an upgradeable ERC-20 token and a LayerZero OFT (Omnichain Fungible Token).

  • Universal Hash Chain: The contract overrides the standard ERC-20 _update hook. Every single balance change is hashed into a continuous, local state variable named hashChain (this is exactly the transfer_hash_chain we analyzed in the previous section). The value is strictly enforced to fit within 248 bits to remain compatible with the BN254 ZK circuits.
  • Mint Authority: It exposes a teleport function to mint new tokens. This function is strictly protected and can only be called by the designated Verifier contract.

2. Verifier Contract

Deployed alongside every zERC20 contract, the Verifier (Verifier.sol) is a LayerZero OApp. It acts as the local brain, bridging the token's hash chain with off-chain ZK provers and the cross-chain Hub.

  • State Sync:

    1. It first takes a snapshot of the token's current `hashChain` via `reserveHashChain()`.
    2. Once the off-chain Prover finishes the heavy computation, it accepts the Nova proof via `proveTransferRoot()` to verify the off-chain Merkle Tree update, storing the result in `provedTransferRoots`.
    
  • Cross-Chain Outbound (relayTransferRoot): It actively pushes its latest local proven root to the central Hub via LayerZero messaging.

  • Cross-Chain Inbound (_lzReceive): It receives the updated global aggregationRoot from the Hub and stores it locally in globalTransferRoots.

  • Withdrawal Execution (teleport): It accepts user ZK proofs. It verifies inclusion against either the local or global roots, enforces the cumulative delta logic (updating totalTeleported to prevent double-spending), and finally instructs the zERC20 contract to mint the exact unspent delta.

3. Hub Contract

The Hub (Hub.sol) is the central LayerZero OApp, typically deployed on a single main settlement chain.

  • Root Collection (_lzReceive): It passively receives local transferRoot payloads from registered Verifier contracts across the network.
  • Cross-Chain Aggregation (broadcast): When triggered, it aggregates all the latest local roots into a dedicated Poseidon tree (designed with up to 64 leaves to support multiple blockchains). It then broadcasts this new global aggregationRoot back to all the targeted LayerZero Endpoint IDs specified by the caller.

4. Cross-Chain Transfer

With the actual codebase mapped, the lifecycle of a private cross-chain transfer is crystal clear:

  1. Transfer Emission: The sender sends tokens to a stealth address on the zERC20 contract (Chain A). This action advances the local hashChain.
  2. Prove & Relay: An off-chain indexer calls reserveHashChain() to lock the state and locally generates a Nova IVC proof for the root transition. This proof is then sent to the Decider Prover to be compressed into an EVM-friendly Decider proof. An off-chain agent submits this final proof via proveTransferRoot() to the Verifier (Chain A). Subsequently, an off-chain agent calls relayTransferRoot() on the Verifier to send this local root to the Hub.
  3. Aggregate & Broadcast: The Hub receives the root. An off-chain agent triggers broadcast, which pushes the updated global Poseidon tree root to the Verifier (Chain B).
  4. Private Teleport: The receiver generates a Nova IVC proof locally, which is then passed through an off-chain Decider to create an EVM-friendly proof. He submits this final proof to the Verifier (Chain B), referencing the newly received global root. The Verifier calculates the unspent delta, records it, and calls zERC20.teleport() to securely mint tokens.

Chart 3

Technical Considerations and Performance Infrastructure

As we have explored, zERC20 offers a sophisticated solution to on-chain privacy. However, achieving this level of efficiency involves specific technical trade-offs and off-chain infrastructure requirements.

  • Two-Stage Proving Architecture: Verifying a raw Nova IVC proof directly on the EVM is computationally unfeasible. Therefore, zERC20 utilizes a two-stage verification pipeline. First, state transitions are sequentially folded into a Nova IVC proof (handled locally by the Client or off-chain by the indexer). Second, a heavy off-chain Decider Prover (decider-prover) converts this massive IVC proof into a final, EVM-friendly Decider Proof. While this composite approach successfully brings verification costs down to standard EVM levels, operating the Decider Prover to generate these final proofs is a highly resource-intensive task requiring dedicated hardware.
  • Latency of State Finality: The protocol's omnichain synchronization relies on an off-chain indexer to monitor local hashChain updates and a central Hub to aggregate them. Consequently, there is a natural delay between a "Burn" on one chain and a "Mint" on another. The global state must be propagated through cross-chain messaging before a withdrawal proof becomes valid. This makes the privacy-preserving transfer an asynchronous process rather than an instantaneous one.
  • Off-Chain Reliability: The integrity and liveliness of the Global Merkle Tree depend on the continuous operation of the decider-prover, the indexer, and the cross-chain relayers. Ensuring the decentralization and uptime of these off-chain components is a critical area for the long-term robustness of the network.

Privacy as a Scalable Primitive

The emergence of zERC20 marks a significant milestone in the practical implementation of EIP-7503. By moving the logic from the Ethereum consensus layer to the ERC-20 application layer, the project has made "Plausible Deniability" an immediately available tool for the EVM ecosystem.

The core innovation lies in the synergy between off-chain folding schemes and on-chain Hash Chains. This combination successfully breaks the "High Gas" curse that has plagued privacy protocols for years, proving that robust anonymity does not have to be prohibitively expensive.

As the industry moves toward a more mature understanding of digital sovereignty, zERC20 stands as a testament to Vitalik Buterin’s vision: Privacy is progress. It is a scalable, efficient, and philosophically grounded bridge toward a future where "hiding in plain sight" is the standard for secure digital interaction.

References

  1. zERC20: https://zerc20.io/
  2. EIPS-7503: https://eip7503.org/
  3. 2077 Research: EIP-7503: Zero-knowledge Wormholes for Private Ethereum Transactions
  4. NUNO: zERC20: Cross-Chain Private ERC-20 Based on ZK Proof-of-Burn
  5. zERC20 Github Repository: https://github.com/kbizikav/zERC20/tree/dev
  6. Abhiram Kothapalli, Srinath Setty, Ioanna Tzialla, 2021: Nova: Recursive Zero-Knowledge Arguments from Folding Schemes.
  7. Jens Groth, 2016: On the Size of Pairing-Based Non-interactive Arguments.
  8. Poseidon Hash: https://www.poseidon-hash.info/.
  9. Vitalik Buterin, 2025: Why I support privacy.

相关博客

CertiK Completes Proof of Reserves  Verification for Gate Dubai
新的 · 消息 ·公告

CertiK Completes Proof of Reserves Verification for Gate Dubai

CertiK has completed an independent Proof of Reserves (PoR) audit for Gate Technology FZE, the Dubai-based entity of the Gate Group. Gate Dubai exchange is licensed by the Virtual Assets Regulatory Authority (VARA). The audit verified that the platform's on-chain reserves fully back its user liabilities across all in-scope assets as of December 31, 2025.

SOF/LAXO Incident Analysis

SOF/LAXO Incident Analysis

In February 2026 two separate exploits occurred on the BNB Smart Chain (BSC), affecting SOF and LAXO tokens, leveraging the same class of vulnerability: a flawed token burn mechanism that allowed price manipulation within a single transaction.

Designing Proof of Reserves for Tokenized Gold

Designing Proof of Reserves for Tokenized Gold

When you buy a real world asset like tokenized gold, the token lives on-chain, but the gold does not. It sits in a vault, managed by a custodian, documented through paper records and serial numbers. The chain confirms you own the token, but it cannot confirm the gold exists.