闪学it-[全栈]程序员转型区块链技术训练营
智能合约 Gas 优化手册:把手续费砍掉一半的 12 个技巧(关注用户名)
Gas 优化不是玄学,而是对 EVM 成本模型的系统性管理。需要先说明:能否“砍掉一半”取决于合约现状、调用频率和链上环境,必须以实际测量为准。但遵循以下 12 个技巧,通常能显著降低手续费,并让合约更易维护。
1. 减少存储写入。 链上存储是最贵的操作之一。能用事件记录的历史数据,不要长期写入状态;能链下计算的派生数据,不要反复上链。每次新增或修改存储槽,都应追问是否必要。
2. 打包变量,减少槽位。 多个小类型变量若能放进同一存储槽,可减少读写次数。设计结构体时,把常用字段与小类型紧凑排列,避免因顺序不当浪费槽位。
3. 优先使用 calldata。 外部函数的只读数组、结构体参数,尽量用 calldata 避免内存拷贝。函数可见性也要准确:外部调用用 external,内部复用才用 public。
4. 缓存存储变量。 同一函数内多次读取状态变量时,先读入局部变量再使用,减少重复的存储读取。循环中尤其明显,但要注意局部变量与最终写回的一致性。
5. 避免不必要的循环。 链上循环成本随长度线性上升,动态数组遍历更危险。能用映射定位就不要遍历查找;必须循环时限制边界,并考虑批量分页。
6. 用映射替代数组扫描。 需要按标识查询时,映射通常比数组遍历更省 Gas。数组适合枚举,映射适合检索;若两者都需要,可维护索引结构,但避免每次全量扫描。
7. 使用自定义错误。 相比长字符串回滚原因,自定义错误编码更紧凑,部署和回滚成本更低。错误信息可通过工具解码,不必把长文案写进字节码。
8. 精简修饰器与检查顺序。 修饰器会展开为额外逻辑,过多嵌套增加开销。把最便宜、最可能失败的检查放在前面,利用短路逻辑尽早回滚,避免执行昂贵操作后才失败。
9. 合理使用 constant 与 immutable。 编译期常量不占存储;部署时确定的不可变量也不占运行期存储槽。把不随运行变化的配置放入二者,可减少读取成本。
10. 合并批量操作。 多次独立交易会产生重复的基础开销。对允许批量的场景,可设计批量入口,一次完成多笔更新,分摊签名、调用和存储访问成本;但要注意单笔上限与失败回滚风险。
- 采用紧凑数据结构与位图。** 布尔集合、权限标记、状态位可用位图压缩,减少槽位占用。状态机可用小整数枚举。紧凑设计要平衡可读性,避免为了省一点 Gas 引入复杂错误。
12. 把计算移到链下与二层。 能用链下签名、默克尔证明、预言机或 Layer2 完成的部分,不要全部放在主链执行。链上只做验证和最终结算,是降低用户手续费的长期方向。
最后,优化必须闭环:先用测试和 Gas 报告定位热点,再改结构,最后回归验证。不要为微小红利牺牲安全性。真正省下一半手续费的,往往不是某个奇技,而是减少存储、减少循环、减少重复读取这三件事的系统落实。
本作品采用《CC 协议》,转载必须注明作者和本文链接
关于 LearnKu
推荐文章: