Solidity中require与if/revert自定义错误的优劣势及取舍问题
这两种校验方式并非仅属于使用偏好差异,二者在gas消耗、调试体验、兼容性上都有明确的区别,具体可以从以下几个维度展开:
1. Gas消耗对比
- 带错误信息的
require(condition, "error msg"):错误字符串会被完整写入合约字节码,字符串越长,部署gas越高;触发校验失败时,也需要额外gas返回全量字符串数据,同等信息量下,比自定义错误的revert每次触发多消耗100~1000gas不等,部署阶段也会多消耗数百到数千gas。 - 无错误信息的
require(condition):仅返回空的错误数据,gas消耗和无参数的自定义错误revert几乎一致,差异可以忽略。 if (!condition) revert CustomError():Solidity 0.8.4引入的自定义错误仅占用4字节的选择器,就算携带结构化参数,编码后的长度也远短于等信息量的字符串,不管是部署成本还是触发失败时的运行时成本都更低,是生产级合约的主流优化选择。
2. 错误输出与调试体验
require的优势是语法简单,带字符串错误信息时不需要额外定义类型,链下工具可以直接读取人可读信息,适合小型项目快速开发。缺点是信息承载力弱,如需传递动态参数(比如错误时的当前余额、需要的额度),只能拼接字符串,会大幅推高gas成本。- 自定义错误的
revert支持结构化参数,比如可以定义error InsufficientBalance(uint256 current, uint256 required),触发错误时直接传入对应数值,链下工具可以直接解析出结构化数据,不需要做字符串匹配,调试复杂业务逻辑时效率高很多,也方便上层SDK做错误类型的精准判断。唯一的劣势是早期的旧版开发工具对自定义错误的解析支持不完善,但目前主流的Hardhat、Foundry、ethers.js等工具都已完成适配。
3. 兼容性与使用场景选择
- 如果你的合约需要兼容0.8.4以下的Solidity版本,只能使用
require语法。 - 如果是小范围使用的简单校验,不需要传递错误参数,两种写法差异很小,可以根据团队编码偏好选择。
- 生产级公共合约、校验逻辑多、需要对外提供SDK对接的场景,更推荐使用自定义错误的revert写法,长期能节省大量用户gas,也能提升对接体验。
内容的提问来源于stack exchange,提问作者Davy
相关产品推荐
相关产品推荐

