失败的`require`会使函数使用更少或没有GAS

时间:2018-02-10 08:30:53

标签: ethereum solidity

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

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

我知道要使方法免费 - 我应该将其标记为view,但这不合适。

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

我的问题是:

  1. 将EVM“知道”可能需要失败,并且这样做 免费通话?或者换句话说,当需求失败并通过时,气体“消耗”会不同吗?
  2. 如果没有(消耗的气体是恒定的) - 有没有办法实现它(有 修饰符?)所以来自_address的任何调用都不会花费任何GAS?
  3. 我猜想我的主要问题是:在运行时计算气体消耗量,还是通过某种静态分析?

2 个答案:

答案 0 :(得分:2)

  
      
  1. 将EVM"知道"可以要求失败,并免费拨打电话吗?
  2.   

如果您的功能的可见性设置为view,那么它将是免费的。

如果您的方法中存在require并且它失败,则返回的值将为:

  • 0 代表uint
  • false bool
  • {li> 0x0000000000000000000000000000000000000000 address
  • "" string

在你的情况下,行votes[_address] = _vote正在修改状态。改变国家总是需要燃气。如果你添加新的非零值,它将需要20000气体,如果你将这个值设置为0,它将花费5000气体。此操作在较低级别称为SSTORE。它说明您在存储内存中进行了更改。

  

将燃气"消费"当需求失败时和何时失败   它通过了?

这个想法是,tx发送者支付矿工完成的任何计算。如果是require,矿工将获得奖励,无论如何 21000 gas将涵盖椭圆曲线操作的成本,以便从签名 + 恢复require之前计算消耗的任何气体的发件人地址。

如果gasLimit - gasConsumed操作码在REVERT评估为错误时被触发,则所有剩余的气体(require)将被发送回tx发件人。所有 require-style 例外都会出现此行为。

如果出现断言式异常,则失败的交易将使用完整的gasLimit

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

答案 1 :(得分:0)

编辑:所以文件不是很精确,而且“不消耗气体”显然意味着只消耗废气,而不是全部气体限制。

我不知道为什么会这样,但我在Udemy课程中注意到,当你明显看到几千个气体消耗时,主持人也说“没有气体消耗”。而且花费的订单或数量很少 - 它被认为是“真的花了”

这有点令人困惑。请检查Roman's answer

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

  

请注意,断言式异常会消耗呼叫可用的所有气体,而需求式异常不会消耗从Metropolis版本开始的任何气体。

来源: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/