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 Tenzrochain_id— Tenzro Network chain ID (default: 1337)rpc_url— JSON-RPC endpoint for Tenzro nodescan_api_url— LayerZero Scan API endpoint for transfer trackingscan_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