LayerZero
Symbiotic-secured DVN (Decentralized Verifier Network) for LayerZero V2 cross-chain messaging.
Overview
The LayerZero provider implements a DVN that uses Symbiotic shared security to verify cross-chain messages. When a message is sent through LayerZero's SendUln302, the DVN contract emits a JobAssigned event. Operators batch these jobs into Merkle trees, collect BLS signatures through Symbiotic relay sidecars, and submit the signed proof to the destination DVN contract. The destination DVN verifies the BLS quorum via the Settlement contract and forwards verification to LayerZero's ReceiveUln302.
Message Flow
Code Pointers
Contracts
contracts/src/SymbioticLayerZeroDVN.sol-- DVN contract handlingassignJob(source) andsubmitProof(destination)contracts/src/symbiotic/Settlement.sol-- BLS signature verification and quorum enforcementcontracts/src/symbiotic/KeyRegistry.sol-- Operator BLS public key registrycontracts/src/symbiotic/VotingPowers.sol-- Operator voting power trackingcontracts/src/symbiotic/Driver.sol-- Epoch and genesis managementcontracts/src/examples/TestOApp.sol-- Test application for sending/receiving messages
Operator (Rust)
operator/src/provider/layerzero.rs-- DecodesJobAssignedevents, stores messagesoperator/src/provider/mod.rs--Providertrait and registrationoperator/src/crypto/mod.rs-- Merkle tree construction, DVN leaf hashingoperator/src/signer/mod.rs-- Batches messages, requests BLS signaturesoperator/src/relay_submitter/mod.rs-- Submits signed proofs via OZ Relayer
Config Templates
config/templates/oz-monitor/monitors/layerzero_job_assigned.json-- Monitor job forJobAssignedeventsconfig/templates/oz-monitor/triggers/webhook_layerzero.json-- Webhook trigger template
Configuration
Select LayerZero as the active provider:
// config/environments/<env>.json
{
"activeProvider": "layerzero"
}Chain config is shared across providers and lives at the top level:
| Field | Description |
|---|---|
chains.source.chainId | Source chain ID |
chains.destination.chainId | Destination chain ID |
chains.source.eid | LayerZero endpoint ID for source |
chains.destination.eid | LayerZero endpoint ID for destination |
LayerZero predeploys (testnet/mainnet) go in chains.<role>.predeploys.layerzero:
{
"predeploys": {
"layerzero": {
"endpoint": "0x6EDCE65403992e310A62460808c4b910D972f10f",
"sendUln302": "0xC1868e054425D378095A003EcbA3823a5D0135C9"
}
}
}make deploy and make start use these values to generate runtime configs (destination_chains, chain_relayers, eid_to_chain_id) under generated/<env>/. Validation fails if chain IDs/EIDs drift from the generated deployment state.
Usage
# Select layerzero provider in config/environments/local.json
# "activeProvider": "layerzero"
# Start the stack
make start
# Send a test message
make send MSG="hello"
# Watch until destination verification
make watch
# Or run both in one shot
make e2emake send sends through TestOApp.send(...) which calls SendUln302, triggering DVN.assignJob().
make watch succeeds when destination target verification is observed on-chain.
See CLI Reference for full command options.
Common Issues
- Message stuck at "Processing" -- BLS signatures not aggregating. Check sidecar health and operator key registration. See Troubleshooting.
- Quorum not reached -- All 3 operators must be running and receiving the same events. See Troubleshooting.
- submitProof reverts -- Check that the OZ Relayer address is authorized as a submitter on the DVN contract, and that Settlement has correct operator keys. See Troubleshooting.