2.Metadata
当 Solidity 为要部署的智能合约生成字节码时,它会在字节码末尾附加有关编译的元数据。我们将检查该字节码中包含的数据。
Simple Example
//SPDX-License-Identifier: MIT
pragma solidity 0.8.20;
contract Empty {
constructor() payable {}
}
该合约什么都没有,但是当我们编译一下,我们可以看到:
6080604052603e80600f5f395ff3fe60806040525f80fdfea26469706673582212203082dbb4f4db7e5d53b235f44d3e38f839dc82075e2cda9df05b88e6585bca8164736f6c63430008140033
默认情况下,solidity 编译器会在“实际”initcode 的末尾附加元数据,当构造函数完成执行时,这些元数据会存储到区块链中。这是下面的“额外”代码:
fea26469706673582212203082dbb4f4db7e5d53b235f44d3e38f839dc82075e2cda9df05b88e6585bca8164736f6c63430008140033
最后两个字节0033的意思是“向后看0x33字节,那就是元数据”。这是指前导 fe(无效操作码)和结尾 0033 之间的所有代码。我们可以检查这确实是 0x33 字节。
Metadata为了什么
此元数据额外增加了 53 个字节的部署成本,这意味着额外的 10,600 个 Gas(每个字节码 200 个 Gas)+ 调用数据成本(每个非零字节 16 个 Gas,每个零字节 4 个 Gas)。这意味着 calldata 成本增加了 848 额外的 Gas。
So why include it? 那么为什么要包括它呢?
这使得智能合约代码能够得到严格验证。编译器输出的元数据 JSON 包括源代码的哈希值。因此,如果源代码发生一点变化,元数据 JSON 文件就会发生变化,其 IPFS 哈希也会发生变化。