Cover photo

如何查看智能合约中状态变量的分布

前置知识:Solidity、Solc、Remix、Ethers.js、Javascript/Typescript

前置条件:Solidity >=0.8.10

当我们希望了解EVM智能合约存储分布时,有三种方法可以获得智能合约状态变量的存储信息。

1.Remix

Remix功能强大,操作简便,我们可以使用Debug功能查看。

首先编写一个测试合约:

// SPDX-License-Identifier: MIT
pragma solidity >=0.8.10;

contract Storage {
    uint8 a ;

    constructor() {
        a = 1;
    }
}
Remix页面结构
Remix页面结构

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

控制台输出
控制台输出

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

调试器页面
调试器页面

看到这个页面之后,请用鼠标点击被圈出的按钮,该按钮会直接获得合约最后的运行状态。便于查看合约最后的存储情况。

点击之后让我们下翻调试器页面,会有一个Storage [Completely Loaded]的框体。

Storage
Storage

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

合约状态变量分布
合约状态变量分布

图中的key为变量a的槽位,value为a的值。

2.Solc

另外我们可以通过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便是变量的槽位。

3.Ethers.js

使用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个槽位,你可以根据自己的需求查看任意地址的任意槽位的值。

以上便是查看智能合约中状态变量的分布的三种方法。

如何本文有任何错误,或者你有什么疑问需要咨询,欢迎联系我