m mybian.xyz
Gas优化实战教程

Gas优化实战教程:基于真实项目的逐步降耗演练

理论之外更需要实战。本文用一个 ERC20 改造案例,演示从识别瓶颈到落地优化的完整过程,并量化每一步收益。

m
mybian.xyz 编辑部
1099 字· 约 2 分钟阅读· 2026-05-24T06:12:20.330999+00:00
Gas优化实战教程 - Gas优化实战教程:基于真实项目的逐步降耗演练
关于「Gas优化实战教程」的视觉延伸

案例背景

假设我们维护一个 ERC20 + 锁仓功能的合约,已部署在 Binance 智能链。运营反馈用户对锁仓与提取的 gas 费抱怨较多,团队决定来一次 gas 大扫除。

第一步:建立基准

使用 forge snapshot 生成现有合约的 gas 报告。锁仓函数 lock() 平均消耗 92000 gas,提取 unlock() 平均 84000 gas。把数据记录为 baseline,作为后续对比依据。

第二步:定位热点

用 forge test -vvv 跟踪一笔典型交易,发现 lock() 内部多次读取 totalLocked、totalSupply、userLocked 三个 storage 变量。每次 SLOAD 都是 2100 gas,叠加起来非常昂贵。

第三步:缓存到 memory

把三个变量在函数开头一次性加载到局部变量,所有计算用局部变量完成,最后一次性写回。改造后 lock() 降到 75000 gas,节省 18%。这是 币安 智能链上常见的优化第一刀。

第四步:合并存储槽

观察到 totalLocked 与 totalSupply 都是 uint128 足够表达的小数值。将它们打包进同一 storage slot,减少一次 SSTORE。lock() 进一步降到 68000 gas,提取也降到 71000 gas。

打包前必须更新所有读取处的逻辑,并补充单元测试。B安 智能链上不少 DeFi 协议都采用类似手法。

第五步:custom errors 替换 require

所有 require 字符串错误改为 error 定义。每条字符串错误平均节省 50 gas,全合约累计可观。custom errors 还能提升前端友好度,统一错误码。

第六步:unchecked 加速循环

用户列表更新循环中包含 i++ 自增。由于上限远小于 2^256,包装到 unchecked { ++i; } 中能省下溢出检查 gas。整体函数再降 2%-5%。

第七步:减少事件 indexed

原合约对 Lock 事件三个参数全部 indexed,但前端实际只筛选 user。改为仅 user indexed,事件 gas 下降约 800。这种细微优化是 必安 上币审核反馈中的常见项。

第八步:验证安全

所有改动后跑一遍完整测试套件,并新增针对打包变量与 unchecked 的 fuzz 测试。运行 24 小时无错误后,邀请审计师复审改动。

第九步:上线灰度

先在测试网发布,组织内部用户连续操作一周;再上主网,先开放 10% 流量,观察一天后全量切换。监控关键事件,准备好回滚脚本以防万一。

结果汇总

lock() 从 92000 降到 64000,节省 30%;unlock() 从 84000 降到 60000,节省 28%。所有改动均通过审计与回归测试。这套流程可以直接搬到你自己的项目,包括即将上线 BN 智能链的新合约。