Alert Source Discuss
Standards Track: Core

EIP-3855: PUSH0 指令

引入一个新的指令,将常量值 0 推送到堆栈上

Authors Alex Beregszaszi (@axic), Hugo De la cruz (@hugo-dc), Paweł Bylica (@chfast)
Created 2021-02-19

摘要

引入 PUSH0 (0x5f) 指令,该指令将常量值 0 推送到堆栈上。

动机

许多指令期望偏移量作为输入,在许多情况下这些偏移量为零。一个很好的例子是 CALL 的返回数据参数,如果合约倾向于使用 RETURNDATA*,则这些参数设置为零。这只是一个例子,但是合约需要推送零值的原因还有很多。它们今天可以通过 PUSH1 0 来实现,这在运行时花费 3 个 gas,并被编码为两个字节,这意味着 2 * 200 gas 的部署成本。

由于总成本的原因,许多人试图使用各种其他指令来实现相同的效果。常见的例子包括 PCMSIZECALLDATASIZERETURNDATASIZECODESIZECALLVALUESELFBALANCE。其中一些仅花费 2 个 gas 并且是一个字节长,但是它们的值可能取决于上下文。

我们对主网进行了分析(区块范围 8,567,259…8,582,058 和 12,205,970…12,817,405),并且执行的所有 PUSH* 指令中约有 11.5% 推送零值。

此更改的主要动机包括:

  1. 减少合约代码大小。
  2. 降低合约(误)使用各种指令作为优化措施的风险。重新定价/更改这些指令可能更具风险。
  3. 减少使用 DUP 指令来复制零的需要。

为了使“浪费”更具说服力,在现有帐户中,有 340,557,331 字节浪费在 PUSH1 00 指令上,这意味着花费了 68,111,466,200 gas 来部署它们。实际上,许多这些帐户与其他帐户共享相同的字节码,因此它们在客户端中的总存储大小较低,但是无论如何都必须支付部署时间成本。

2) 的一个例子是更改 RETURNDATASIZE 的行为,使其不能保证在调用帧的开头为零。

规范

0x5f 处引入指令 PUSH0。它没有立即数据,不会从堆栈中弹出任何项目,并将一个值为 0 的项目放置到堆栈上。此指令的成本为 2 gas(又名 base)。

理由

Gas 成本

base gas 成本用于将常量值放置到堆栈上的指令,例如 ADDRESSORIGIN 等。

操作码

0x5f 意味着它与其余的 PUSH 实现位于“连续”空间中,并且可能可以共享实现。

向后兼容性

此 EIP 引入了一个以前不存在的新操作码。已部署的使用此操作码的合约可能会在此 EIP 之后更改其行为。

测试用例

  • 5F – 成功执行,堆栈由单个项目组成,设置为零
  • 5F5F..5F (1024 times) – 成功执行,堆栈由 1024 个项目组成,全部设置为零
  • 5F5F..5F (1025 times) – 由于堆栈溢出而中止执行

安全注意事项

作者不知道对安全的任何影响。请注意,jumpdest-analysis 不受影响,因为 PUSH0 没有立即数据字节。

版权

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

Citation

Please cite this document as:

Alex Beregszaszi (@axic), Hugo De la cruz (@hugo-dc), Paweł Bylica (@chfast), "EIP-3855: PUSH0 指令," Ethereum Improvement Proposals, no. 3855, February 2021. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-3855.