diff --git a/EIPS/eip-5164.md b/EIPS/eip-5164.md new file mode 100644 index 00000000000000..bfbd0ba9e0c6d6 --- /dev/null +++ b/EIPS/eip-5164.md @@ -0,0 +1,200 @@ +--- +eip: 5164 +title: Cross-Chain Execution +description: Defines an interface that supports execution across EVM networks. +author: Brendan Asselstine (@asselstine), Pierrick Turelier (@PierrickGT), Anna Carroll (@anna-carroll), Hadrien Croubois (@Amxx), Nam Chu Hoai (@nambrot), Georgios (@geogons), Theo Gonella (@mintcloud), Rafael Solari (@rsolari), Auryn Macmillan (@auryn-macmillan), Nathan Ginnever (@nginnever) +discussions-to: https://ethereum-magicians.org/t/eip-5164-cross-chain-execution/9658 +status: Draft +type: Standards Track +category: ERC +created: 2022-06-14 +--- + +## Abstract + +This specification defines a cross-chain execution interface for EVM-based blockchains. Developers will be able to have contracts call contracts on other chains. There are two parts to this spec: the "sending" interface and the "executing" interface. The "sending" interface specifies the interface to send a call to another chain; this interface must be implemented by bridges. The "executing" interface must be implemented by the application; it is an interface for executing cross-chain calls. This specification is agnostic of the bridge implementation; it simply standardizes the call interfaces. + +## Motivation + +Many Ethereum protocols need to coordinate state changes across multiple EVM-based blockchains. These chains often have native or third-party bridges that allow Ethereum contracts to execute code. However, bridges have different APIs so bridge integrations are custom. Each one affords different properties; with varying degrees of security, speed, and control. + +## Specification + +The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in RFC 2119. + +This specification allows contracts on one chain to send messages to contracts on another chain. There are two key interfaces that needs to be implemented: + +- `CrossChainRelayer` +- `CrossChainExecutor` + +The `CrossChainRelayer` lives on the origin chain. Users can share a single `CrossChainRelayer` or deploy their own. + +The `CrossChainExecutor` lives on the destination chain and executes relayed calls. Users can share a single `CrossChainExecutor` or deploy their own. + +### CrossChainRelayer + +The `CrossChainRelayer` lives on the chain from which messages are sent. The Relayer's job is to broadcast the messages through a transport layer. + +#### Methods + +**relayCalls** + +`CrossChainRelayer`s MUST emit the `RelayedCalls` event when successfully called. + +`CrossChainRelayer`s MUST increment a `nonce` so that each batch of calls can be uniquely identified. + +`CrossChainRelayer`s MAY require payment. + +```solidity +struct Call { + address target; + bytes data; +} + +interface CrossChainRelayer { + function relayCalls(Call[] calldata calls, uint256 gasLimit) external payable; +} +``` + +```yaml +- name: relayCalls + type: function + stateMutability: payable + inputs: + - name: calls + type: Call[] + - name: gasLimit + type: uint256 +``` + +#### Events + +**RelayedCalls** + +The `RelayedCalls` event MUST be emitted by the `CrossChainRelayer` when `relayCalls` is called. + +```solidity +interface CrossChainRelayer { + event RelayedCalls( + uint256 indexed nonce, + address indexed sender, + CrossChainExecutor indexed executor, + Call[] calls, + uint256 gasLimit + ); +} +``` + +```yaml +- name: RelayedCalls + type: event + inputs: + - name: nonce + indexed: true + type: uint256 + - name: sender + indexed: true + type: address + - name: executor + indexed: true + type: address + - name: calls + type: Call[] + - name: gasLimit + type: uint256 +``` + +#### Error handling + +**GasLimitTooHigh** + +`CrossChainRelayer`s MAY revert with `GasLimitTooHigh` if the `gasLimit` passed to `relayCalls` is higher than the maximum gas limit accepted by the bridge being used. + +```solidity +interface CrossChainRelayer { + error GasLimitTooHigh( + uint256 gasLimit, + uint256 maxGasLimit + ); +} +``` + +### CrossChainExecutor + +The `CrossChainExecutor` executes relayed calls. Developers must implement a `CrossChainExecutor` in order to execute messages on the receiving chain. + +#### Authentication + +`CrossChainRelayer`s SHOULD authenticate that the call has been performed by the bridge transport layer. + +`CrossChainRelayer`s SHOULD use [EIP-2771](./eip-2771.md) for authentication and append the address of the Transaction Signer (20 bytes of data) on the origin chain to the end of the call data being executed. + +#### Error handling + +**CallFailure** + +`CrossChainRelayer`s SHOULD revert with `CallFailure` if a call fails. + +```solidity +interface CrossChainExecutor { + error CallFailure( + Call call, + bytes errorData + ); +} +``` + +#### Events + +**ExecutedCalls** + +`ExecutedCalls` MUST be emitted once calls have been executed. + +```solidity +interface CrossChainExecutor { + event ExecutedCalls( + CrossChainRelayer indexed relayer, + uint256 indexed nonce, + address indexed caller + ); +} +``` + +```yaml +- name: ExecutedCalls + type: event + inputs: + - name: relayer + indexed: true + type: CrossChainRelayer + - name: nonce + indexed: true + type: uint256 + - name: caller + indexed: true + type: address +``` + +### ExecutorAware + +The `ExecutorAware` interface follows [EIP-2771](./eip-2771.md) and allows applications to verify where the call originated from. + +## Rationale + +The Relayer address is passed to the executor so that the execution can easily be traced by a client using the relayer address and nonce. A third party just needs to be aware of a list of Relayers and a list of Executors and can trace execution across all of them. + +Calls are relayed in batches because it is such a common action. Rather than have implementors take different approaches to encoding multiple calls into the `data` portion, this spec includes call batching to take away any guess work. + +Some bridges may require payment in the native currency, so the `relayCalls` function is payable. + +## Backwards Compatibility + +This specification is compatible with existing governance systems as it offers simple cross-chain execution. + +## Security Considerations + +Bridge trust profiles are variable, so users must understand that bridge security depends on the implementation. + +## Copyright + +Copyright and related rights waived via [CC0](../LICENSE.md).