ILayerZeroReceiver
and extends MessageBridgeProver
for common proving functionality.
Architecture
Configuration
endpoint
: Chain-specific LayerZero V2 endpoint addressdelegate
: Set viaILayerZeroEndpointV2(endpoint).setDelegate(delegate)
- can configure paths and settingsprovers
: Whitelist of trusted provers on source chains (bytes32 format for cross-VM compatibility)minGasLimit
: Enforced minimum is 200,000 gas if zero or lower value provided
Proving Flow
Sending Proofs (Destination → Source)
Called by Portal after intent fulfillment:Receiving Proofs (Source Chain)
LayerZero endpoint callslzReceive()
with message containing:
- 8 bytes: destination chain ID
- 64 bytes per intent:
[intentHash (32 bytes)][claimant (32 bytes)]
isWhitelisted(origin.sender)
.
Fee Calculation
Domain IDs
Critical: LayerZero uses Endpoint IDs (eids), not chain IDs.sourceChainDomainID
parameter must be LayerZero’s endpoint ID. Consult LayerZero V2 Documentation for mappings.
Example:
- Ethereum: Chain ID 1 → Endpoint ID 30101
- Arbitrum: Chain ID 42161 → Endpoint ID 30110
Message Options
Default (Empty Options)
Custom Options
Pass encoded LayerZero options for advanced configurations:Security
Whitelisting
Only provers in the whitelist can send messages:Access Control
- Only LayerZero endpoint can call
lzReceive()
- Only Portal can call
prove()
- Path initialization allowed only for whitelisted senders
Gas Limits
Minimum gas enforced during unpacking:Integration Example
Advantages
- Wide Chain Support: 50+ chains including EVM and non-EVM
- Mature Infrastructure: Battle-tested with significant TVL
- Flexible Configuration: Delegate model allows operational control
- Good Tooling: LayerZero Scan for message tracking
Limitations
- Higher Costs: More expensive than native bridges ($5-50 per message)
- Domain ID Complexity: Endpoint IDs differ from chain IDs, requires mapping
- Gas Estimation: Must specify gas limit upfront, failures if underestimated
- Bridge Dependency: Relies on LayerZero infrastructure availability
Errors
EndpointCannotBeZeroAddress()
: Invalid endpoint in constructorDelegateCannotBeZeroAddress()
: Invalid delegate in constructorSenderCannotBeZeroAddress()
: Zero sender in lzReceiveDomainIdTooLarge(uint64)
: Domain ID exceeds uint32.maxInvalidExecutor(address)
: Unexpected executor addressNonPortalCaller(address)
: Unauthorized prove() callerNotWhitelisted(bytes32)
: Sender not in whitelist