The ZRC-20 Standard

To make native privacy assets a practical and developer-friendly reality, ZeroLayer introduces the ZRC-20 standard. ZRC-20 is to private tokens what the ubiquitous ERC-20 standard is to public tokens: a predictable and standardized interface for creating and interacting with fungible assets.

What is ZRC-20?

ZRC-20 is a token standard for native privacy assets on EVM-compatible blockchains. It defines a unified interface that allows anyone to create privacy-preserving tokens as easily as deploying an ERC-20 contract. Like ERC-20, ZRC-20 provides standardized functions for token creation, transfer, and management—but with complete transaction confidentiality built into the core design.

Key Characteristics

  • Permissionless Creation: Anyone can create a ZRC-20 token through the PrivacyTokenFactory
  • Privacy-First Design: All balances, amounts, and transaction details are encrypted by default
  • Cryptographically Secured: Privacy guarantees are enforced by zero-knowledge proofs, not obscurity
  • Developer-Friendly: Familiar interface similar to ERC-20, but with privacy primitives
  • Composable: Can be integrated into DeFi protocols, DAOs, and other Web3 applications

A New Paradigm for Tokens

While a ZRC-20 token might feel like an ERC-20 from a user's perspective (it has a name, a symbol, and can be transferred), its underlying mechanics are fundamentally different and built entirely around privacy.

Feature ERC-20 (Public) ZRC-20 (Private)
State Model A public ledger of address -> balance An encrypted Merkle tree of "notes" (commitments)
Balance Check balanceOf(address) returns a public number No public balance function. Balance is computed locally by the owner.
Transfer Logic transfer(recipient, amount) transfer(proof, encryptedNotes)
Privacy None. All data is public. Full. Sender, receiver, and amount are shielded.
Security Based on public key cryptography. Based on zero-knowledge proofs and nullifiers.
State Storage Simple balance mapping Dual-layer Merkle tree (active + archived)
Double-Spend Prevention Account balance check Nullifier tracking system

Core Components of ZRC-20

Instead of tracking balances in a simple mapping, the ZRC-20 standard operates on three core cryptographic primitives that work together to provide privacy:

1. Commitments (Notes)

A commitment, or "note," is the fundamental unit of ownership in the ZRC-20 model. It is a cryptographic hash that binds together:

  • The token amount
  • The owner's stealth public key (a Baby Jubjub curve point)
  • A random salt value (for uniqueness)

Technical Construction:

commitment = Poseidon(stealthPublicKey_x, amount, salt)

Properties:

  • Hiding: The commitment reveals nothing about its contents to external observers
  • Binding: Cannot be opened to different values (prevents fraud)
  • Unique: Each commitment is distinct due to the random salt
  • Compact: Stored as a single 32-byte hash on-chain

On-Chain Storage: Commitments are stored as leaves in a dual-layer Merkle tree structure:

  • Active Subtree: Current working tree (16 levels, 65,536 capacity)
  • Finalized Root Tree: Archive of completed subtrees (20 levels, 1M+ capacity)

2. Nullifiers

To prevent a user from spending the same note twice (double-spending), the protocol uses nullifiers. A nullifier is a unique serial number cryptographically derived from the note's secrets and the owner's private key.

Technical Construction:

nullifier = Poseidon(commitment, stealthPrivateKey)

Properties:

  • Uniqueness: Each note has exactly one nullifier
  • Unlinkability: Cannot be linked back to the original commitment without the private key
  • Permanent: Once recorded on-chain, a nullifier marks a note as spent forever
  • Unforgeable: Only the legitimate owner can compute the correct nullifier (proven via ZK-SNARK)

Double-Spend Prevention: When a note is spent, its nullifier is revealed and recorded in the smart contract's nullifier set. Any subsequent attempt to spend the same note (with the same nullifier) will be rejected by the contract.

3. Zero-Knowledge Proofs

The zero-knowledge proof is the cryptographic engine that makes the entire system work securely and privately. When a user wants to perform any operation (mint, transfer, unshield), they generate a zk-SNARK proof that demonstrates the validity of the transaction without revealing any sensitive information.

What the Proof Demonstrates:

For a Transfer operation, the proof cryptographically proves:

  • ✅ Input notes exist in the Merkle tree (membership proof)
  • ✅ The user possesses the secret keys to spend those notes (ownership proof)
  • ✅ Nullifiers are correctly computed from the private keys (prevents forgery)
  • ✅ Total input value equals total output value (conservation of value)
  • ✅ Output notes are properly constructed (integrity check)
  • ✅ All cryptographic operations are correctly performed

Proof System:

  • Type: Groth16 zk-SNARKs on the BN254 curve
  • Circuits: Written in Circom language
  • Verification: Performed by specialized on-chain verifier contracts
  • Constraints: 20K-50K constraints depending on operation type
  • Generation Time: 1-4 seconds (client-side)
  • Verification Time: <100ms (on-chain)

The ZRC-20 Interface

Standard Functions

The ZRC-20 interface provides three core operations:

mint(proofType, proof, encryptedNote)

Purpose: Convert public assets (ERC-20 or ETH) into private ZRC-20 notes (also called "shielding")

Parameters:

  • proofType: 0 for regular mint, 1 for rollover mint (when subtree is full)
  • proof: The ZK-SNARK proof with public signals
  • encryptedNote: Encrypted note data for the recipient's wallet to decrypt

Process:

  1. User transfers public tokens to the contract
  2. Submits ZK proof demonstrating ownership and commitment construction
  3. Contract verifies proof and adds commitment to Merkle tree
  4. Emits CommitmentAppended and Minted events

transfer(proofType, proof, encryptedNotes)

Purpose: Execute a private transfer between ZeroLayer users

Parameters:

  • proofType: 0 (active), 1 (finalized), or 2 (rollover) depending on input source
  • proof: ZK-SNARK proof demonstrating valid state transition
  • encryptedNotes: Array of encrypted notes for recipients

Process:

  1. User generates proof consuming input notes and creating output notes
  2. Contract verifies proof
  3. Marks input nullifiers as spent
  4. Adds output commitments to Merkle tree
  5. Emits NullifierSpent, CommitmentAppended, and Transaction events

unshield(proofType, proof, encryptedNotes, recipient)

Purpose: Convert private ZRC-20 notes back to public assets (withdrawal)

Parameters:

  • proofType: Transfer proof type
  • proof: ZK proof with special burn address output
  • encryptedNotes: Encrypted note data
  • recipient: Public Ethereum address to receive tokens

Process:

  1. User creates transfer proof where first output goes to special burn address
  2. Contract verifies proof and extracts withdrawal amount
  3. Burns privacy notes by marking nullifiers as spent
  4. Sends underlying ERC-20/ETH to recipient (minus protocol fee)
  5. Emits Unshielded event

Metadata Functions

Like ERC-20, ZRC-20 provides standard metadata:

  • name(): Token name (e.g., "Privacy USDC")
  • symbol(): Token symbol (e.g., "pUSDC")
  • decimals(): Token decimals (inherited from underlying asset)
  • totalSupply(): Total shielded supply (public)

State Query Functions

Additional functions for querying the protocol state:

  • activeSubtreeRoot(): Current active Merkle tree root
  • finalizedRoot(): Archived subtrees root
  • nullifiers(bytes32): Check if a nullifier has been spent

How Notes Work

Note Structure

Each note contains the following information (encrypted):

{
  amount: uint256,                  // Token quantity
  stealthPublicKey: [uint256, uint256],  // Owner's Baby Jubjub public key
  salt: uint256                     // Random value for uniqueness
}

Stealth Addresses

To protect recipient privacy, ZRC-20 uses stealth address technology:

  1. Sender generates an ephemeral key pair
  2. Sender performs ECDH key exchange with recipient's public scan key
  3. Sender derives a one-time stealth public key for this transaction
  4. Recipient can detect and decrypt notes using their private scan key

This ensures that even if someone knows your ZeroLayer address, they cannot see which transactions are sent to you by analyzing the blockchain.

View Tags

To make transaction scanning efficient, each transaction includes a view tag—a single-byte identifier derived from the shared secret. Recipients can:

  1. Quickly filter transactions by view tag (reduces scanning by 256x)
  2. Only attempt decryption on matching transactions
  3. Achieve ~40% reduction in client-side scanning costs

Note Encryption

Notes are encrypted using:

  • ECDH: Key exchange using Baby Jubjub elliptic curve
  • AES-GCM: Authenticated encryption with 128-bit security
  • Semantic Security: Each note encryption is indistinguishable from random data

Only the intended recipient (with the correct private key) can decrypt and read the note.


The Dual-Layer Merkle Tree

ZRC-20 uses a sophisticated two-tier Merkle tree architecture for scalability:

Active Subtree (Layer 1)

  • Purpose: Store recent notes for fast access
  • Height: 16 levels
  • Capacity: 65,536 leaves
  • Usage: Used for low-cost "active transfers"

Root Tree (Layer 2)

  • Purpose: Archive completed subtrees
  • Height: 20 levels
  • Capacity: 1,048,576 subtrees (68 billion notes total)
  • Usage: Provides historical note access via "finalized transfers"

Rollover Mechanism

When the active subtree reaches capacity (65,536 notes):

  1. The current active root is archived into the root tree
  2. A new empty active subtree is created
  3. New notes are added to the fresh subtree
  4. Old notes remain accessible via finalized transfer proofs

This design enables:

  • Horizontal Scalability: Millions of transactions supported
  • Cost Optimization: Recent notes have lower verification costs
  • Historical Access: All notes remain spendable indefinitely

Privacy Guarantees

What is Hidden

When using ZRC-20 tokens, the following information is completely private:

  • Transaction amounts: How much was sent
  • Sender identity: Who initiated the transaction
  • Recipient identity: Who received the funds
  • Account balances: How much any user holds
  • Transaction graph: Links between senders and receivers
  • Transaction history: Past spending patterns

What is Public

To enable verification and prevent fraud, some information remains public:

  • 📊 Commitment hashes: Opaque identifiers for notes
  • 📊 Nullifier hashes: Opaque identifiers for spent notes
  • 📊 Merkle tree roots: Cryptographic state commitments
  • 📊 Total supply: Aggregate shielded amount
  • 📊 Transaction count: Number of operations performed

Important: All public data is cryptographically opaque—it cannot be used to infer amounts, identities, or relationships.


Security Properties

Cryptographic Foundations

ZRC-20's security relies on:

  • Elliptic Curve Security: Baby Jubjub curve based on Twisted Edwards curves
  • Hash Function Security: Poseidon hash optimized for zero-knowledge proofs
  • Proof System Security: Groth16 zk-SNARKs with 128-bit security level
  • Encryption Security: AES-GCM with semantic security guarantees

Protocol Guarantees

The ZRC-20 standard provides:

  1. Double-Spending Prevention: Enforced by on-chain nullifier tracking
  2. Value Conservation: Proven cryptographically (no inflation possible)
  3. Ownership Proof: Only true owners can generate valid proofs
  4. Replay Protection: Each proof is bound to specific inputs
  5. State Integrity: Merkle trees provide tamper-evident history

Trust Model

  • Non-Custodial: Users always control their funds via private keys
  • Trustless Verification: Smart contracts verify proofs mathematically
  • Transparent Logic: All code is open-source and auditable
  • Decentralized: No central authority or admin keys

Creating a ZRC-20 Token

Using the Factory

Anyone can create a new ZRC-20 token through the PrivacyTokenFactory:

// For ERC-20 tokens
factory.createToken(underlyingTokenAddress)

// For native ETH
factory.createToken(address(0))

The factory automatically:

  1. Reads metadata from the underlying token (name, symbol, decimals)
  2. Deploys a new ZRC-20 privacy token contract
  3. Configures all verifier contracts
  4. Initializes the Merkle tree structure
  5. Sets up the burn address for unshielding

Creation Fee: Small fee (e.g., 0.0005 ETH) to prevent spam deployments

Token Naming Convention

Created tokens follow a consistent naming pattern:

  • Underlying: "USD Coin" (USDC)
  • ZRC-20: "Privacy USD Coin" (pUSDC)

This makes it easy for users to identify privacy-wrapped versions of familiar tokens.


Comparison with Other Privacy Solutions

vs. Mixers (Tornado Cash)

Feature Mixers ZRC-20
Privacy Source Anonymity set size Mathematical proofs
Asset Type Obscures public tokens Creates new private assets
User Flow Deposit → Wait → Withdraw Shield → Transfer freely → Unshield
Composability Limited High (can be used in DeFi)
Privacy Guarantee Statistical Cryptographic

vs. Confidential Transactions

Feature Confidential Transactions ZRC-20
Amounts Hidden ✅ Yes ✅ Yes
Senders Hidden ❌ No ✅ Yes
Recipients Hidden ❌ No ✅ Yes (stealth addresses)
Implementation Requires chain modifications Works on any EVM chain

vs. Private Blockchains

Feature Private Chains ZRC-20
Privacy Full Full
Decentralization ❌ Permissioned ✅ Permissionless
Composability ❌ Isolated ✅ Interoperable with public DeFi
Trust Model Federation Smart contracts

Composability with DeFi

How ZRC-20 Works with Existing DeFi

One of the most powerful features of ZRC-20 is its seamless integration with the existing DeFi ecosystem. Unlike privacy solutions that create isolated pools, ZRC-20 tokens can be converted back to standard ERC-20 tokens at any time, allowing users to leverage the full DeFi landscape while maintaining privacy when needed.

The Shield-Use-Unshield Cycle

ZRC-20 enables a flexible privacy workflow:

┌─────────────────────────────────────────────────────┐
│  Private World (ZRC-20)                             │
│  ┌─────────────────────────────────────────┐        │
│  │  User holds pUSDC                       │        │
│  │  • Balance: Private                     │        │
│  │  • Transfers: Anonymous                 │        │
│  │  • History: Encrypted                   │        │
│  └─────────────────────────────────────────┘        │
│                    ↕ SHIELD/UNSHIELD                │
└─────────────────────────────────────────────────────┘
                     ↕
┌─────────────────────────────────────────────────────┐
│  Public DeFi World (ERC-20)                         │
│  ┌─────────────────────────────────────────┐        │
│  │  • Uniswap: Trade USDC for other tokens │        │
│  │  • Aave: Lend/Borrow USDC               │        │
│  │  • Compound: Earn interest on USDC      │        │
│  │  • Curve: Provide liquidity              │        │
│  └─────────────────────────────────────────┘        │
└─────────────────────────────────────────────────────┘

Practical Integration Examples

Example 1: Private Trading on Uniswap

Scenario: Alice wants to trade USDC for ETH without revealing her portfolio size.

Process:

  1. Start: Alice holds 10,000 pUSDC (private)
  2. Unshield: Alice unshields 5,000 pUSDC → 5,000 USDC (public)
  3. Trade: Alice swaps 5,000 USDC for 2 ETH on Uniswap
  4. Shield: Alice shields 2 ETH → 2 pETH (private again)
  5. Result: Alice now has 5,000 pUSDC + 2 pETH, remaining balance (5,000 pUSDC) stayed private

Privacy Benefits:

  • Her total holdings remain hidden
  • Only the specific trading amount is temporarily public
  • Transaction cannot be linked to her other private transfers

Example 2: Private Lending with Aave

Scenario: Bob wants to earn yield on his tokens while keeping his wealth private.

Process:

  1. Start: Bob holds 50,000 pUSDC (private)
  2. Unshield: Bob unshields 30,000 pUSDC → 30,000 USDC
  3. Deposit: Bob deposits 30,000 USDC into Aave
  4. Earn: Bob earns interest for 6 months → receives 31,500 USDC
  5. Withdraw: Bob withdraws 31,500 USDC from Aave
  6. Shield: Bob shields 31,500 USDC → 31,500 pUSDC
  7. Result: Bob now has 51,500 pUSDC total (20,000 never left privacy + 31,500 returned)

Privacy Benefits:

  • His total wealth remains private
  • Only the lending position is temporarily visible
  • Yield is re-shielded immediately after withdrawal

Example 3: Private Liquidity Provision

Scenario: Carol wants to provide liquidity to a DEX without exposing her holdings.

Process:

  1. Start: Carol holds 100,000 pUSDC + 50 pETH (private)
  2. Unshield: Carol unshields portions → 50,000 USDC + 25 ETH
  3. Add Liquidity: Carol adds to Uniswap USDC/ETH pool
  4. Earn Fees: Carol earns trading fees over time
  5. Remove Liquidity: Carol withdraws her position + earned fees
  6. Shield: Carol shields all proceeds back to pUSDC + pETH
  7. Result: Carol's total holdings remain mostly private, only the LP position was public

Privacy Benefits:

  • Main wealth stays private
  • Only LP position is visible
  • Fees can be re-shielded immediately

Composability Advantages

ZRC-20's design provides unique composability benefits:

✅ Best of Both Worlds

  • Privacy: When holding funds in ZRC-20 form
  • Functionality: When temporarily converting to ERC-20 for DeFi

✅ Time-Limited Exposure

  • Funds only become public for the duration of DeFi interaction
  • Immediately re-shield after completing operations
  • Minimizes blockchain footprint

✅ Selective Transparency

  • Choose which transactions to make public (DeFi interactions)
  • Keep everything else private (holdings, transfers, savings)
  • Granular control over privacy vs. functionality

✅ No Protocol Lock-In

  • Not limited to ZeroLayer ecosystem
  • Can use any ERC-20-compatible protocol
  • Freedom to leverage entire Ethereum DeFi stack

✅ Future-Proof Design

  • As more protocols add native ZRC-20 support, privacy improves
  • No need to change user behavior or holdings
  • Gradual ecosystem evolution towards privacy

Conclusion

The ZRC-20 standard represents a breakthrough in blockchain privacy technology. By combining zero-knowledge proofs, stealth addresses, and efficient cryptographic primitives, it delivers:

  • True Privacy: Cryptographically guaranteed confidentiality
  • Full Functionality: Complete token lifecycle (mint, transfer, burn)
  • Ease of Use: Familiar interface for developers
  • Scalability: Supports up to 68,719,476,736 notes (1,048,576 subtrees × 65,536 leaves per subtree)
  • Composability: Works with existing DeFi infrastructure

The ZRC-20 standard makes privacy a fundamental right, not a luxury feature. It empowers developers to build the next generation of privacy-preserving financial applications while maintaining the openness and decentralization that make blockchain technology valuable.

With ZRC-20, anyone can create a fully private token as easily as deploying an ERC-20 contract—opening the door to a new wave of confidential, yet verifiable, on-chain economies.

results matching ""

    No results matching ""