
在 Solidity 里处理异常时,几乎每份代码都会用到 require、assert、revert 这三个语句。很多新手把它们当"报错就 throw"混着用,结果要么多烧了 gas,要么在特定优化版本下把不该翻的合约搞挂。本文用一段可跑通的合约,讲清三者底层区别(借助汇编级 invalid vs revert),并给出按场景选择的 checklist。## 适用场景- 你正在写 ERC20 / 众筹 / 多签等需要入参校验、白名单判断、余额检查的合约。- 你遇到过报错信息相同但 gas 消耗不同的困惑,或合约在升级后某些 assert 莫名失效。- 你需要理解 Solidity 0.8 内置溢出检查与 require/assert 的协同关系。## 核心技术栈- Solidity ^0.8.0(内置算术溢出检查)- 编译目标:EVM(Remix / Hardhat / Foundry 均可)- 关键字节码:invalid操作码(0xFE)与REVERT指令## 完整可跑代码示例solidity// SPDX-License-Identifier: MITpragma solidity ^0.8.20;contract GuardDemo { uint256 public total = 0; address public owner; constructor() { owner = msg.sender; } // 1) require:入参/外部条件校验,最常用,退回剩余 gas function deposit(uint256 amount) external payable { require(msg.value == amount, "value mismatch"); require(amount 0, "amount must 0"); total += amount; } // 2) revert:主动回滚,可带定制错误(0.8+ 推荐用 error) error InsufficientBalance(uint256 have, uint256 need); function withdraw(uint256 amount) external { if