Cross Chain Message Examples
Using Foundry’s cast for Cross-Chain Messages
cast for Cross-Chain MessagesThis guide explains how to send cross-chain messages from a blockchain to the Multi-Ledger Rollup, and how to verify the message on the rollup.
Cross chain messages can be triggered directly by a transaction or indirectly via a smart contract. This initial guide shows a cross chain message being triggered by a transaction. But it should be easily inferable for how this demo can be expanded on for a cross chain smart contract call.
Assumptions:
You are familiar with the rollup environment and have valid RPC endpoints for both L1 and the Multi-Ledger Rollup networks.
Additionally this guide assumes you are aware of the cross chain messaging smart contract addresses as described in the Smart Contract Page.
Firewall Restrictions
For easier initial testing, the public testnet version of the firewall is configured to let all messages through. At a future point to be determined, the firewall will be locked down to only allow a user to send messages to a Multi-Ledger Rolllup smart contract that he is authorised to interact with.
1. Install Foundry and cast
castcast is part of Foundry , an Ethereum development toolkit maintained by Paradigm. It provides CLI utilities for interacting with smart contracts via JSON-RPC.
Install Foundry
curl -L https://foundry.paradigm.xyz | bash
foundryup
Verify Installation
cast --version
You should see output of version 0.2.0 or higher.
2. Environment Setup
Before running the commands below, make sure the following environment variables are exported. These are used for the L1 → rollup cross-chain message operation.
# RPC Endpoints
export L1_RPC_URL=<your L1 RPC endpoint>
export ROLLUP_RPC_URL=<your ROLLUP RPC endpoint>
# Wallet configuration
export PRIVATE_KEY=<your private key> # wallet performing the cross-chain message
export WALLET=<wallet address derived from PRIVATE_KEY> # e.g., cast wallet address --private-key $PRIVATE_KEY
# Cross-chain contract configuration
export L1_MESSENGER_ADDRESS=<L1 messenge address> # for this specific blockchain
export ROLLUP_STORAGE_ADDRESS="0x69813858813d3d3960a2145b43575b08b3eccca9" # a demo smart contract
# Rollup configuration
export ROLLUP_CHAIN_ID=73073
export GAS_LIMIT=300000 # safe gas limit for message execution
# Message data
export TEST_KEY="exampleKey" # string key to store the provided value under in rollup contract
export TEST_VALUE="exampleValue" # string value to store in the rollup contract
3. Send Cross-Chain Message (Blockchain → Rollup)
Description
This step sends a cross-chain message from the blockchain to the rollup via the Cross-Chain Messenger contract on the blockchain.
The rollup nodes then pick up the message, and transfer it to the rollup.
Command
cast send $L1_MESSENGER_ADDRESS \
"sendMessage(address,bytes,uint32,uint256)" \
$ROLLUP_STORAGE_ADDRESS \
$(cast calldata "set(string,string)" "$TEST_KEY" "$TEST_VALUE") \
$GAS_LIMIT \
$ROLLUP_CHAIN_ID \
--rpc-url $L1_RPC_URL \
--private-key $PRIVATE_KEY
Verify Transaction on the Blockchain
Foundry will return you the transaction information. Make sure that status of the transaction is 1 (success).
4. Read Value from Rollup Storage
Description
After the L1 message is finalized and relayed, you can read the stored value from the Rollup's contract to verify message delivery.
Command
cast call $ROLLUP_STORAGE_ADDRESS \
"get(string,address)(string)" \
"$TEST_KEY" \
$WALLET \
--rpc-url $ROLLUP_RPC_URL
NOTE
Your message will only appear on the rollup after finalization - typically after 2 epochs on Sepolia (≈20 minutes) but around 3 minutes on Polygon & Besu.
5. Troubleshooting
| Issue | Likely Cause | Resolution |
|---|---|---|
| ❌ Message not visible on rollup | Finalization not complete | Wait for a minimum of 3 minutes and a maximum of 2 epochs (usually 20 minutes) for Sepolia |
| ❌ “Invalid address” error | Missing or incorrect contract address | Double-check ROLLUP_STORAGE_ADDRESS and L1_CROSS_DOMAIN_MESSENGER_ADDRESS |
❌ cast fails to execute | Environment variables not exported | Run export commands again and verify with `env |
Updated about 2 hours ago
