在Solidity中用constant常量存储重复错误消息能否优化Gas/内存?
问题
我正在开发一款Solidity智能合约,其中多个require语句重复使用相同的错误消息。如果把该消息存储在constant常量变量中,并用这个变量替代所有require里的重复字符串,能不能优化Gas/内存使用?或者这种做法不可取?如果不可取,原因是什么?
示例代码
优化前
contract myContract{ function myFunc() external { require( [CONDITION_A] , "Test failed"); require( [CONDITION_B] , "Test failed"); require( [CONDITION_C] , "Test failed"); require( [CONDITION_D] , "Test failed"); [ACTUAL_OPERATIONS] } }
优化后
contract myContract{ string constant errMsg = "Test failed"; function myFunc() external { require( [CONDITION_A] , errMsg ); require( [CONDITION_B] , errMsg ); require( [CONDITION_C] , errMsg ); require( [CONDITION_D] , errMsg ); [ACTUAL_OPERATIONS] } }
解答
部署Gas能省,调用Gas差异可忽略
用string constant存储重复错误消息,确实能优化部署阶段的Gas消耗:
- 直接写重复字符串的话,每个
require里的字符串都会被单独打包进合约字节码,导致字节码体积变大,部署时要付更多Gas。换成常量后,字符串只存一次,字节码体积缩小,部署Gas直接减少,重复次数越多,省得越多。 - 调用阶段的Gas差异几乎可以忽略:常量是编译时直接嵌入字节码的,每次用的时候只是从字节码里读取,和直接写字符串的操作相比,额外消耗的Gas微乎其微,完全不影响实际使用。
这种做法不仅可取,还能提升代码质量
除了Gas优化,这么做最大的好处是提升可维护性:以后要改错误消息,只需要修改常量的定义,不用逐个找所有require语句去改,避免漏改或者改错。
额外建议:优先用自定义错误(Solidity 0.8.4+)
如果你的合约用的是Solidity 0.8.4及以上版本,更推荐用自定义错误替代字符串错误消息,Gas效率比常量还要高:
contract myContract{ error TestFailed(); function myFunc() external { if(![CONDITION_A]) revert TestFailed(); if(![CONDITION_B]) revert TestFailed(); // ... [ACTUAL_OPERATIONS] } }
自定义错误只在合约里存储一个标识符,不管调用多少次,都不会额外增加字节码体积,部署和调用阶段的Gas都比字符串更省,而且可读性也不差。
内容的提问来源于stack exchange,提问作者valed
相关产品推荐
相关产品推荐

