Why Use Cross-Chain Reads?

Many decentralized applications rely on data from multiple chains. Some key use cases include:

  • Aggregating liquidity across chains for better DeFi execution.
  • Fetching token ownership or balances across chains before execution.
  • Governance protocols checking votes on multiple chains before passing a decision.

How Cross-Chain Reads Work

  1. A contract on one chain requests data from multiple chains.
  2. The CCIP Read ISM validates the read request and forwards it to Hyperlane’s message relayers.
  3. Hyperlane retrieves data from off-chain RPC nodes, aggregates it, and relays it back.
  4. The data is returned to the contract that initiated the read.

Protocol Interface

interface IMetaLayerRead {
    function fetchCrossChainData(
        uint32[] calldata sourceChains,
        address user,
        bytes calldata queryData
    ) external view returns (bytes[] memory);
}

Explanation of ReadOperation Struct

Each cross-chain read operation is encapsulated in a ReadOperation struct:

struct ReadOperation {
    uint32 sourceChain;
    address contractAddress;
    bytes callData;
}
  • sourceChain: The ID of the chain where data is being queried.
  • contractAddress: Address of the contract being queried.
  • callData: Encoded function call to retrieve data.

Example: Querying Data from 4 Chains

This example demonstrates how a contract queries balances from multiple chains.

Cross-Chain Data Reader

contract MultiChainReader {
    IMetaLayerRead public metalayer;

    constructor(address _metalayer) {
        metalayer = IMetaLayerRead(_metalayer);
    }

    function getMultiChainData(uint32[] calldata chains, address user, bytes calldata queryData) 
        external view returns (bytes[] memory) {
        return metalayer.fetchCrossChainData(chains, user, queryData);
    }
}