前置知识:Solidity、Solc、Remix、Ethers.js、Javascript/Typescript
前置条件:Solidity >=0.8.10
当我们希望了解EVM智能合约存储分布时,有三种方法可以获得智能合约状态变量的存储信息。
Remix功能强大,操作简便,我们可以使用Debug功能查看。
首先编写一个测试合约:
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.10;
contract Storage {
uint8 a ;
constructor() {
a = 1;
}
}

之后我们点击部署按钮,控制台会输出成功部署合约的信息。

这时我们点击控制台右下角的调试按钮,Remix左侧会弹出合约调试器的界面。

看到这个页面之后,请用鼠标点击被圈出的按钮,该按钮会直接获得合约最后的运行状态。便于查看合约最后的存储情况。
点击之后让我们下翻调试器页面,会有一个Storage [Completely Loaded]的框体。

有了他我们便可以快速查询合约中状态变量的存储分布情况。

图中的key为变量a的槽位,value为a的值。
另外我们可以通过Solidity编译器查看状态变量的分布。
首先需要安装Solc(solcjs无法使用该功能,请安装solc)
安装完成后,进入合约文件所在目录,输入shell命令
solc --storage-layout storage.sol
加上的--storage-layout可以输出合约内变量分布的json信息。
solc --storage-layout contracts/storage.sol
======= contracts/storage.sol:Storage =======
Contract Storage Layout:
{"storage":[{"astId":3,"contract":"contracts/storage.sol:Storage","label":"a","offset":0,"slot":"0","type":"t_uint8"}],"types":{"t_uint8":{"encoding":"inplace","label":"uint8","numberOfBytes":"1"}}}
其中的slot便是变量的槽位。
使用node.js的ethers.js库也可以查看状态变量的分布,但相对来说比较繁琐。
首先使用npm/yarn安装ethers.js库
yarn add ethers
编写脚本文件inspect_storage.js
const { ethers } = require('ethers');
const provider = new ethers.providers.JsonRpcProvider("https://mainnet.infura.io/v3/xxxxxxxxxxxx")
const main = async () => {
const slot0 = await provider.getStorageAt("0xdAC17F958D2ee523a2206206994597C13D831ec7", 0)
console.log(`slot0 value: ${slot0}`);
}
main()
运行脚本inspect_storage.js输出:
slot0 value: 0x000000000000000000000000c6cde7c39eb2f0f0095f41570af89efc2c1ea828
provider有个getStorageAt方法,第一个参数为已经部署的合约的地址,第二个参数为槽位数。代码中我们查看了该地址的第0x0个槽位,你可以根据自己的需求查看任意地址的任意槽位的值。
以上便是查看智能合约中状态变量的分布的三种方法。
如何本文有任何错误,或者你有什么疑问需要咨询,欢迎联系我。

