OpenZeppelin ContractsPrevious Versionsv4API Reference

Crosschain

Smart contract crosschain utilities and implementations

Outdated Version

You're viewing an older version (v4.x) The latest documentation is available for the current version. Click here to visit latest version.

This directory provides building blocks to improve cross-chain awareness of smart contracts.

  • CrossChainEnabled is an abstraction that contains accessors and modifiers to control the execution flow when receiving cross-chain messages.

CrossChainEnabled specializations

The following specializations of CrossChainEnabled provide implementations of the CrossChainEnabled abstraction for specific bridges. This can be used to complex cross-chain aware components such as AccessControlCrossChain.

CrossChainEnabledAMB

CrossChainEnabledArbitrumL1

CrossChainEnabledArbitrumL2

CrossChainEnabledOptimism

CrossChainEnabledPolygonChild

Libraries for cross-chain

In addition to the CrossChainEnabled abstraction, cross-chain awareness is also available through libraries. These libraries can be used to build complex designs such as contracts with the ability to interact with multiple bridges.

LibAMB

LibArbitrumL1

LibArbitrumL2

LibOptimism

import "@openzeppelin/contracts/crosschain/CrossChainEnabled.sol";

Provides information for building cross-chain aware contracts. This abstract contract provides accessors and modifiers to control the execution flow when receiving cross-chain messages.

Actual implementations of cross-chain aware contracts, which are based on this abstraction, will have to inherit from a bridge-specific specialization. Such specializations are provided under crosschain/<chain>/CrossChainEnabled<chain>.sol.

Available since v4.6.

onlyCrossChain()

internal

#

Throws if the current function call is not the result of a cross-chain execution.

onlyCrossChainSender(address expected)

internal

#

Throws if the current function call is not the result of a cross-chain execution initiated by account.

_isCrossChain() → bool

internal

#

Returns whether the current function call is the result of a cross-chain message.

_crossChainSender() → address

internal

#

Returns the address of the sender of the cross-chain message that triggered the current function call.

Should revert with NotCrossChainCall if the current function call is not the result of a cross-chain message.

import "@openzeppelin/contracts/crosschain/amb/CrossChainEnabledAMB.sol";

AMB specialization or the CrossChainEnabled abstraction.

As of february 2020, AMB bridges are available between the following chains:

Available since v4.6.

constructor(address bridge)

public

#

_isCrossChain() → bool

internal

#

_crossChainSender() → address

internal

#
import "@openzeppelin/contracts/crosschain/amb/LibAMB.sol";

Primitives for cross-chain aware contracts using the AMB family of bridges.

isCrossChain(address bridge) → bool

internal

#

Returns whether the current function call is the result of a cross-chain message relayed by bridge.

crossChainSender(address bridge) → address

internal

#

Returns the address of the sender that triggered the current cross-chain message through bridge.

NOTE: LibAMB.isCrossChain should be checked before trying to recover the sender, as it will revert with NotCrossChainCall if the current function call is not the result of a cross-chain message.

import "@openzeppelin/contracts/crosschain/arbitrum/CrossChainEnabledArbitrumL1.sol";

Arbitrum specialization or the CrossChainEnabled abstraction the L1 side (mainnet).

This version should only be deployed on L1 to process cross-chain messages originating from L2. For the other side, use CrossChainEnabledArbitrumL2.

The bridge contract is provided and maintained by the arbitrum team. You can find the address of this contract on the rinkeby testnet in Arbitrum's developer documentation.

Available since v4.6.

constructor(address bridge)

internal

#

_isCrossChain() → bool

internal

#

_crossChainSender() → address

internal

#
import "@openzeppelin/contracts/crosschain/arbitrum/CrossChainEnabledArbitrumL2.sol";

Arbitrum specialization or the CrossChainEnabled abstraction the L2 side (arbitrum).

This version should only be deployed on L2 to process cross-chain messages originating from L1. For the other side, use CrossChainEnabledArbitrumL1.

Arbitrum L2 includes the ArbSys contract at a fixed address. Therefore, this specialization of CrossChainEnabled does not include a constructor.

Available since v4.6.

There is currently a bug in Arbitrum that causes this contract to fail to detect cross-chain calls when deployed behind a proxy. This will be fixed when the network is upgraded to Arbitrum Nitro, currently scheduled for August 31st 2022.

_isCrossChain() → bool

internal

#

_crossChainSender() → address

internal

#
import "@openzeppelin/contracts/crosschain/arbitrum/LibArbitrumL1.sol";

Primitives for cross-chain aware contracts for Arbitrum.

This version should only be used on L1 to process cross-chain messages originating from L2. For the other side, use LibArbitrumL2.

isCrossChain(address bridge) → bool

internal

#

Returns whether the current function call is the result of a cross-chain message relayed by the bridge.

crossChainSender(address bridge) → address

internal

#

Returns the address of the sender that triggered the current cross-chain message through the bridge.

NOTE: LibAMB.isCrossChain should be checked before trying to recover the sender, as it will revert with NotCrossChainCall if the current function call is not the result of a cross-chain message.

import "@openzeppelin/contracts/crosschain/arbitrum/LibArbitrumL2.sol";

Primitives for cross-chain aware contracts for Arbitrum.

This version should only be used on L2 to process cross-chain messages originating from L1. For the other side, use LibArbitrumL1.

There is currently a bug in Arbitrum that causes this contract to fail to detect cross-chain calls when deployed behind a proxy. This will be fixed when the network is upgraded to Arbitrum Nitro, currently scheduled for August 31st 2022.

isCrossChain(address arbsys) → bool

internal

#

crossChainSender(address arbsys) → address

internal

#

Returns the address of the sender that triggered the current cross-chain message through arbsys.

NOTE: LibAMB.isCrossChain should be checked before trying to recover the sender, as it will revert with NotCrossChainCall if the current function call is not the result of a cross-chain message.

ARBSYS() → address

public

#

Returns whether the current function call is the result of a cross-chain message relayed by arbsys.

import "@openzeppelin/contracts/crosschain/errors.sol";

NotCrossChainCall()

error

#
import "@openzeppelin/contracts/crosschain/errors.sol";

InvalidCrossChainSender(address actual, address expected)

error

#
import "@openzeppelin/contracts/crosschain/optimism/CrossChainEnabledOptimism.sol";

Optimism specialization or the CrossChainEnabled abstraction.

The messenger (CrossDomainMessenger) contract is provided and maintained by the optimism team. You can find the address of this contract on mainnet and kovan in the deployments section of Optimism monorepo.

Available since v4.6.

constructor(address messenger)

internal

#

_isCrossChain() → bool

internal

#

_crossChainSender() → address

internal

#
import "@openzeppelin/contracts/crosschain/optimism/LibOptimism.sol";

Primitives for cross-chain aware contracts for Optimism. See the documentation for the functionality used here.

isCrossChain(address messenger) → bool

internal

#

Returns whether the current function call is the result of a cross-chain message relayed by messenger.

crossChainSender(address messenger) → address

internal

#

Returns the address of the sender that triggered the current cross-chain message through messenger.

NOTE: LibAMB.isCrossChain should be checked before trying to recover the sender, as it will revert with NotCrossChainCall if the current function call is not the result of a cross-chain message.

import "@openzeppelin/contracts/crosschain/polygon/CrossChainEnabledPolygonChild.sol";
import "@openzeppelin/contracts/crosschain/polygon/CrossChainEnabledPolygonChild.sol";

Polygon specialization or the CrossChainEnabled abstraction the child side (polygon/mumbai).

This version should only be deployed on child chain to process cross-chain messages originating from the parent chain.

The fxChild contract is provided and maintained by the polygon team. You can find the address of this contract polygon and mumbai in Polygon's Fx-Portal documentation.

Available since v4.6.

constructor(address fxChild)

internal

#

_isCrossChain() → bool

internal

#

_crossChainSender() → address

internal

#

processMessageFromRoot(uint256, address rootMessageSender, bytes data)

external

#

External entry point to receive and relay messages originating from the fxChild.

Non-reentrancy is crucial to avoid a cross-chain call being able to impersonate anyone by just looping through this with user-defined arguments.

Note: if _fxChild calls any other function that does a delegate-call, then security could be compromised.