Alert Source Discuss
⚠️ Review Standards Track: Core

EIP-5920: PAY 操作码

引入一个新的操作码 PAY,用于将以太币发送到一个地址,而不调用该地址的任何函数

Authors Gavin John (@Pandapip1), Zainan Victor Zhou (@xinbenlv), Sam Wilson (@SamWilsn), Jochem Brouwer (@jochem-brouwer), Charles Cooper (@charles-cooper)
Created 2022-03-14
Requires EIP-214, EIP-2929, EIP-7523

摘要

本 EIP 引入一个新的操作码 PAY,它接受两个堆栈参数 addrval,并将 val wei 转移到地址 addr,而不调用它的任何函数。

动机

目前,要将以太币发送到一个地址,需要调用该地址,这会将执行上下文转移到该地址,从而产生以下几个问题:

  • 首先,它打开了一个重入攻击向量,因为接收者可以回调发送者。更一般地说,接收者可以单方面执行任意状态更改,仅受转发的 gas 限制,这从发送者的角度来看是不希望的。
    • 在实践中,当调用另一个账户并发送以太币时,在新创建的调用帧中总是可以“免费”提供 2300 gas(“gas 预付”)。尽管目前无法使用 2300 gas 预付进行存储状态更改(参见 EIP-1283 在君士坦丁堡被最后一刻拒绝,并被伊斯坦布尔的“gas 预付安全”EIP-2200 版本取代),但可以使用瞬态存储 (EIP-1153) 来做到这一点。这是一个安全风险,瞬态存储可能会被意外更改。目标是发送以太币,而不必考虑这些潜在的、不直观的安全问题。
  • 其次,它打开了一个 DoS 向量。想要发送以太币的合约必须意识到接收者可能会耗尽 gas 或 revert。
  • 未来潜在的类调用操作码可能无法提供限制转发给接收者的 gas 数量的方法,因此目前使用的针对意外副作用的微薄缓解措施(gas 限制)无法保证可用。
  • CALLEXTCALL 操作码将在接收者上执行代码,这在想要发送以太币时是无意的,并且可能导致无意的操作。代码执行也必须用 gas 支付,即使意图只是发送以太币,这也是不必要的 gas 浪费。
  • 最后,EIP-7702 允许将外部拥有账户 (EOA) 委托给其他账户,这打破了 EOA 不能包含代码的不变性。因此,调用这样的 EOA 以发送以太币也将执行代码并花费不必要的 gas。

拥有一个专门用于以太币转移的操作码可以解决所有这些问题,并且将是对 EVM 的一个有用的补充。

规范

常量

常量 定义
WARM_STORAGE_READ_COST EIP-2929
COLD_ACCOUNT_ACCESS_COST EIP-2929
GAS_NEW_ACCOUNT EELS
GAS_CALL_VALUE EELS

行为

引入了一个新的操作码:PAY (0xfc),它:

  • 如果当前帧是静态的,则以异常失败halt,如 EIP-214 中定义的那样。
  • 从堆栈中弹出两个值:addr 然后 val
  • 如果 addr 的任何高 12 个字节设置为非零值(即,它不包含 20 字节地址),则异常halt。
  • 收取下面详述的 gas 成本。
  • addr 标记为 warm(将 addr 添加到 accessed_addresses)。
  • val wei 从当前地址转移到地址 addr,仅当当前地址的余额大于或等于 val 时。
  • 如果 PAY 操作成功,则在堆栈上推送 1,如果失败,则推送 0
    • 目前只有余额不足会产生 0 返回值。

Gas 成本

PAY 的 gas 成本是以下各项的总和:

  • addr 是否在 accessed_addresses 中?
    • 如果是,WARM_STORAGE_READ_COST
    • 否则,COLD_ACCOUNT_ACCESS_COST
  • addr 是否存在或 val 是否为零?
    • 如果是,则为零;
    • 否则,GAS_NEW_ACCOUNT
  • val 是否为零?
    • 如果是,则为零;
    • 否则,GAS_CALL_VALUE

PAY 无法在具有空账户的网络上实现(参见 EIP-7523)。

理由

参数顺序

参数的顺序模仿 CALL 的顺序,后者在 val 之前弹出 addr。除了保持一致性之外,这种排序还有助于验证器模式匹配 MEV 机会,因此 PAY 总是立即出现在 COINBASE 之后。

无效地址时暂停

暂停行为旨在允许地址空间扩展。 如果像在 CALL 中一样截断了高位字节,则合约可以依赖于截断行为。 如果地址空间扩展到 20 字节以上,则 PAY 要么无法定位这些账户,要么期望截断的代码可能会将以太币发送到错误的地址。

由于此行为可能会更改,因此合约不应依赖此暂停行为,而应使用指定为有意暂停的方法(例如 INVALID 操作码)。

向后兼容性

此更改需要硬分叉。

安全注意事项

现有合约不应依赖于其余额在其控制之下,因为已经可以通过使用 SELFDESTRUCT 操作码(在 EIP-6780 中受到一些限制)将以太币发送到地址而不调用它。 也可以通过发送到 block.coinbase 的优先级费用来非自愿地为账户提供资金。 但是,此操作码确实使此过程更便宜且更容易。因此,它不会打破不变性。

版权

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

Citation

Please cite this document as:

Gavin John (@Pandapip1), Zainan Victor Zhou (@xinbenlv), Sam Wilson (@SamWilsn), Jochem Brouwer (@jochem-brouwer), Charles Cooper (@charles-cooper), "EIP-5920: PAY 操作码 [DRAFT]," Ethereum Improvement Proposals, no. 5920, March 2022. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-5920.