Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

require和assert的gas消耗对比问题 #93

Closed
edddyguo opened this issue Jul 13, 2022 · 9 comments
Closed

require和assert的gas消耗对比问题 #93

edddyguo opened this issue Jul 13, 2022 · 9 comments

Comments

@edddyguo
Copy link

理论上require的报错会将余下的gas返回给user,而assert会全部没收,而15_Error中实验结果,是assert比require更少的损耗,问题出在哪里

@AmazingAng
Copy link
Owner

AmazingAng commented Jul 13, 2022

可能是因为require里包含了报错提示字符,字符越长gas消耗越多。另外例子中代码比较少,可能代码长一些,才能看出差别。

@MultiSuperK
Copy link

@edddyguo 可以用钱包连公链测试一下差异,remix提供的默认节点返回的gas应该是实际执行指令的gas cost,跟公链有差别

@edddyguo
Copy link
Author

我在相应的require和assert的下方加入了一个for循环100次的逻辑,测试结果和原来的一直,assert都是将剩下的gas返还给user了,考虑到编译器版本的问题,我用0.6.4的编译器也是同样的测试结果,不知道为啥和搜到的文档里面描述的不一样

@edddyguo
Copy link
Author

@edddyguo 可以用钱包连公链测试一下差异,remix提供的默认节点返回的gas应该是实际执行指令的gas cost,跟公链有差别

一直是用的rinkeby测试的

@CryptoRbtree
Copy link
Contributor

CryptoRbtree commented Oct 4, 2022

Panic exceptions used to use the invalid opcode before Solidity 0.8.0, which consumed all gas available to the call.
https://docs.soliditylang.org/en/latest/control-structures.html#revert
感觉可以看下字节码指令是revert还是invalid。

0.8.0以后,revert、require、assert的底层字节码都是revert。
revert的消耗量应该和要看自定义Error的参数数目有关。
assert在revert的时候会默认携带内建Error——Panic(1),它有1个Error参数,所以理论上会比不带Error参数的revert消耗多一些gas。
require(string)在revert的时候会是携带Error(string),虽然也只有1个参数,但是如果想描述清楚错误原因,一般需要比较长的字符串,所以通常是消耗的。

@0xkookoo
Copy link
Contributor

0xkookoo commented Oct 8, 2022

我深入研究了一下:

Assert

assert关键字的底层opcodeSolidity 0.8.0之前都是INVALID, 是会消耗所有的剩余gas的,然后将所有状态恢复到这个call之前

  • AF: INVALID

On execution of any invalid operation, whether the designated INVALID opcode or simply an undefined opcode, all remaining gas is consumed and the state is reverted to the point immediately prior to the beginning of the current execution context.
image


assert关键字的底层opcodeSolidity 0.8.0之后都是REVERT, 而REVERT opcode只是一个简单的内存操作, revert(mem[ost:ost+len-1]),剩余的gas是会返还的

  • A0-1: Memory Expansion
    An additional gas cost is paid by any operation that expands the memory that is in use. This memory expansion cost is dependent on the existing memory size and is 0 if the operation does not reference a memory address higher than the existing highest referenced memory address. A reference is any read, write, or other usage of memory (such as in a CALL).

image

Require

Require关键字的底层opcode不管在Solidity的哪个版本都是REVERT,因此都会返还剩余的gas
image
image

Revert

Revert 关键字跟Require一样,会返还所有剩余的gas,可以自己去做实验

Highlight

以上讨论的topic都是是否会返还剩余的gas,已经执行过的语句(即报错之前的语句)所消耗的gas是不会返还的,因为这一块已经占用了矿工们(现在是POS Validator)的资源了,如果不收费就会造成有人无成本攻击Ethereum生态了。

References

@AmazingAng
Copy link
Owner

我深入研究了一下:

Assert

assert关键字的底层opcodeSolidity 8.0之前都是INVALID, 是会消耗所有的剩余gas的,然后将所有状态恢复到这个call之前

  • AF: INVALID

On execution of any invalid operation, whether the designated INVALID opcode or simply an undefined opcode, all remaining gas is consumed and the state is reverted to the point immediately prior to the beginning of the current execution context. image

assert关键字的底层opcodeSolidity 8.0之后都是REVERT, 而REVERT opcode只是一个简单的内存操作, revert(mem[ost:ost+len-1]),剩余的gas是会返还的

  • A0-1: Memory Expansion
    An additional gas cost is paid by any operation that expands the memory that is in use. This memory expansion cost is dependent on the existing memory size and is 0 if the operation does not reference a memory address higher than the existing highest referenced memory address. A reference is any read, write, or other usage of memory (such as in a CALL).

image

Require

Require关键字的底层opcode不管在Solidity的哪个版本都是REVERT,因此都会返还剩余的gas image image

Revert

Revert 关键字跟Require一样,会返还所有剩余的gas,可以自己去做实验

Hightlight

以上讨论的topic都是是否会返还剩余的gas,已经执行过的语句(即报错之前的语句)所消耗的gas是不会返还的,因为这一块已经占用了矿工们(现在是POS Validator)的资源了,如果不收费就会造成有人无成本攻击Ethereum生态了。

References

wow 详细

@dukedaily
Copy link

我深入研究了一下:

Assert

assert关键字的底层opcodeSolidity 8.0之前都是INVALID, 是会消耗所有的剩余gas的,然后将所有状态恢复到这个call之前

  • AF: INVALID

On execution of any invalid operation, whether the designated INVALID opcode or simply an undefined opcode, all remaining gas is consumed and the state is reverted to the point immediately prior to the beginning of the current execution context. image

assert关键字的底层opcodeSolidity 8.0之后都是REVERT, 而REVERT opcode只是一个简单的内存操作, revert(mem[ost:ost+len-1]),剩余的gas是会返还的

  • A0-1: Memory Expansion
    An additional gas cost is paid by any operation that expands the memory that is in use. This memory expansion cost is dependent on the existing memory size and is 0 if the operation does not reference a memory address higher than the existing highest referenced memory address. A reference is any read, write, or other usage of memory (such as in a CALL).

image

Require

Require关键字的底层opcode不管在Solidity的哪个版本都是REVERT,因此都会返还剩余的gas image image

Revert

Revert 关键字跟Require一样,会返还所有剩余的gas,可以自己去做实验

Hightlight

以上讨论的topic都是是否会返还剩余的gas,已经执行过的语句(即报错之前的语句)所消耗的gas是不会返还的,因为这一块已经占用了矿工们(现在是POS Validator)的资源了,如果不收费就会造成有人无成本攻击Ethereum生态了。

References

bravo!

@0xkookoo
Copy link
Contributor

0xkookoo commented Oct 8, 2022

Note

另外,在REVERT opcode被正式引入之前,所有rollback操作只能通过INVALID opcode来执行,痛点就是虽然rollback了但仍然要消耗掉所有剩余的gas,资本效率非常低。且那个时候Solidity连RequireRevert关键字都还没有

Time logs

  • 2016年8月22日 nmushegian 在这个PR中提出想引入一个新的opcode为REVERT
  • 2017年2月7号 axic 正式编写 EIP-140
  • 2017年3月16正式发布Solidity 0.4.10 版本,一次性加入了Require关键字,Revert关键字,REVERT opcode的编译支持。
  • 2017年9月14日发布EVM Megara (v1.7.0),支持REVERT opcode。

BTW,从这里我们可以看出来好像是Solidity语言先支持,然后EVM再支持,这个有点违反我的直觉了,没想通。

image

image

image

image

References

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants