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
,则新的合约创建(通过创建交易、CREATE
或 CREATE2
指令)将导致异常中止。
备注
initcode 是在 create 交易、CREATE
或 CREATE2
指令的上下文中执行的代码。initcode 返回 code(通过 RETURN
指令),该 code 被插入到帐户中。有关更多信息,请参见黄皮书第 7 节(“合约创建”)。
操作码 0xEF
目前是一个未定义的指令,因此:它不弹出任何堆栈项,也不推送任何堆栈项,并且在执行时会导致异常中止。 这意味着以该指令开头的 initcode 或已部署的 code 将继续中止执行。
由于 code 以 0xEF
开头而导致的异常中止的行为与 initcode 执行期间可能发生的任何其他异常中止完全相同,即如果中止,则提供给 CREATE*
或创建交易的所有 gas 都会被消耗。
理由
选择 0xEF
字节是因为它类似于 Executable Format。
通常认为使用未分配操作码的合约存在更改语义的风险。因此,使用未分配的 0xEF
应该比选择已分配的操作码(例如 0xFD
(REVERT
)、0xFE
(INVALID)
) 或 0xFF
(SELFDESTRUCT
))产生更小的影响。可以说,虽然这样的合约可能不是很有用,但它们仍然在使用有效的操作码。
2021 年 5 月对状态中的 18084433
个合约进行的分析表明,没有以 0xEF
字节开头的现有合约,而分别有 1、4 和 12 个合约以 0xFD
、0xFE
和 0xFF
开头。
测试用例
以下每个测试用例都可以在 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.