Alert Source Discuss
Standards Track: Core

EIP-140: REVERT 指令

Authors Alex Beregszaszi (@axic), Nikolai Mushegian <nikolai@nexusdev.us>
Created 2017-02-06

简单总结

REVERT 指令提供了一种停止执行并恢复状态更改的方法,无需消耗所有提供的 gas,并且能够返回原因。

摘要

REVERT 指令将停止执行,回滚到目前为止所做的所有状态更改,并提供一个指向内存区域的指针,该指针可以被解释为错误代码或消息。 在此过程中,它不会消耗所有剩余的 gas。

动机

目前这是不可能的。 从合约内部恢复交易有两种实用的方法:耗尽 gas 或执行无效指令。 这两种选择都会消耗所有剩余的 gas。 此外,恢复 EVM 执行意味着所有更改(包括 LOG)都会丢失,并且无法传达中止 EVM 执行的原因。

规范

block.number >= BYZANTIUM_FORK_BLKNUM 的区块上,REVERT 指令在 0xfd 处引入。 它需要两个堆栈项,顶部项是 memory_offset,后跟 memory_length。 它不会产生任何堆栈元素,因为它会停止执行。

REVERT 在内存和内存成本方面的语义与 RETURN 的语义相同。 memory_offsetmemory_length 给出的字节序列在下文中称为“错误消息”。

REVERT 的效果是执行中止,被视为失败,并且状态更改被回滚。 错误消息将在 returndata 缓冲区中提供给调用者,并且也会被复制到输出区域,即它以与处理常规返回数据相同的方式进行处理。

REVERT 指令的成本等于 RETURN 指令的成本,即回滚本身不会消耗所有 gas,合约只需支付内存费用。

如果剩余的 gas 不足以支付 REVERT 的成本,或者存在堆栈下溢,则 REVERT 指令的效果将等于常规的 out of gas 异常,即它将消耗所有 gas。

与所有其他失败一样,调用操作码在被调用者中的 REVERT 操作码之后,在堆栈上返回 0

如果在 CREATECREATE2 调用的上下文中使用了 REVERT,则不会部署任何代码,0 会被放置在堆栈上,并且错误消息可以在 returndata 缓冲区中使用。

此 EIP 未定义可选提供的内存部分的内容,但它是另一个信息性 EIP 的候选对象。

向后兼容性

此更改对过去创建的合约没有影响,除非它们包含 0xfd 作为指令。

测试用例

6c726576657274656420646174616000557f726576657274206d657373616765000000000000000000000000000000000000600052600e6000fd

应该:

  • 返回 0x726576657274206d657373616765 作为 REVERT 数据,
  • 0x0 处的存储应保持未设置状态,并且
  • 总共使用 20024 gas。

版权

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

Citation

Please cite this document as:

Alex Beregszaszi (@axic), Nikolai Mushegian <nikolai@nexusdev.us>, "EIP-140: REVERT 指令," Ethereum Improvement Proposals, no. 140, February 2017. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-140.