Tenzro Testnet is live. Get testnet TNZO

LayerZero

The LayerZero adapter enables omnichain messaging and token transfers between Tenzro Network and other blockchains using LayerZero V2 protocol. LayerZero provides ultra-light node verification and supports dozens of chains including Ethereum, Arbitrum, Optimism, Polygon, Avalanche, BNB Chain, and more.

Overview

LayerZero is an omnichain interoperability protocol that enables cross-chain messaging and token transfers through an innovative ultra-light node design. Unlike traditional bridges that rely on wrapped tokens or federated validators, LayerZero delivers messages directly between chains using independent oracles and relayers for security.

The Tenzro Network LayerZero adapter (LayerZeroAdapter) integrates with LayerZero V2 endpoints to provide:

  • Cross-chain message passing with guaranteed delivery
  • Native token transfers without wrapping
  • Peer management for supported chains
  • Nonce tracking for message ordering
  • Real JSON-RPC integration with EndpointV2 contracts
  • LayerZero Scan API integration for transfer status monitoring

Architecture

The LayerZero adapter sits within the tenzro-bridge crate as one of four bridge implementations. It implements the BridgeAdapter trait, providing a unified interface for cross-chain operations.

tenzro-bridge/
├── adapters/
│   ├── layerzero.rs         # LayerZero V2 adapter
│   ├── chainlink_ccip.rs    # Chainlink CCIP adapter
│   ├── debridge.rs          # deBridge adapter
│   └── canton.rs            # Canton enterprise adapter
├── router.rs                # Strategy-based routing
└── types.rs                 # Common bridge types

The adapter maintains state for:

  • Endpoint configuration — EndpointV2 contract address and chain ID
  • Peer registry — Trusted peer addresses on remote chains
  • Nonce counters — Per-destination outbound message nonces
  • Transfer tracking — In-flight transfer status monitoring

Key Features

Ultra-Light Nodes

LayerZero's breakthrough innovation is the ultra-light node (ULN) architecture. Instead of running full nodes for every chain, LayerZero uses:

  • Oracles — Provide block headers from the source chain
  • Relayers — Submit transaction proofs to the destination chain
  • Endpoint contracts — Verify proofs and deliver messages on-chain

This separation of concerns ensures that even if an oracle and relayer collude, they cannot forge invalid messages—the endpoint contract cryptographically verifies all proofs.

Message Security

All cross-chain messages on Tenzro Network use cryptographic signatures for authenticity. The TenzroMessage type includes built-in signing and verification:

use tenzro_bridge::types::{TenzroMessage, ChainType};
use tenzro_crypto::signatures::{Ed25519Signer, Signer};

// Create a message
let mut message = TenzroMessage {
    source_chain: ChainType::Tenzro,
    destination_chain: ChainType::Ethereum,
    payload: b"Transfer 100 TNZO to Alice".to_vec(),
    nonce: 42,
    sender: sender_address.clone(),
    signature: None,
    signer_public_key: None,
};

// Sign the message with Ed25519
let signer = Ed25519Signer::new(secret_key);
message.sign(&signer)?;

// Verify on the receiving side
assert!(message.verify_signature()?.is_valid);

Message signing uses tenzro-crypto primitives supporting both Ed25519 and Secp256k1 signatures. The verification process recovers the public key from the signature and validates it matches the claimed signer.

Peer Management

LayerZero requires explicit peer configuration to prevent unauthorized chains from sending messages. The adapter maintains a peer registry mapping chain IDs to trusted peer addresses:

// Add a trusted peer on Ethereum
adapter.add_peer(
    ChainType::Ethereum,
    "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb".to_string()
).await?;

// Check if a peer is trusted
if adapter.is_peer_trusted(&ChainType::Ethereum).await {
    // Send message to Ethereum peer
}

Configuration

The LayerZero adapter is configured through the LayerZeroConfig struct:

use tenzro_bridge::adapters::LayerZeroConfig;

let config = LayerZeroConfig {
    endpoint_address: "0x1a44076050125825900e736c501f859c50fE728c".to_string(),
    chain_id: 1337,  // Tenzro chain ID
    rpc_url: "https://rpc.tenzro.network".to_string(),
    scan_api_url: "https://scan.layerzero.network/api".to_string(),
    scan_api_key: Some("your_api_key".to_string()),
};

let adapter = LayerZeroAdapter::new(config).await?;

Configuration Parameters:

  • endpoint_address — LayerZero EndpointV2 contract address on Tenzro
  • chain_id — Tenzro Network chain ID (default: 1337)
  • rpc_url — JSON-RPC endpoint for Tenzro node
  • scan_api_url — LayerZero Scan API endpoint for transfer tracking
  • scan_api_key — Optional API key for LayerZero Scan

Usage Examples

Sending a Cross-Chain Message

use tenzro_bridge::adapters::LayerZeroAdapter;
use tenzro_bridge::types::{TenzroMessage, ChainType};

// Create adapter instance
let adapter = LayerZeroAdapter::new(config).await?;

// Create message to send to Ethereum
let message = TenzroMessage {
    source_chain: ChainType::Tenzro,
    destination_chain: ChainType::Ethereum,
    payload: serde_json::to_vec(&json!({
        "action": "transfer",
        "recipient": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
        "amount": "1000000000000000000"  // 1 TNZO (18 decimals)
    }))?,
    nonce: adapter.get_next_nonce(&ChainType::Ethereum).await?,
    sender: wallet_address.clone(),
    signature: None,
    signer_public_key: None,
};

// Send the message
let tx_hash = adapter.send_message(message).await?;
println!("Message sent in transaction: {}", tx_hash);

Bridging Tokens

use tenzro_bridge::types::{BridgeTransfer, BridgeAsset};

// Create a token transfer from Tenzro to Arbitrum
let transfer = BridgeTransfer {
    id: uuid::Uuid::new_v4().to_string(),
    source_chain: ChainType::Tenzro,
    destination_chain: ChainType::Arbitrum,
    asset: BridgeAsset::Tnzo,
    amount: 5_000_000_000_000_000_000,  // 5 TNZO
    sender: sender_address.clone(),
    recipient: recipient_address.clone(),
    status: TransferStatus::Pending,
    tx_hash: None,
    created_at: chrono::Utc::now(),
    completed_at: None,
};

// Execute the transfer
let tx_hash = adapter.bridge_tokens(transfer.clone()).await?;

// Monitor transfer status via LayerZero Scan API
let status = adapter.get_transfer_status(&transfer.id).await?;
match status {
    TransferStatus::Delivered => println!("Transfer completed!"),
    TransferStatus::Pending => println!("Transfer in progress..."),
    TransferStatus::Failed => println!("Transfer failed"),
}

Verifying Incoming Messages

// Verify a message received from another chain
let incoming_message = receive_message_from_layerzero().await?;

// Check message signature
let verification = incoming_message.verify_signature()?;
if !verification.is_valid {
    return Err("Invalid message signature");
}

// Check if sender chain is a trusted peer
if !adapter.is_peer_trusted(&incoming_message.source_chain).await {
    return Err("Untrusted source chain");
}

// Process the verified message
process_cross_chain_message(incoming_message).await?;

Supported Chains

LayerZero V2 supports 70+ blockchains. Common chains supported by the Tenzro adapter include:

ChainType::Ethereum        // Ethereum Mainnet
ChainType::Arbitrum        // Arbitrum One
ChainType::Optimism        // Optimism Mainnet
ChainType::Polygon         // Polygon PoS
ChainType::Avalanche       // Avalanche C-Chain
ChainType::BnbChain        // BNB Smart Chain
ChainType::Base            // Base (Coinbase L2)
ChainType::Solana          // Solana (via SVM bridge)
ChainType::Canton          // Canton enterprise chains

Bridge Router Integration

The BridgeRouter automatically selects the best adapter for each cross-chain operation based on configurable strategies:

use tenzro_bridge::router::{BridgeRouter, RoutingStrategy};

let router = BridgeRouter::new(RoutingStrategy::Cost);

// Add LayerZero adapter
router.add_adapter("layerzero", Box::new(layerzero_adapter)).await;

// Router automatically chooses LayerZero for supported chains
let transfer = BridgeTransfer { /* ... */ };
let result = router.route_transfer(transfer).await?;

Available routing strategies:

  • Cost — Minimize bridge fees
  • Speed — Minimize confirmation time
  • Availability — Use the first available adapter

Fee Estimation

LayerZero charges fees for oracle and relayer services. Estimate fees before sending messages:

// Estimate fee for a message to Ethereum
let estimated_fee = adapter.estimate_fee(
    &ChainType::Ethereum,
    1024  // payload size in bytes
).await?;

println!(
    "Estimated fee: {} wei (native gas on source chain)",
    estimated_fee
);

Note on Current Implementation:

Fee estimation currently returns static values. Dynamic gas price queries from LayerZero endpoints are planned for a future release (see issue #104 in production readiness audit).

Security Considerations

When using LayerZero bridge, keep these security principles in mind:

  • Always verify peer addresses — Only add trusted peers to the registry
  • Validate message signatures — Use verify_signature() on all incoming messages
  • Implement replay protection — Check nonces to prevent message replay (issue #102)
  • Monitor transfer status — Use LayerZero Scan API to track cross-chain transfers
  • Set reasonable limits — Implement maximum transfer amounts per transaction

Error Handling

use tenzro_bridge::error::BridgeError;

match adapter.send_message(message).await {
    Ok(tx_hash) => {
        println!("Message sent: {}", tx_hash);
    }
    Err(BridgeError::UntrustedPeer(chain)) => {
        eprintln!("Chain {:?} is not a trusted peer", chain);
    }
    Err(BridgeError::InvalidSignature) => {
        eprintln!("Message signature verification failed");
    }
    Err(BridgeError::InsufficientFee) => {
        eprintln!("Insufficient fee for cross-chain message");
    }
    Err(e) => {
        eprintln!("Bridge error: {:?}", e);
    }
}

Monitoring and Observability

The LayerZero adapter integrates with LayerZero Scan API for real-time transfer monitoring:

// Track a transfer using LayerZero Scan
let transfer_id = "550e8400-e29b-41d4-a716-446655440000";
let status = adapter.get_transfer_status(&transfer_id).await?;

println!("Transfer status: {:?}", status);
println!("Source tx: {:?}", transfer.tx_hash);

// Poll for completion
loop {
    let status = adapter.get_transfer_status(&transfer_id).await?;
    match status {
        TransferStatus::Delivered => {
            println!("Transfer delivered!");
            break;
        }
        TransferStatus::Failed => {
            eprintln!("Transfer failed!");
            break;
        }
        TransferStatus::Pending => {
            tokio::time::sleep(Duration::from_secs(10)).await;
        }
    }
}

Roadmap

The LayerZero adapter is under active development. Planned improvements include:

  • Dynamic gas price queries from LayerZero endpoints
  • Nonce-based replay protection for all message types
  • Automatic transfer status updates via event listeners
  • Support for custom oracles and relayers
  • Integration with Tenzro's ZK proof system for privacy-preserving transfers
  • Testnet deployment with live Ethereum/Arbitrum integration

Additional Resources