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

# Light Clients

> Checkpoint contracts that authenticate cross-chain state roots

## Shared checkpoint behavior

The light clients on Metal expose the state-root interface used by
`ForeignInbox`:

```solidity theme={null}
interface ICheckpointStateRoot {
    function stateRoot(bytes32 blockHash) external view returns (bytes32);
}
```

They also expose `checkpoint(blockHash)` and `isAccepted(blockHash)`.
`checkpoint` and `stateRoot` revert for an unknown checkpoint, while
`isAccepted` returns `false`.

## Configured routes

Obtain the light client address, deployed ABI and runtime bytecode hash, source
chain ID, and authenticated trust configuration from the route provider. Compare
them with the inbox's `lightClient()` and source chain ID. `MetalInbox` exposes
`metalChainId()`, while `ForeignInbox` exposes `foreignChainId()`,
`foreignOutbox()` and `foreignOutboxCodeHash()`. The latter pins the approved
runtime bytecode hash of the direct, immutable source `Outbox`. Compare it to
the authenticated deployment artifact's runtime bytecode hash and the source
contract's runtime bytecode hash at the checkpoint used for delivery. A new
`Outbox` version requires a new inbox and an updated route configuration.

Metal, Tempo, and Arc clients pin their verification keys for their lifetime.
Replacing a client also requires a new inbox. Its consumed-nonce state starts
empty, so application records must prevent previously completed instructions
from executing again through the replacement route.

`ForeignInbox` verifies the pinned code hash from the same account proof that
establishes the `Outbox`'s storage root. `CodeHashMismatch` means that the
proven runtime bytecode hash differs from the configured route. Correct the
route or proof selection before retrying.

## Metal light client

```solidity theme={null}
function update(
    bytes calldata headerRlp,
    uint64 epoch,
    uint64 viewNumber,
    uint64 parentView,
    bytes calldata signersBitmap,
    bytes calldata signature
) external;
```

The Metal verifier accepts only epoch `0`, and each update must advance both
block height and view. `signature` is the 256-byte EIP-2537 G2 encoding.

Read `latestBlockHash()` and then `checkpoint(blockHash)`. The checkpoint
returns `(uint64 blockNumber, uint64 viewNumber, uint64 timestampMs,
bytes32 stateRoot, bytes32 receiptsRoot, bytes32 interopMessageRoot)`.
`isAccepted(bytes32)` returns a boolean. The client also exposes
`metalChainId()`, `metalGenesisHash()`, `VERIFIER_VERSION()`,
`participantCount()`, `quorum()`, `latestBlockNumber()`, `latestView()`, and
`validatorKey(uint256)` for checking the authenticated deployment configuration.
The key getter returns a 128-byte EIP-2537 G1 key in bitmap order.

Supply `headerRlp`, `epoch`, `view`, `parentView`, `signersBitmap`, and
`signatureEipUncompressed` from the
[finality-certificate response](https://docs.metalntwx.com/reference/interop/finality-certificates.md) to
`update` in that order. Verify `keccak256(headerRlp) == blockHash` before
submission. Checkpoint acceptance is established by a successful update and
`isAccepted(blockHash)`, followed by destination-chain finality.

## Ethereum light client

The [protocol contract](https://docs.metalntwx.com/reference/contract-addresses.md) at
`0x00000000000000000000000000000000000000FC` exposes read methods only:

```solidity theme={null}
struct Checkpoint {
    uint64 blockNumber;
    uint64 slot;
    uint64 timestamp;
    bytes32 stateRoot;
    bytes32 receiptsRoot;
}

function checkpoint(bytes32 blockHash) external view returns (Checkpoint memory);
function stateRoot(bytes32 blockHash) external view returns (bytes32);
function isAccepted(bytes32 blockHash) external view returns (bool);
function storeHash() external view returns (bytes32);
function latestBlockHash() external view returns (bytes32);
function latestBlockNumber() external view returns (uint64);
function latestUpdateTimestamp() external view returns (uint64);
```

`slot` is the finalized beacon slot. `timestamp` is the Ethereum execution
block's timestamp in seconds, and `latestUpdateTimestamp` is the Metal block
timestamp of the latest accepted store update. An update can advance the store
without recording a newer execution checkpoint.

Metal block execution verifies the update witness carried in the header and
writes the resulting store and checkpoints before transactions execute. Trust
roots, fork schedule, and participation threshold come from Metal's network
configuration.

## Tempo light client

```solidity theme={null}
function update(
    bytes calldata headerRlp,
    uint64 epoch,
    uint64 viewNumber,
    uint64 parentView,
    bytes calldata voteSignature
) external;
```

Tempo updates must advance block height and the `(epoch, view)` pair. The
128-byte `voteSignature` is the recovered threshold signature in EIP-2537 G1
encoding.

The route provider must supply a public finalized-header and certificate feed
and its conversion instructions. `headerRlp` is the exact finalized header,
`epoch`, `viewNumber`, and `parentView` are its consensus fields, and
`voteSignature` is the recovered threshold vote signature in EIP-2537 G1
encoding. The pinned group key identifies the source network. Resharing that
preserves the key is supported, while replacing the key requires a new client.

`latestBlockHash()` selects the most recent checkpoint. `checkpoint(bytes32)`
returns `(uint64 blockNumber, uint64 viewNumber, uint64 timestampMs,
bytes32 stateRoot, bytes32 receiptsRoot)`.

## Arc light client

```solidity theme={null}
struct Vote {
    uint32 validatorIndex;
    bytes signature;
}

function update(bytes calldata headerRlp, uint32 round, Vote[] calldata votes)
    external;
```

The route provider must supply the finalized header and its precommit votes with
a documented public conversion to this ABI. Each vote contains a validator index
and a 64-byte Ed25519 signature. Sort votes by strictly increasing validator
index and include more than two-thirds of the pinned voting power. Every vote
must authenticate the same block and round. The block number must advance. The
pinned validator keys identify the source network, and validator-set changes
require a new client.

`latestBlockHash()` selects the most recent checkpoint. `checkpoint(bytes32)`
returns `(uint64 blockNumber, uint64 timestampMs, bytes32 stateRoot,
bytes32 receiptsRoot)`. Arc header timestamps are converted from seconds to
milliseconds.

Follow [receiving messages](https://docs.metalntwx.com/build/interop/receive-messages-on-metal.md) to bind account
and storage proofs to these checkpoints, or
[sending messages](https://docs.metalntwx.com/build/interop/send-messages-from-metal.md) for the Metal message-tree
proof path.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.