IMetalayerRecipient
and extends MessageBridgeProver
for common proving functionality.
Architecture
Configuration
router
: Chain-specific Metalayer router addressportal
: Portal contract that initiates provingprovers
: 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)
Metalayer router callshandle()
with message containing:
- 8 bytes: destination chain ID
- 64 bytes per intent:
[intentHash (32 bytes)][claimant (32 bytes)]
isWhitelisted(sender)
.
Fee Calculation
Domain IDs
Critical: Metalayer uses custom domain IDs, not chain IDs.sourceChainDomainID
parameter must be Metalayer’s domain ID. Consult Caldera Metalayer documentation for mappings.
Finality State
Messages are dispatched withFinalityState.INSTANT
:
Gas Limits
Minimum gas enforced during unpacking:MIN_GAS_LIMIT
is 200,000 gas.
Security
Whitelisting
Only provers in the whitelist can send messages:Access Control
- Only Metalayer router can call
handle()
- Only Portal can call
prove()
- Zero domain ID rejected:
if (origin == 0) revert ZeroDomainID()
Validation
Sender validation inhandle()
:
Integration Example
Advantages
- Lowest Costs: Generally cheapest among message bridge provers
- Instant Finality: Fast message delivery with
FinalityState.INSTANT
- Simple Configuration: No delegate setup, straightforward deployment
- Caldera Optimized: Native integration with Caldera rollups
Limitations
- Smallest Chain Coverage: Limited to Caldera-supported chains
- Less Mature: Newer infrastructure compared to Hyperlane/LayerZero
- Limited Tooling: Fewer third-party integrations and explorers
- Caldera Dependency: Primarily designed for Caldera rollup ecosystem
Errors
RouterCannotBeZeroAddress()
: Invalid router in constructorZeroDomainID()
: Origin domain is zero in handle()SenderCannotBeZeroAddress()
: Zero sender in handle()DomainIdTooLarge(uint64)
: Domain ID exceeds uint32.maxNonPortalCaller(address)
: Unauthorized prove() callerNotWhitelisted(bytes32)
: Sender not in whitelist