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

By [0xCQHG](https://paragraph.com/@0xcqhg) · 2023-04-23

---

> 前置知识：Solidity、Solc、Remix、Ethers.js、Javascript/Typescript
> 
> 前置条件：Solidity >=0.8.10

当我们希望了解[EVM智能合约存储分布](https://mirror.xyz/dashboard/edit/Yij1y3hYHROo55hj9GYw8GXa_DqoHYId36HMAsGdpG8)时，有三种方法可以获得智能合约状态变量的存储信息。

### 1.Remix

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

首先编写一个测试合约：

    // SPDX-License-Identifier: MIT
    pragma solidity >=0.8.10;
    
    contract Storage {
        uint8 a ;
    
        constructor() {
            a = 1;
        }
    }
    

![Remix页面结构](https://storage.googleapis.com/papyrus_images/1eb37430698505e0ff7c52cac1184a6e0480535a7a05469f7d98bdfe985c4108.png)

Remix页面结构

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

![控制台输出](https://storage.googleapis.com/papyrus_images/7982ba11b0246e3b1dbcf6c26646555a6e5a8f554a72fb447cd14f029412c124.png)

控制台输出

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

![调试器页面](https://storage.googleapis.com/papyrus_images/f45b8cc41f236b2bd8a2109acab4758b54e1adad7048fec28bca5d1fa91916ff.png)

调试器页面

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

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

![Storage](https://storage.googleapis.com/papyrus_images/fc96a48522511ee25d8a49cd4d66200953df3d73f26c54b5d8a30e47fc5b9eb4.png)

Storage

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

![合约状态变量分布](https://storage.googleapis.com/papyrus_images/aae4a7ea32f4eb2f9ee5e07b6b68d553c8cac18357696bb84af3997fcf16b2bf.png)

合约状态变量分布

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

### 2.Solc

另外我们可以通过Solidity编译器查看状态变量的分布。

首先需要[安装Solc](https://docs.soliditylang.org/en/latest/installing-solidity.html#macos-packages)（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个槽位，你可以根据自己的需求查看任意地址的任意槽位的值。

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

如何本文有任何错误，或者你有什么疑问需要咨询，欢迎[联系我](https://linktr.ee/cqhg)。

---

*Originally published on [0xCQHG](https://paragraph.com/@0xcqhg/bI9pineK2bddVv3PFiGl)*
