Crosschain
Smart contract crosschain utilities and implementations
Outdated 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
.
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.
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.
Functions
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:
- ETH ⇌ xDai
- ETH ⇌ qDai
- ETH ⇌ ETC
- ETH ⇌ BSC
- ETH ⇌ POA
- BSC ⇌ xDai
- POA ⇌ xDai
- Rinkeby ⇌ xDai
- Kovan ⇌ Sokol
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.
Functions
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
.
Functions
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.
Functions
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.