验证truffle-config.js优化选项的运行以及对Truffle v4的担忧


简介

truffle-config.js设置Truffle环境,但是您似乎可以使用在优化块中运行的规范。

这个值是多少?

从Solidity官方页面上的解释来看,以solc运行似乎如下。

1
デフォルトでは、オプティマイザは、コントラクトがそのライフタイムにわたって200回呼び出されると仮定して、コントラクトを最適化します。 イニシャルコントラクトのデプロイのガス代をより安く、その後の関数実行時のガス代をより高くしたい場合は、--optimize-runs=1 と設定してください。 多くのトランザクションを想定していて、デフォルトより高いデプロイコストとアウトプットサイズを気にしないのであれば、 --optimize-runs を大きな数に設定してください。

显然,运行设置为"如果减少该值,则部署时的天然气成本将降低,而交易的天然气成本将增加,而如果您增加该值,则当时的天然气成本将增加。部署量将增加,交易的天然气成本将减少。"

似乎在松露环境中solcjs被用作编译器,因此并不总是能够原样使用solc的功能,但这是一个试验。让我们测试一下它的效果(*这是一个测试项目)。

测试方法

为了测量气体消耗,请准备一个简单的结构,该结构具有创建一个结构并将其添加到动态数组的功能(*我借用了CryptoKitties的Kitty结构,因为这很重要)。

<详细信息> <摘要>测试代码(单击以打开/关闭)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
pragma solidity 0.5.12;

contract CompileOpt5{
  // クリプトキティの構造体を拝借
  struct Kitty {
    uint256 genes;
    uint64 birthTime;
    uint64 cooldownEndBlock;
    uint32 matronId;
    uint32 sireId;
    uint32 siringWithId;
    uint16 cooldownIndex;
    uint16 generation;
  }

  // ニャンコの配列
  Kitty[] internal kitties;

  // 要素数の取得
  function getTotalKitties() public view returns( uint256 ){
    return kitties.length;
  }

  // ニャンコの追加
  function createKitty( uint256 _val256 ) public{
    Kitty memory _kitty = Kitty({
      genes: _val256,
      birthTime: uint64(_val256),
      cooldownEndBlock: uint64(_val256),
      matronId: uint32(_val256),
      sireId: uint32(_val256),
      siringWithId: uint32(_val256),
      cooldownIndex: uint16(_val256),
      generation: uint16(_val256)
    });

    kitties.push( _kitty );
  }
}

上面的代码是用运行[1],[200]和[2000]的值编译的,并使用了部署时的耗气量和访问该函数时的耗气量。顺便说一下,让我们也测试禁用优化的状态。

已通过Truffle v5.1.2(solc-js v0.5.12)

测试

我部署了每个合同,并尝试访问createKitty函数超过200次(*我认为如果超出运行指定的事务数量,则成本会增加,因此我进行了大量测试)。
结果,在所有合同中,仅第一笔交易的汽油消耗量较低,并且从第二笔交易开始获得了统一的消耗量。

?经过优化(游程= 1)
部署期间的耗气量:187,711
初始耗气量:45,551
第二次起的耗气量:68,963

<详细信息>

truffle-config.js(单击以打开和关闭)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
module.exports = {
  // ? 省略 ?

  // 最適化有り:runs=1
  compilers: {
    solc: {
      version: "0.5.12",
      parser: "solcjs",
      settings: {
        optimizer: {
          enabled: true,
          runs: 1
        }
      }
    }
  }
}

?经过优化(游程= 200)
部署期间的气体消耗:190,327
初始耗气量:45,503
第二次起的耗气量:68,915

<详细信息>

truffle-config.js(单击以打开和关闭)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
module.exports = {
  // ? 省略 ?

  // 最適化有り:runs=200(デフォルト値)
  compilers: {
    solc: {
      version: "0.5.12",
      parser: "solcjs",
      settings: {
        optimizer: {
          enabled: true,
          runs: 200
        }
      }
    }
  }
}

?经过优化(游程= 2000)
部署期间的耗气量:245,294
初始耗气量:45,419
第二次起的耗气量:68,831

<详细信息>

truffle-config.js(单击以打开和关闭)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
module.exports = {
  // ? 省略 ?

  // 最適化有り:runs=2000
  compilers: {
    solc: {
      version: "0.5.12",
      parser: "solcjs",
      settings: {
        optimizer: {
          enabled: true,
          runs: 2000
        }
      }
    }
  }
}

?没有优化
部署期间的耗气量:220,118
初始气体消耗:55,710
第二次起的耗气量:79,122

<详细信息>

truffle-config.js(单击以打开和关闭)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
module.exports = {
  // ? 省略 ?

  // 最適化無し
  compilers: {
    solc: {
      version: "0.5.12",
      parser: "solcjs",
      settings: {
        optimizer: {
          enabled: false
        }
      }
    }
  }
}

顺便说一下,比较每个值,似乎运行次数越小,部署时的气体消耗越低。
另一方面,由于运行值引起的交易成本波动微不足道。与默认运行= 200相比,运行= 1(应牺牲交易)和运行= 2000(应优先考虑)之间没有明显差异。

而且,与未进行优化的状态相比,第二次及后续交易的耗气量减少了约13%。

摘要

truffle-config.js中运行的值似乎无关紧要。看起来,仅通过暂时对其进行优化就可以在某种程度上减少气体消耗,除非您在DApp发布时忘记对其进行优化,否则似乎没有问题。

松露v4中的优化如何?

好吧,从某种意义上讲,主要主题可能来自这里。
优化规范在Truffle v4环境中是否运作良好?

我的印象是,许多与松露相关的信息,尤其是书籍,都涉及v4内容。此外,松露控制台的可用性在v4和v5之间已发生了很大变化,因此我认为有很多人敢于继续使用v4环境。这是个好主意,所以让我们用v4进行测试。

使用Truffle v4.1.15(solcjs v0.4.25)

测试

为v4准备一个具有调整后名称和编译器版本的合同,然后开始测试。

<详细信息> <摘要>测试代码(单击以打开/关闭)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
pragma solidity 0.4.25;

contract CompileOpt4{
  // クリプトキティの構造体を拝借
  struct Kitty {
    uint256 genes;
    uint64 birthTime;
    uint64 cooldownEndBlock;
    uint32 matronId;
    uint32 sireId;
    uint32 siringWithId;
    uint16 cooldownIndex;
    uint16 generation;
  }

  // ニャンコの配列
  Kitty[] internal kitties;

  // 要素数の取得
  function getTotalKitties() public view returns( uint256 ){
    return kitties.length;
  }

  // ニャンコの追加
  function createKitty( uint256 _val256 ) public{
    Kitty memory _kitty = Kitty({
      genes: _val256,
      birthTime: uint64(_val256),
      cooldownEndBlock: uint64(_val256),
      matronId: uint32(_val256),
      sireId: uint32(_val256),
      siringWithId: uint32(_val256),
      cooldownIndex: uint16(_val256),
      generation: uint16(_val256)
    });

    kitties.push( _kitty );
  }
}

?经过优化(游程= 1)
部署期间的气体消耗:225,602
初始耗气量:55,701
第二次起的耗气量:79,113

<详细信息>

truffle-config.js(单击以打开和关闭)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
module.exports = {
  // ? 省略 ?

  // 最適化有り:runs=1
  compilers: {
    solc: {
      version: "0.4.25",
      parser: "solcjs",
      settings: {
        optimizer: {
          enabled: true,
          runs: 1
        }
      }
    }
  }
}

?经过优化(游程= 200)
部署期间的气体消耗:225,602
初始耗气量:55,701
第二次起的耗气量:79,113

<详细信息>

truffle-config.js(单击以打开和关闭)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
module.exports = {
  // ? 省略 ?

  // 最適化有り:runs=200(デフォルト値)
  compilers: {
    solc: {
      version: "0.4.25",
      parser: "solcjs",
      settings: {
        optimizer: {
          enabled: true,
          runs: 200
        }
      }
    }
  }
}

?经过优化(游程= 2000)
部署期间的气体消耗:225,602
初始耗气量:55,701
第二次起的耗气量:79,113

<详细信息>

truffle-config.js(单击以打开和关闭)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
module.exports = {
  // ? 省略 ?

  // 最適化有り:runs=2000
  compilers: {
    solc: {
      version: "0.4.25",
      parser: "solcjs",
      settings: {
        optimizer: {
          enabled: true,
          runs: 2000
        }
      }
    }
  }
}

?没有优化
部署期间的气体消耗:225,602
初始耗气量:55,701
第二次起的耗气量:79,113

<详细信息>

truffle-config.js(单击以打开和关闭)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
module.exports = {
  // ? 省略 ?

  // 最適化無し
  compilers: {
    solc: {
      version: "0.4.25",
      parser: "solcjs",
      settings: {
        optimizer: {
          enabled: false
        }
      }
    }
  }
}

在所有设置中,耗气量完全相同...

起初,我以为我在编译规范中犯了一个错误,但是当我使用Etherscan查看字节码时,每个合约的二进制级别都有细微的差异。如果Etherscan显示相同的二进制数据,则应将其视为重复合同,因此,当可以单独显示合同时,毫无疑问合同之间存在差异。

但是,当我尝试在Etherscan上注册验证码时,除非它是" Optimization Enabled:No",否则它将不被接受。

总之,即使由于优化设置而导致二进制数据存在差异,也似乎无法在Etherscan上识别优化。

最大的问题是,无论优化与否,所有合同的燃气消耗都是相同的。

我希望这个结果是由于我的环境或过程中的错误所致,但是如果Truffle v4环境没有在合同中反映优化规范,那将是一个糟糕的情况。

如果您正在使用Truffle v4并考虑到Dapp版本,我们建议您尽快测试优化以查看其是否在您的环境中有效。在发布之前仔细考虑一下情况是令人恐惧的:"优化不起作用!?"