To simplify the process of creating a cross-chain proposal this repository contains opinionated CrosschainForwarder
contracts for Polygon
, Optimism
and Arbitrum
abstracting away the complexity of bridging & cross-chain gas calculations.
All the forwarders follow the same pattern. They expect a payload to be deployed on L2 and to be executed with a parameterless execute()
signature and via DELEGATECALL
.
For a proposal to be executed on Polygon it needs to pass a mainnet governance proposal that sends an encoded payload via sendMessageToChild(address,bytes)
on FX_ROOT(mainnet) to FX_CHILD(Polygon).
Once the state is synced to FX_CHILD
on Polygon network it will queue the payload on POLYGON_BRIDGE_EXECUTOR.
For a proposal to be executed on Optimism it needs to pass a mainnet governance proposal that sends an encoded payload via sendMessage(address,bytes,uint32)
on L1_CROSS_DOMAIN_MESSENGER(mainnet) to L2_CROSS_DOMAIN_MESSENGER(Optimism).
Once the state is L2_CROSS_DOMAIN_MESSENGER
on Optimism it will queue the payload on OPTIMISM_BRIDGE_EXECUTOR.
For a proposal to be executed on Arbitrum it needs to pass a mainnet governance proposal that sends an encoded payload via unsafeCreateRetryableTicket{value: uint256}(address,uint256,uint256,address,address,uint256,uint256,bytes)
on INBOX(mainnet). The Arbitrum bridge will then call the bridged calldata via the L2_ALIAS of the mainnet msg.sender
(in this case is the aliased mainnet governance executor) which will queue the payload on ARBITRUM_BRIDGE_EXECUTOR.
Caveat: Opposed to the other bridges, Arbitrum inbox bridge requires you to supply some gas.
For simplicity the CrosschainForwarderArbitrum
expects some eth to be available on the SHORT_EXECUTOR.
You can check if you need to top-up the SHORT_EXECUTOR by calling getRequiredGas(580)
on the CrosschainForwarderArbitrum
.