Solidity中如此使用revert是否正确?参数验证与Gas返还咨询
问题:Solidity中modifier里同时使用require和revert是否正确?
我编写了一个抽象合约,需要对参数进行验证,若参数无效则返回错误并返还Gas费用。我创建了名为checkNumber的modifier,在其中验证_number参数,同时使用了require和revert语句,相关代码如下:
//SPDX-License-Identifier: UNLICENSED // Solidity files have to start with this pragma. // It will be used by the Solidity compiler to validate its version. pragma solidity >=0.7.0 <0.9.0; struct Information { uint number; string avatar; } abstract contract AbstractCandidate { uint[6] private _numbers = [1, 2, 3, 4, 5, 6]; string[6] private _avatars = [ "https://raw.githubusercontent.com/thiagosaud/dApp-superior-electoral-court/main/temp/imgs/candidate-1.png", "https://raw.githubusercontent.com/thiagosaud/dApp-superior-electoral-court/main/temp/imgs/candidate-2.png", "https://raw.githubusercontent.com/thiagosaud/dApp-superior-electoral-court/main/temp/imgs/candidate-3.png", "https://raw.githubusercontent.com/thiagosaud/dApp-superior-electoral-court/main/temp/imgs/candidate-4.png", "https://raw.githubusercontent.com/thiagosaud/dApp-superior-electoral-court/main/temp/imgs/candidate-5.png", "https://raw.githubusercontent.com/thiagosaud/dApp-superior-electoral-court/main/temp/imgs/candidate-6.png" ]; modifier checkNumber(uint _number) { string memory _errorMessage = "Candidate number is incorret!"; require(_number < 1 || _number > _numbers.length, _errorMessage); if (_number < 1 || _number > _numbers.length) { revert(_errorMessage); } _; } function getInformation(uint _number) external view checkNumber(_number) returns(Information memory) { return Information({ avatar: _avatars[_number], number: _numbers[_number] }); } }
请问这样使用revert是否正确?
回答
你的用法不正确,核心问题有以下几点:
- require条件逻辑完全写反
require的执行逻辑是:当条件为true时继续执行代码,条件为false时触发回滚并返回错误信息。你当前的require(_number < 1 || _number > _numbers.length, _errorMessage);意思是「只有参数无效时才允许继续执行」,这和你的验证需求完全相反。正确的条件应该是验证参数有效:
require(_number >= 1 && _number <= _numbers.length, _errorMessage);
重复验证完全多余
在require已经触发回滚的前提下,后面的if判断和revert语句永远不会被执行——因为如果参数无效,require已经终止了代码执行并回滚。所以同时使用require和revert做相同验证是毫无意义的,选其中一个即可(实际开发中更常用require做参数校验)。存在数组索引越界风险
你的_numbers和_avatars是长度为6的数组,索引从0到5,但候选编号是1到6。当你用_avatars[_number]时,比如_number=6,会访问数组索引6,直接触发越界报错。正确的写法应该是用_number - 1来匹配数组索引:
return Information({ avatar: _avatars[_number - 1], number: _numbers[_number - 1] });
另外注意你的错误信息里拼写错误:incorret应该改为incorrect。
修正后的核心代码
modifier checkNumber(uint _number) { string memory _errorMessage = "Candidate number is incorrect!"; require(_number >= 1 && _number <= _numbers.length, _errorMessage); _; } function getInformation(uint _number) external view checkNumber(_number) returns(Information memory) { return Information({ avatar: _avatars[_number - 1], number: _numbers[_number - 1] }); }
总结:
- require和revert的作用一致,都是触发回滚并返还未消耗的Gas,无需同时使用
- 编写校验条件时一定要注意逻辑正确性,避免反向判断
- 访问数组时要确保索引在合法范围内,防止越界报错
内容的提问来源于stack exchange,提问作者THIAGO DE BONIS
相关产品推荐
相关产品推荐

