npm package: @metalayer/contracts
Description: The Metalayer is a fast, low-cost, and flexible interchain communication protocol. It supports both reads and writes.
Author: Constellation Labs
Latest version: 1.1.0-beta

# MetalayerRouter Contracts


## 📚 Overview

**MetalayerRouter** is a messaging layer built on top of Hyperlane. It is designed for EVM-compatible chains and offers enhanced functionality such as:

- 1-to-1 messaging between chains
- Predefined finality configurations (e.g., rollup-based, RPC soft confirmations).
- n-to-1 cross-chain reads via offchain aggregation and CCIP-compatible delivery.
- Package encoding for richer message semantics.
- Fallback compatibility with Hyperlane interfaces.
- Preset ISMs (Interchain Security Modules) and fee hooks controlled at the protocol level.

(Metalayer)[https://caldera.xyz/metalayer] makes it easy for developers to build sophisticated cross-chain applications without dealing with the complexities of cross-chain messaging infrastructure. The MetalayerRouter is the messaging piece of the overall metalayer product. 
---

## Message Flow

```mermaid
sequenceDiagram
    participant SenderApp as Sender Smart Contract
    participant MetalayerRouter
    participant HyperlaneMailbox
    participant OffchainRelayer as Offchain Relayer
    participant DestinationHyperlaneMailbox as Destination HyperlaneMailbox
    participant ISM
    participant DestinationRouter as Destination MetalayerRouter
    participant RecipientApp as Recipient App

    SenderApp->>MetalayerRouter: sendMessage(destDomain, recipient, metadata, message)
    MetalayerRouter->>MetalayerRouter: encodeMessageWithPackage()
    MetalayerRouter->>HyperlaneMailbox: dispatch()
    HyperlaneMailbox-->OffchainRelayer: Dispatch event emitted
    
    OffchainRelayer->>DestinationHyperlaneMailbox: handle()
    DestinationHyperlaneMailbox->>ISM: verify(metadata, message)
    ISM-->>DestinationHyperlaneMailbox: verified
    DestinationHyperlaneMailbox->>DestinationRouter: handle()

    DestinationRouter->>RecipientApp: handle(metadata, message)
```

---

## 📁 File Overview

| File | Description |
|------|-------------|
| `MetalayerRouter.sol` | Main entry point for sending/receiving messages; wraps Hyperlane mailbox. |
| `MetalayerIsm.sol` | CCIP Read ISM used to process n-to-1 offchain reads |
| `interfaces/IMetalayerRouter.sol` | Interface defining the external API for the MetalayerRouter. |
| `interfaces/IMetalayerRecipient.sol` | Interface for contracts receiving messages via Metalayer. |
| `lib/MetalayerMessage.sol` | Defines message encoding and decoding logic. |

---

## ✨ Core Concepts

### Aggregation ISM (MetalayerIsm)

The Metalayer ISM is an **Aggregation ISM** that plays a key role in enabling **cross-chain reads**.

- Offchain relayers collect and aggregate state from one or more source chains.
- The result is encoded and delivered on the destination chain using a **CCIP-compatible ISM**.
- This ISM validates the aggregated result before forwarding the payload to the recipient app.

The ISM used to verify a message is defined on the **destination chain**. This means that:

> 🧠 **The destination MetalayerRouter's ISM is what verifies the message, not the sender's.**

This allows the destination chain to independently enforce:
- Required finality rules
- Aggregation strategies (eg CCIPReads + Multisig Validator Signing)


---

### Finality Configurations
Supported finality options include:
- **Rollup-based finality** (e.g., L2 sequencer confirmations).
- **Soft confirmations** (e.g., N blocks deep RPC-based confirmations).
- **Future finality rules** defined via ISM.

These rules are enforced at message receipt via the destination ISM.

---

### Package Encoding
Metalayer encodes messages as:
- **Metadata**: Finality proofs, aggregated read info, etc.
- **Payload**: Application-level content.

Encoding/decoding logic is defined in `MetalayerMessage.sol`.

---

### n-to-1 Cross Chain Reads

Applications can perform **reads across multiple source chains**, aggregate the result offchain, and **deliver the final answer to a single destination chain**.

- Relayers act as data aggregators.
- The result is posted onchain using the Aggregation ISM and verified via the CCIP-compatible mechanism.

---

### Fallback Compatibility

Metalayer contracts conform to the same external interface as Hyperlane routers. This allows:
- Seamless integration with Hyperlane-native apps.
- Protocol-level switching between Hyperlane and Metalayer deployments without breaking changes.

---

### Preset ISMs and Fee Hooks

- Each domain may use protocol-defined **default ISMs** and **fee hooks**.
- These are configured during deployment to standardize behavior across apps.
- This minimizes misconfiguration risk and improves consistency.

---

## ✉️ Messaging Flow

### Write Flow

```solidity
    function dispatch(
        uint32 _destinationDomain,
        address _recipientAddress,
        ReadOperation[] memory _reads, // can be empty
        bytes memory _writeCallData,
        FinalityState _finalityState,
        uint256 _gasLimit
    ) external payable;
```

1. App calls `dispatch` on the **source MetalayerRouter**. The reads can be empty.
2. Message and metadata are encoded.
3. Hyperlane's `Mailbox` handles cross-chain dispatch.
4. A offchain Hyperlane relayer aggregates signatures from the Offchain validator and delivers the message the the destination chain. 
5. The destination Hyperlane `Mailbox` contract recieves the message, and forwards it to the MetalayerRouter
6. The `Mailbox` verifyies the message using the the **ISM set on the destination MetalayerRouter**.
7. The `MetalayerRouter` recieves the message and calls the recipient's `handle` method.

---

### Read Flow (Cross-chain Aggregation)

The read flow is identical to the write, however, the read operations are populated on `dispatch`. 

When the offchain relayer processes the message, it inspects the ism configration on the
destination chain via an rpc call to `modulesAndThreshold`.

```solidity
    function modulesAndThreshold(bytes calldata _message) public view override returns (address[] memory, uint8) {
        [ ... ]
        FinalityState finalityState = Message.body(_message).finalityState();

        if (Message.body(_message).readCount() == 0) {
            return finalityState == FinalityState.FINALIZED ? (onlyFinalizedMultisigIsm, 1) : (onlyMultisigIsm, 1);
        } else {
            return finalityState == FinalityState.FINALIZED ? (bothIsmsFinalized, 2) : (bothIsms, 2);
        }
    }
```

This requires a 2/2 agreement between the multisig ism as well as a CCIP Read ISM. This
CCIP Read ISM is implemented in `MetalayerIsm.sol`. When this ISM verifies the message using the ISM metadata from the relayer, it verifies that the message payload with the
reads is properly signed, and persists the read payloads in the contract.

Finally, the handle function on the `MetalayerRouter` is called by the `HyperlaneMailbox` to read, unpack, and deliver the message that is saved on the ISM. 

```solidity
 function handle(
        uint32 _origin,
        bytes32 _sender,
        bytes calldata _message // This is the Metalayer message.
    ) external payable {
        require(_sender.bytes32ToAddress() == routerAddresses[_origin], "only router can send hyperlane msg");
        require(msg.sender == address(mailbox), "only mailbox can call");

        uint256 readCount = _message.readCount();
        bytes[] memory results = new bytes[](readCount);

        if (readCount > 0) {
            bytes memory packedData = metalayerIsm.responseMap(keccak256(_message));
            // packedData has structs containing {uint32 length, bytes data}
            uint256 offset = 0;

            for (uint256 i = 0; i < readCount; i++) {
                [ ... unpack reads ]
            }
        }

        // Deliver message to the recipient with reads. 
        IMetalayerRecipient(_message.recipientAddress()).handle{value: msg.value}(
            _message.origin(), _message.senderAddress(), _message.writeCallData(), _message.reads(), results
        );
    }
```
---

## 🚀 Deployment Instructions

Metalayer uses **Foundry** for deployment. You will need:

### Prerequisites
- Foundry installed (`forge`)
- RPC URLs and private key in `.env`
- ISM and fee hook config per domain

### Steps

1. Clone the repo and install dependencies.
2. Set up your `.env` file with deployer key and RPC endpoints.
3. Run the deployment script:

```bash
forge script script/MetalayerDeploy.s.sol --rpc-url <RPC> --broadcast --verify -vvvv
```

> **Note:** Update `DeployMetalayer.s.sol` to configure ISMs, fee hooks, and router defaults.

---

## 🧠 Security Notes

- Metalayer leverages Hyperlane's Mailbox for low-level message passing.
- Message verification is performed via the **destination chain's ISM**, allowing strict control.
- Read aggregation is trust-minimized via CCIP-compatible ISM logic.
- Protocol-enforced hooks/ISMs reduce configuration errors across deployments.

---

## 📎 References

- [Hyperlane Protocol Docs](https://docs.hyperlane.xyz)
- [Hyperlane ISMs Overview](https://docs.hyperlane.xyz/docs/protocol/ISM/modular-security)
- Internal examples: `sample/BlockHeightProvider.sol`, `BlockHeightReader.sol`