Skip to main content

Overview

MetaProver processes proof messages from Caldera Metalayer’s router and records proven intents. It extends MessageBridgeProver to provide Metalayer-specific messaging functionality. Contract: contracts/prover/MetaProver.sol Inheritance: IMetalayerRecipient, MessageBridgeProver, Semver Proof Type: "Meta"
In MetaProver documentation, “source” refers to the chain where the intent was created, and “destination” refers to the chain where the intent is fulfilled.
Domain ID vs Chain ID: Metalayer uses domain IDs specific to their routing system. Consult Metalayer’s documentation for the correct domain ID mapping.

Constructor

constructor(
    address router,
    address portal,
    bytes32[] memory provers,
    uint256 minGasLimit
)
Initializes the MetaProver contract.
router
address
required
Address of the local Metalayer router contract
portal
address
required
Address of the Portal contract
provers
bytes32[]
required
Array of trusted prover addresses (as bytes32 for cross-VM compatibility)
minGasLimit
uint256
required
Minimum gas limit for cross-chain messages. Defaults to 200,000 if zero.
Errors:
  • MessengerContractCannotBeZeroAddress(): Router address is zero
  • ZeroPortal(): Portal address is zero
Location: contracts/prover/MetaProver.sol:58

State Variables

ROUTER

IMetalayerRouterExt public immutable ROUTER
Address of the local Metalayer router contract.

PROOF_TYPE

string public constant PROOF_TYPE = "Meta"
Constant indicating this contract uses Metalayer for proving.

MIN_GAS_LIMIT

uint256 public immutable MIN_GAS_LIMIT
Minimum gas limit for cross-chain message dispatch. Inherited from MessageBridgeProver. Defaults to 200,000.

ETH_QUOTE_VALUE

uint256 private immutable ETH_QUOTE_VALUE = 1e36
ETH message value used in fee calculation metadata. Set to very high value to avoid fee calculation failures in Metalayer’s quote dispatch function.

Core Functions

prove

function prove(
    address sender,
    uint64 domainID,
    bytes calldata encodedProofs,
    bytes calldata data
) external payable
Inherited from MessageBridgeProver. Initiates proving process by dispatching a message via Metalayer.
sender
address
required
Address that initiated the proving request (receives refund if overpaid)
domainID
uint64
required
Metalayer domain ID of the source chain (where the intent was created). NOT the chain ID.
encodedProofs
bytes
required
Encoded (intentHash, claimant) pairs. Format: [intentHash1][claimant1][intentHash2][claimant2]...
data
bytes
required
ABI-encoded UnpackedData struct containing:
  • sourceChainProver (bytes32): Address of prover on source chain
  • gasLimit (uint256): Gas limit for execution (min 200k)
Behavior:
  1. Calculates required fee via fetchFee
  2. Validates msg.value covers fee
  3. Dispatches message via Metalayer router
  4. Refunds excess payment to sender
Errors:
  • InsufficientFee(uint256 required): msg.value is less than required fee
  • DomainIdTooLarge(uint64 domainID): Domain ID exceeds uint32.max
Access Control: Only callable by PORTAL Location: Inherited from MessageBridgeProver.sol:112

handle

function handle(
    uint32 origin,
    bytes32 sender,
    bytes calldata message,
    ReadOperation[] calldata /* operations */,
    bytes[] calldata /* operationsData */
) external payable
Handles incoming Metalayer messages containing proof data. Called by the Metalayer Router on the source chain.
origin
uint32
required
Origin chain ID from the destination chain. Cannot be zero.
sender
bytes32
required
Address that dispatched the message on destination chain (as bytes32). Cannot be zero.
message
bytes
required
Encoded message with format: [chainId (8 bytes)][intentHash1][claimant1][intentHash2][claimant2]...
Behavior:
  1. Validates origin is not zero
  2. Validates sender is whitelisted
  3. Extracts chain ID from first 8 bytes of message
  4. Processes intent proofs using _processIntentProofs
Errors:
  • MessageOriginChainDomainIDCannotBeZero(): Origin is zero
  • MessageSenderCannotBeZeroAddress(): Sender is zero
  • UnauthorizedIncomingProof(bytes32 sender): Sender not whitelisted
Access Control: Only callable by ROUTER Location: contracts/prover/MetaProver.sol:77

fetchFee

function fetchFee(
    uint64 domainID,
    bytes calldata encodedProofs,
    bytes calldata data
) public view override returns (uint256)
Calculates the fee required for Metalayer message dispatch.
domainID
uint64
required
Metalayer domain ID of the source chain
encodedProofs
bytes
required
Encoded (intentHash, claimant) pairs
data
bytes
required
ABI-encoded UnpackedData struct
Returns: Fee amount in native tokens required for message dispatch Note: Uses custom hook metadata with actual gas limit to ensure accurate fee estimation. Fixes issue where 3-parameter quoteDispatch used hardcoded 100k gas limit. Location: contracts/prover/MetaProver.sol:158

getProofType

function getProofType() external pure override returns (string memory)
Returns: "Meta"

Internal Functions

_dispatchMessage

function _dispatchMessage(
    uint64 domainID,
    bytes calldata encodedProofs,
    bytes calldata data,
    uint256 fee
) internal override
Implementation of message dispatch for Metalayer. Called by base prove() function. Behavior:
  1. Unpacks data into structured format (enforces min gas limit)
  2. Formats Metalayer message parameters
  3. Calls ROUTER.dispatch with:
    • Empty ReadOperation array
    • FinalityState.INSTANT
    • Configured gas limit
Location: contracts/prover/MetaProver.sol:118

_fetchFee

function _fetchFee(
    uint64 domainID,
    bytes calldata encodedProofs,
    UnpackedData memory unpacked
) internal view returns (uint256)
Internal function to calculate fee with pre-decoded data. Behavior:
  1. Formats Metalayer message
  2. Creates custom hook metadata with actual gas limit (min 200k)
  3. Queries router for fee estimate via quoteDispatch
Hook Metadata:
StandardHookMetadata.formatMetadata(
    ETH_QUOTE_VALUE, // 1e36
    unpacked.gasLimit, // Actual gas limit (min 200k)
    msg.sender,        // Refund address
    bytes("")          // Custom metadata
)
Location: contracts/prover/MetaProver.sol:175

_formatMetalayerMessage

function _formatMetalayerMessage(
    uint64 domainID,
    bytes calldata encodedProofs,
    bytes32 sourceChainProver
) internal pure returns (
    uint32 domain,
    bytes32 recipient,
    bytes memory message
)
Formats data for Metalayer message dispatch. Returns:
  • domain (uint32): Metalayer domain ID
  • recipient (bytes32): Source chain prover address
  • message (bytes): Encoded proofs
Location: contracts/prover/MetaProver.sol:224

_unpackData

function _unpackData(
    bytes calldata data
) internal view returns (UnpackedData memory unpacked)
Decodes raw message data and enforces minimum gas limit. Behavior:
  • Decodes ABI-encoded UnpackedData
  • If gasLimit < MIN_GAS_LIMIT, sets to MIN_GAS_LIMIT
Location: contracts/prover/MetaProver.sol:99

Data Structures

UnpackedData

struct UnpackedData {
    bytes32 sourceChainProver; // Address of prover on source chain
    uint256 gasLimit;          // Gas limit for execution
}
Contains fields decoded from the data parameter. Gas limit is enforced to be at least MIN_GAS_LIMIT (200k).

Usage Example

// On destination chain, prepare proof data
bytes memory data = abi.encode(
    UnpackedData({
        sourceChainProver: bytes32(uint256(uint160(sourceProverAddress))),
        gasLimit: 250000 // Custom gas limit (min 200k)
    })
);

// Calculate fee
uint256 fee = metaProver.fetchFee(
    metalayerSourceDomainId,
    encodedProofs,
    data
);

// Send proof via portal
portal.prove{value: fee}(
    address(metaProver),
    metalayerSourceDomainId,
    encodedProofs,
    data
);

Finality State

MetaProver uses FinalityState.INSTANT for all message dispatches, providing the fastest possible message delivery.

Build docs developers (and LLMs) love