失败的 `require` 是否会使函数使用更少或不使用 GAS

Does failing `require` makes function use less or no GAS

让我们想象一下简单的智能合约功能

mapping (address => uint8) votes;
function vote(address _address, uint8 _vote) {
   require(notVotedYet(_address))
   votes[_address] = _vote
}

我知道免费提供一个方法 - 我应该将其标记为 view,但这不合适。

仅当用户尚未投票时,此方法才会写入区块链。

我的问题是:

  1. EVM "know" 会不会有 require 失败,并做出这样的 免费电话?或者换句话说,当需求失败和通过时,gas "consumption" 会有所不同吗?
  2. 如果不是(消耗的气体是恒定的)-有没有办法实现它(用 修饰符?)所以来自 _address 的任何调用都不会花费任何 GAS?

我想我的主要问题是:耗气量是在运行时计算的,还是通过某种静态分析计算的?

  1. would EVM "know" that there can be a require failing, and make such calls free?

如果您的函数的可见性设置为 view,那么这两种方式都是免费的。

如果您的方法中有 require 而失败,返回值将是:

  • 0 对于 uint
  • false 对于 bool
  • 0x0000000000000000000000000000000000000000 对于 address
  • “”为 string

在您的情况下,行 votes[_address] = _vote 正在修改状态。修改状态总是要消耗 gas。如果您添加新的非零值,则需要 20000 gas,如果您将此值设置为 0,则需要 5000 gas。此操作在较低级别上称为 SSTORE。说明你对存储内存做了改动。


would gas "consumption" be different when the require fails and when it pass?

这个想法是,tx 发送方为矿工完成的任何计算付费。在 require 的情况下,矿工将因他 无论如何 所做的工作而获得奖励。 21000 gas 将支付椭圆曲线操作的成本,以从签名 + 之前计算消耗的任何气体中恢复发件人地址 require

如果 REVERT 操作码在 require 评估为 false 时被触发,所有剩余的气体 (gasLimit - gasConsumed) 将被发送回 tx 发送方。所有 require-style 异常都遵循此行为。

assert-style异常的情况下,完整的gasLimit将被失败的事务消耗。


文档中提到的 Byzantium(大都会第 1 部分 - 2017 年 10 月发布)更改是 require 现在使用 REVERT 操作码。在发布之前,它使用与 assert 相同的操作码,这将消耗所有气体。 REVERT 退还剩余的 gas。有关详细信息,请参阅此博客 post:POST

编辑:所以文档不是很准确,"consuming no gas" 显然意味着只消耗用过的气体,而不是所有的气体限制。

我不知道为什么会这样,但我在 Udemy 课程上注意到,当您清楚地看到消耗了几千 gas 时,演示者也会说 "no gas consumed"。在花费的订单或量级很少的地方 - 它被认为是 "really spent"

有点混乱。请也检查


所以我扫描了文档,找到了一个明确的答案:

Note that assert-style exceptions consume all gas available to the call, while require-style exceptions will not consume any gas starting from the Metropolis release.

来源:https://solidity.readthedocs.io/en/develop/control-structures.html#error-handling-assert-require-revert-and-exceptions

我找不到确切的日期,但根据各种文章看来它已经发布了 (https://www.cryptocompare.com/coins/guides/the-ethereum-releases-of-frontier-homestead-metropolis-and-serenity/)