> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/eco/eco-routes/llms.txt
> Use this file to discover all available pages before exploring further.

# MetaProver

> Prover implementation using Caldera Metalayer's cross-chain messaging system

## 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"`

<Note>
  In MetaProver documentation, "source" refers to the chain where the intent was **created**, and "destination" refers to the chain where the intent is **fulfilled**.
</Note>

<Warning>
  **Domain ID vs Chain ID:** Metalayer uses domain IDs specific to their routing system. Consult [Metalayer's documentation](https://docs.caldera.xyz/metalayer) for the correct domain ID mapping.
</Warning>

## Constructor

```solidity theme={null}
constructor(
    address router,
    address portal,
    bytes32[] memory provers,
    uint256 minGasLimit
)
```

Initializes the MetaProver contract.

<ParamField path="router" type="address" required>
  Address of the local Metalayer router contract
</ParamField>

<ParamField path="portal" type="address" required>
  Address of the Portal contract
</ParamField>

<ParamField path="provers" type="bytes32[]" required>
  Array of trusted prover addresses (as bytes32 for cross-VM compatibility)
</ParamField>

<ParamField path="minGasLimit" type="uint256" required>
  Minimum gas limit for cross-chain messages. Defaults to 200,000 if zero.
</ParamField>

**Errors:**

* `MessengerContractCannotBeZeroAddress()`: Router address is zero
* `ZeroPortal()`: Portal address is zero

**Location:** `contracts/prover/MetaProver.sol:58`

## State Variables

### ROUTER

```solidity theme={null}
IMetalayerRouterExt public immutable ROUTER
```

Address of the local Metalayer router contract.

### PROOF\_TYPE

```solidity theme={null}
string public constant PROOF_TYPE = "Meta"
```

Constant indicating this contract uses Metalayer for proving.

### MIN\_GAS\_LIMIT

```solidity theme={null}
uint256 public immutable MIN_GAS_LIMIT
```

Minimum gas limit for cross-chain message dispatch. Inherited from `MessageBridgeProver`. Defaults to 200,000.

### ETH\_QUOTE\_VALUE

```solidity theme={null}
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

```solidity theme={null}
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.

<ParamField path="sender" type="address" required>
  Address that initiated the proving request (receives refund if overpaid)
</ParamField>

<ParamField path="domainID" type="uint64" required>
  Metalayer domain ID of the source chain (where the intent was created). **NOT the chain ID.**
</ParamField>

<ParamField path="encodedProofs" type="bytes" required>
  Encoded (intentHash, claimant) pairs. Format: `[intentHash1][claimant1][intentHash2][claimant2]...`
</ParamField>

<ParamField path="data" type="bytes" required>
  ABI-encoded `UnpackedData` struct containing:

  * `sourceChainProver` (bytes32): Address of prover on source chain
  * `gasLimit` (uint256): Gas limit for execution (min 200k)
</ParamField>

**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

```solidity theme={null}
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.

<ParamField path="origin" type="uint32" required>
  Origin chain ID from the destination chain. Cannot be zero.
</ParamField>

<ParamField path="sender" type="bytes32" required>
  Address that dispatched the message on destination chain (as bytes32). Cannot be zero.
</ParamField>

<ParamField path="message" type="bytes" required>
  Encoded message with format: `[chainId (8 bytes)][intentHash1][claimant1][intentHash2][claimant2]...`
</ParamField>

**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

```solidity theme={null}
function fetchFee(
    uint64 domainID,
    bytes calldata encodedProofs,
    bytes calldata data
) public view override returns (uint256)
```

Calculates the fee required for Metalayer message dispatch.

<ParamField path="domainID" type="uint64" required>
  Metalayer domain ID of the source chain
</ParamField>

<ParamField path="encodedProofs" type="bytes" required>
  Encoded (intentHash, claimant) pairs
</ParamField>

<ParamField path="data" type="bytes" required>
  ABI-encoded UnpackedData struct
</ParamField>

**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

```solidity theme={null}
function getProofType() external pure override returns (string memory)
```

**Returns:** `"Meta"`

## Internal Functions

### \_dispatchMessage

```solidity theme={null}
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

```solidity theme={null}
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:**

```solidity theme={null}
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

```solidity theme={null}
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

```solidity theme={null}
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

```solidity theme={null}
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

```solidity theme={null}
// 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.
