Skip to main content

Cross-chain messaging overview

The Arbitrum protocol and related tooling make it easy for developers to build cross-chain applications; i.e., applications that involve sending messages from Ethereum to an Arbitrum chain, and/or from an Arbitrum chain to Ethereum.

Arbitrum SDK

The @arbitrum/sdk is a TypeScript library for bridging tokens and passing messages between parent and child Arbitrum chains. It provides a typed interface to the underlying bridge and messaging smart contracts.

Links: GitHub | npm | Tutorials

Install: npm install @arbitrum/sdk

Ethereum-to-Arbitrum messaging

Creating an arbitrary parent-to-child chain contract call occurs via the Inbox's createRetryableTicket method. Upon publishing the parent chain transaction, the child chain side will typically be included within minutes. Commonly, the child chain execution will automatically succeed, but if it reverts, it can be re-executed via a call to the redeem method of the ArbRetryableTx precompile.

Depositing from a smart contract (address aliasing)

When a contract (rather than an EOA) sends a parent-to-child chain message, the sender's address is aliased on the child chain by adding 0x1111000000000000000000000000000000001111. This prevents cross-chain address spoofing. You can compute the aliased address with the Arbitrum SDK:

import { Address } from '@arbitrum/sdk';

// When depositing from a contract, the sender's address is aliased on the child chain
const contractAddress = new Address(depositContract.address);
const aliasedAddress = contractAddress.applyAlias().value;

For a complete working example, see the contract-deposit tutorial.

Arbitrum-to-Ethereum messaging

Similarly, child chain contracts can send arbitrary messages for execution on the parent chain. These are initiated via calls to the ArbSys precompile contract's sendTxToL1 method. Upon confirmation (about one week later), you can execute them by retrieving the relevant data via a call to the NodeInterface contract's constructOutboxProof method, and then calling the Outbox's executeTransaction method.

Redeeming failed retryable tickets

When a retryable ticket's initial auto-redeem fails on the child chain, you can manually redeem it using the Arbitrum SDK. This is useful for recovering from transactions where the child chain execution reverted due to insufficient gas or other issues.

import { ParentTransactionReceipt, ParentToChildMessageStatus } from '@arbitrum/sdk';

// Wrap the parent chain transaction receipt
const parentReceipt = new ParentTransactionReceipt(
await parentProvider.getTransactionReceipt(parentTxHash),
);

// Get the parent-to-child messages
const messages = await parentReceipt.getParentToChildMessages(childSigner);
const message = messages[0];

// Check the status
const result = await message.waitForStatus();
if (result.status === ParentToChildMessageStatus.REDEEMED) {
console.log('Already redeemed');
} else {
// Manually redeem the failed retryable ticket
const redeemTx = await message.redeem();
const redeemReceipt = await redeemTx.waitForRedeem();
console.log('Redeemed:', redeemReceipt.transactionHash);
}

For a complete example, see the redeem-pending-retryable tutorial.