Alert Source Discuss
📢 Last Call Standards Track: ERC

ERC-5164: 跨链执行

定义了一个支持跨 EVM 网络执行的接口。

Authors Brendan Asselstine (@asselstine), Pierrick Turelier (@PierrickGT), Chris Whinfrey (@cwhinfrey)
Created 2022-06-14
Last Call Deadline 2023-11-15

摘要

本规范定义了基于 EVM 的区块链的跨链执行接口。 此规范的实现将允许一条链上的合约通过发送跨链消息来调用另一条链上的合约。

该规范定义了两个组件:“消息调度器”和“消息执行器”。 消息调度器位于调用端,执行器位于接收端。 发送消息时,消息调度器会将消息通过传输层移动到消息执行器,并在那里执行它们。 此规范的实现必须实现这两个组件。

动机

许多以太坊协议需要协调多个基于 EVM 的区块链之间的状态更改。 这些链通常具有允许以太坊合约执行代码的本机或第三方桥。 但是,桥具有不同的 API,因此桥集成是自定义的。 每一个都提供不同的属性; 具有不同程度的安全性、速度和控制。 定义一个简单、通用的规范将增加代码重用,并允许我们使用通用的桥实现。

规范

本文档中使用的关键词“MUST”、“MUST NOT”、“REQUIRED”、“SHALL”、“SHALL NOT”、“SHOULD”、“SHOULD NOT”、“RECOMMENDED”、“MAY”和“OPTIONAL”应按照 RFC 2119 中的描述进行解释。

该规范允许一条链上的合约向另一条链上的合约发送消息。 需要实现两个关键接口:

  • MessageDispatcher
  • MessageExecutor

MessageDispatcher 位于原始链上,并将消息调度到 MessageExecutor 以供执行。 MessageExecutor 位于目标链上并执行调度的消息。

MessageDispatcher

MessageDispatcher 位于发送消息的链上。 调度程序的工作是通过传输层将消息广播到一个或多个 MessageExecutor 合约。

必须为每条消息或消息批次生成唯一的 messageId。 消息标识符在链和调度程序之间必须是唯一的。 这可以通过散列 chainId, dispatcherAddress, messageNonce 元组来实现,其中 messageNonce 是每条消息单调递增的整数。

MessageDispatcher 方法

dispatchMessage

将调度一条消息,以便由 toChainId 指定的目标链上的 MessageExecutor 执行。

当调度消息时,MessageDispatcher 必须发出 MessageDispatched 事件。

如果不支持 toChainIdMessageDispatcher 必须恢复。

MessageDispatcher 必须将消息转发到 toChainId 上的 MessageExecutor

MessageDispatcher 必须为每条消息使用唯一的 messageId

MessageDispatcher 必须返回 messageId,以允许消息发送者跟踪消息。

MessageDispatcher 可以要求付款。

interface MessageDispatcher {
  function dispatchMessage(uint256 toChainId, address to, bytes calldata data) external payable returns (bytes32 messageId);
}
- name: dispatchMessage
  type: function
  stateMutability: payable
  inputs:
    - name: toChainId
      type: uint256
    - name: to
      type: address
    - name: data
      type: bytes
  outputs:
    - name: messageId
      type: bytes32

MessageDispatcher 事件

MessageDispatched

当调度单个消息时,MessageDispatcher 必须发出 MessageDispatched 事件。

interface MessageDispatcher {
  event MessageDispatched(
    bytes32 indexed messageId,
    address indexed from,
    uint256 indexed toChainId,
    address to,
    bytes data,
  );
}
- name: MessageDispatched
  type: event
  inputs:
    - name: messageId
      indexed: true
      type: bytes32
    - name: from
      indexed: true
      type: address
    - name: toChainId
      indexed: true
      type: uint256
    - name: to
      type: address
    - name: data
      type: bytes

MessageExecutor

MessageExecutor 执行调度的消息和消息批次。 开发人员必须实现 MessageExecutor 才能在接收链上执行消息。

MessageExecutor 将仅执行一次 messageId,但可以按任何顺序执行 messageId。 此规范不保证排序,因为消息和消息批次可能以非顺序方式通过传输层传输。

执行

MessageExecutor 应该使用桥传输层验证所有消息数据。

MessageExecutor 绝不能成功执行一条消息多次。

当消息执行失败时,MessageExecutor 必须恢复交易,以便稍后重试消息。

Calldata

MessageExecutor 必须将 ABI 编码的(messageIdfromChainIdfrom)附加到要执行的每条消息的 calldata 中。 这允许消息的接收者验证跨链发送者以及消息来自的链。

to.call(abi.encodePacked(data, messageId, fromChainId, from));
- name: calldata
  type: bytes
  inputs:
    - name: data
      type: bytes
    - name: messageId
      type: bytes32
    - name: fromChainId
      type: uint256
    - name: from
      type: address

MessageExecutor 事件

MessageIdExecuted

一旦执行了消息或消息批次,就必须发出 MessageIdExecuted

interface MessageExecutor {
  event MessageIdExecuted(
    uint256 indexed fromChainId,
    bytes32 indexed messageId
  );
}
- name: MessageIdExecuted
  type: event
  inputs:
    - name: fromChainId
      indexed: true
      type: uint256
    - name: messageId
      indexed: true
      type: bytes32

MessageExecutor 错误

MessageAlreadyExecuted

如果 messageId 已经被执行,MessageExecutor 必须恢复,并且应该发出一个 MessageIdAlreadyExecuted 自定义错误。

interface MessageExecutor {
  error MessageIdAlreadyExecuted(
    bytes32 messageId
  );
}

MessageFailure

如果单个消息失败,MessageExecutor 必须恢复,并且应该发出 MessageFailure 自定义错误。

interface MessageExecutor {
  error MessageFailure(
    bytes32 messageId,
    bytes errorData
  );
}

理由

MessageDispatcher 可以耦合到一个或多个 MessageExecutor。 由桥决定如何耦合这两个。 用户可以通过调用 dispatchMessage 轻松桥接消息,而无需知道 MessageExecutor 地址。 客户端还可以使用 MessageIdExecuted 事件记录的数据来跟踪消息。

某些桥可能需要以本地货币支付,因此 dispatchMessage 函数是 payable 的。

向后兼容性

此规范与现有的治理系统兼容,因为它提供了简单的跨链执行。

安全注意事项

桥信任配置文件是可变的,因此用户必须了解桥安全性取决于实现。

版权

CC0 下放弃版权和相关权利。

Citation

Please cite this document as:

Brendan Asselstine (@asselstine), Pierrick Turelier (@PierrickGT), Chris Whinfrey (@cwhinfrey), "ERC-5164: 跨链执行 [DRAFT]," Ethereum Improvement Proposals, no. 5164, June 2022. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-5164.