You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何移除构造函数中的SLOAD操作可大幅节省Gas?附实测数据

合约部署Gas消耗差异的原因

我将构造函数中引用的状态变量改为直接传入数值常量,测试了合约部署时的Gas消耗差异:

  • 部署BeforeDemo合约消耗93915 Gas
  • 部署AfterDemo合约消耗76288 Gas
  • 两者差值达17627

原以为差异仅来自一次SLOAD操作,但单次SLOAD的Gas成本远低于此,请问造成如此大差值的原因是什么?

测试代码

contract BeforeDemo {
    uint256 public constant INITIAL_SUPPLY = 10000 * (10 ** 18);

    constructor() {
        check(INITIAL_SUPPLY);
    }

    function check(uint256 supply) public {

    }
}

contract AfterDemo {
    constructor() {
        check(10000 * (10 ** 18));
    }

    function check(uint256 supply) public {

    }
}

原因分析

这俩合约的Gas差异根本不是来自SLOAD——你搞错了,public constant变量并不会触发运行时的SLOAD操作,真正的差异来自以下两点:

  • 自动生成的Getter函数成本:BeforeDemo里的INITIAL_SUPPLY是public修饰的常量,编译器会自动生成一个同名的public getter函数,这个函数的字节码会被加入到合约的运行时代码中。部署合约时,运行时代码的每字节需要消耗200 Gas,这部分额外的字节码带来了不小的Gas开销。而AfterDemo没有这个常量定义,自然也不会生成多余的getter函数。
  • 常量值的存储成本:INITIAL_SUPPLY的数值会被嵌入到合约字节码的只读区域(包括getter函数的逻辑里),部署时写入这部分数据到链上需要消耗Gas——每存储一个非零字节是68 Gas,零字节是4 Gas,这个32字节的数值会产生对应的存储成本。而AfterDemo里的数值只是作为构造函数调用的参数,直接嵌入构造函数的字节码中,不需要额外在运行时代码里存储这个值,也不会因为getter函数重复嵌入数值。

把这两部分成本加起来,就解释了为什么Gas差值远大于单次SLOAD的成本(当前SLOAD的Gas成本仅800左右,和17k的差值完全不是一个量级)。

内容的提问来源于stack exchange,提问作者Zoey

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 19:25:27