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

# How the LayerZero prover works

> Cross-chain verification using LayerZero's omnichain messaging

The LayerZero Prover enables cross-chain intent verification using LayerZero's omnichain messaging infrastructure. It receives messages via `ILayerZeroReceiver` and extends `MessageBridgeProver` for common proving functionality.

## Architecture

```
Destination Chain                Source Chain
━━━━━━━━━━━━━━━━                ━━━━━━━━━━━━━━
Portal                           Portal
    ↓                                ↑
LayerZeroProver                  LayerZeroProver
    ↓                                ↑
LayerZero Endpoint ──────────→ LayerZero Endpoint
```

## Configuration

```solidity theme={null}
constructor(
    address endpoint,         // LayerZero V2 endpoint on this chain
    address delegate,         // Address authorized to configure LayerZero
    address portal,           // Portal contract address
    bytes32[] memory provers, // Trusted prover addresses on other chains
    uint256 minGasLimit       // Minimum gas limit (defaults to 200k if zero)
)
```

**Key Points:**

* `endpoint`: Chain-specific LayerZero V2 endpoint address
* `delegate`: Set via `ILayerZeroEndpointV2(endpoint).setDelegate(delegate)` - can configure paths and settings
* `provers`: 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:

```solidity theme={null}
portal.prove{value: fee}(
    address(prover),
    sourceChainDomainID,
    intentHashes,
    data
);
```

**Data Parameter:**

```solidity theme={null}
abi.encode(
    LayerZeroProver.UnpackedData({
        sourceChainProver: bytes32(uint256(uint160(sourceProverAddress))),
        options: bytes(""),      // Empty for default, or custom LayerZero options
        gasLimit: 250000         // Minimum MIN_GAS_LIMIT enforced
    })
)
```

### Receiving Proofs (Source Chain)

LayerZero endpoint calls `lzReceive()` with message containing:

* 8 bytes: destination chain ID
* 64 bytes per intent: `[intentHash (32 bytes)][claimant (32 bytes)]`

Only whitelisted senders accepted via `isWhitelisted(origin.sender)`.

## Fee Calculation

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

Returns native token amount required for LayerZero message dispatch. Always call before proving to avoid reverts.

## Domain IDs

**Critical:** LayerZero uses Endpoint IDs (eids), not chain IDs.

```solidity theme={null}
params.dstEid = uint32(domainID);
```

The `sourceChainDomainID` parameter must be LayerZero's endpoint ID. Consult [LayerZero V2 Documentation](https://docs.layerzero.network/v2/developers/evm/technical-reference/deployed-contracts) for mappings.

**Example:**

* Ethereum: Chain ID 1 → Endpoint ID 30101
* Arbitrum: Chain ID 42161 → Endpoint ID 30110

## Message Options

### Default (Empty Options)

```solidity theme={null}
options: ""
```

Creates basic options with gas limit:

```solidity theme={null}
abi.encodePacked(uint16(3), gasLimit)
```

### Custom Options

Pass encoded LayerZero options for advanced configurations:

```solidity theme={null}
options: customEncodedOptions
```

See LayerZero documentation for option encoding.

## Security

### Whitelisting

Only provers in the whitelist can send messages:

```solidity theme={null}
function isWhitelisted(bytes32 sender) internal view returns (bool)
```

### 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:

```solidity theme={null}
if (unpacked.gasLimit < MIN_GAS_LIMIT) {
    unpacked.gasLimit = MIN_GAS_LIMIT;
}
```

## Integration Example

```solidity theme={null}
// Deploy prover
bytes32[] memory trustedProvers = new bytes32[](1);
trustedProvers[0] = bytes32(uint256(uint160(ethereumProverAddress)));

LayerZeroProver prover = new LayerZeroProver(
    layerZeroEndpoint,  // Chain-specific endpoint
    delegateAddress,    // Governance/admin address
    portalAddress,
    trustedProvers,
    250_000            // 250k gas minimum
);

// Fulfill and prove
bytes memory proverData = abi.encode(
    LayerZeroProver.UnpackedData({
        sourceChainProver: bytes32(uint256(uint160(ethereumProver))),
        options: "",
        gasLimit: 250_000
    })
);

uint256 fee = prover.fetchFee(30101, encodedProofs, proverData);

portal.fulfillAndProve{value: route.nativeAmount + fee}(
    intentHash,
    route,
    rewardHash,
    claimant,
    address(prover),
    30101,  // Ethereum endpoint ID
    proverData
);
```

## 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 constructor
* `DelegateCannotBeZeroAddress()`: Invalid delegate in constructor
* `SenderCannotBeZeroAddress()`: Zero sender in lzReceive
* `DomainIdTooLarge(uint64)`: Domain ID exceeds uint32.max
* `InvalidExecutor(address)`: Unexpected executor address
* `NonPortalCaller(address)`: Unauthorized prove() caller
* `NotWhitelisted(bytes32)`: Sender not in whitelist

## Constant

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

Identifies this prover's mechanism type.
