Alert Source Discuss
Standards Track: Core

EIP-3541: 拒绝以 0xEF 字节开头的新合约代码

Authors Alex Beregszaszi (@axic), Paweł Bylica (@chfast), Andrei Maiboroda (@gumb0), Alexey Akhunov (@AlexeyAkhunov), Christian Reitwiessner (@chriseth), Martin Swende (@holiman)
Created 2021-03-16

摘要

禁止部署以 0xEF 字节开头的新代码。帐户 trie 中已经存在的以 0xEF 字节开头的代码不受此更改的语义影响。

动机

符合 EVM Object Format (EOF) 的合约将在部署时进行验证。为了保证状态中每个 EOF 格式的合约都是有效的,我们需要防止已经部署(且未验证)的合约被识别为此格式。这将通过为 magic 选择一个字节序列来实现,该字节序列在任何已部署的合约中都不存在。为了防止搜索空间的增长,并将分析限制在此分叉之前存在的合约,我们禁止该格式的起始字节(magic 的第一个字节)。

如果 EVM Object Format 提案在未来没有部署,magic 可以被其他依赖于版本控制的功能使用。如果版本控制变得过时,那么通过再次允许部署以 0xEF 字节开头的合约来简单地回滚此操作。

规范

block.number == HF_BLOCK 之后,如果 code 的第一个字节是 0xEF,则新的合约创建(通过创建交易、CREATECREATE2 指令)将导致异常中止。

备注

initcode 是在 create 交易、CREATECREATE2 指令的上下文中执行的代码。initcode 返回 code(通过 RETURN 指令),该 code 被插入到帐户中。有关更多信息,请参见黄皮书第 7 节(“合约创建”)。

操作码 0xEF 目前是一个未定义的指令,因此:它不弹出任何堆栈项,也不推送任何堆栈项,并且在执行时会导致异常中止。 这意味着以该指令开头的 initcode 或已部署的 code 将继续中止执行。

由于 code0xEF 开头而导致的异常中止的行为与 initcode 执行期间可能发生的任何其他异常中止完全相同,即如果中止,则提供给 CREATE* 或创建交易的所有 gas 都会被消耗。

理由

选择 0xEF 字节是因为它类似于 Executable Format。

通常认为使用未分配操作码的合约存在更改语义的风险。因此,使用未分配的 0xEF 应该比选择已分配的操作码(例如 0xFD (REVERT)、0xFE (INVALID)) 或 0xFF (SELFDESTRUCT))产生更小的影响。可以说,虽然这样的合约可能不是很有用,但它们仍然在使用有效的操作码。

2021 年 5 月对状态中的 18084433 个合约进行的分析表明,没有以 0xEF 字节开头的现有合约,而分别有 1、4 和 12 个合约以 0xFD0xFE0xFF 开头。

测试用例

以下每个测试用例都可以在 3 种不同的上下文中执行:

  • 创建交易(没有帐户代码)
  • CREATE,使用以下帐户代码:0x6000356000523660006000f0151560165760006000fd5b (Yul code: mstore(0, calldataload(0)) if iszero(create(0, 0, calldatasize())) { revert(0, 0) }),
  • CREATE2,使用以下帐户代码:0x60003560005260003660006000f5151560185760006000fd5b (Yul code: mstore(0, calldataload(0)) if iszero(create2(0, 0, calldatasize(), 0)) { revert(0, 0) })
用例 Calldata 预期结果
部署一个字节 ef 0x60ef60005360016000f3 新合约未部署,交易失败
部署两个字节 ef00 0x60ef60005360026000f3 新合约未部署,交易失败
部署三个字节 ef0000 0x60ef60005360036000f3 新合约未部署,交易失败
部署 32 个字节 ef00...00 0x60ef60005360206000f3 新合约未部署,交易失败
部署一个字节 fe 0x60fe60005360016000f3 新合约已部署,交易成功

向后兼容性

这是一个重大更改,因为以 0xEF 字节开头的新代码将无法部署,并且合约创建将导致失败。但是,鉴于字节码从其第一个字节开始执行,因此以 0xEF 作为第一个字节部署的代码无论如何都不可执行。

虽然这意味着当前没有可执行合约受到影响,但它确实拒绝了部署以 0xEF 字节开头的新数据合约。

安全注意事项

作者不知道此更改带来的任何安全或 DoS 风险。

版权

通过 CC0 放弃版权及相关权利。

Citation

Please cite this document as:

Alex Beregszaszi (@axic), Paweł Bylica (@chfast), Andrei Maiboroda (@gumb0), Alexey Akhunov (@AlexeyAkhunov), Christian Reitwiessner (@chriseth), Martin Swende (@holiman), "EIP-3541: 拒绝以 0xEF 字节开头的新合约代码," Ethereum Improvement Proposals, no. 3541, March 2021. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-3541.