Storage object JSON interface

Hi there, on PG 168, 3.14.2 JSON Output section about storage layout of a contract, the sample given has “slot” and “offset” fields, however, I checked local folders from Hardhat and found no JSON files containing such information. I am wondering where I can find the standard JSON interface? Thanks.
image

You need to specifically request this output with storageLayout in outputSelection in Standard JSON. Apparently Hardhat does not need it so it does not request it. The description of Standard JSON input is here: Input Description.

Example

Input:

{
    "language": "Solidity",
    "sources": {
        "contract.sol": {
            "content": "contract C {uint a; address b;}"
        }
    },
    "settings": {"outputSelection": {"*": { "*": ["storageLayout"]}}}
}

Output:

{
  "contracts": {
    "contract.sol": {
      "C": {
        "storageLayout": {
          "storage": [
            {
              "astId": 2,
              "contract": "contract.sol:C",
              "label": "a",
              "offset": 0,
              "slot": "0",
              "type": "t_uint256"
            },
            {
              "astId": 4,
              "contract": "contract.sol:C",
              "label": "b",
              "offset": 0,
              "slot": "1",
              "type": "t_address"
            }
          ],
          "types": {
            "t_address": {
              "encoding": "inplace",
              "label": "address",
              "numberOfBytes": "20"
            },
            "t_uint256": {
              "encoding": "inplace",
              "label": "uint256",
              "numberOfBytes": "32"
            }
          }
        }
      }
    }
  },
  "errors": [
    {
      "component": "general",
      "errorCode": "1878",
      "formattedMessage": "Warning: SPDX license identifier not provided in source file. Before publishing, consider adding a comment containing \"SPDX-License-Identifier: <SPDX-License>\" to each source file. Use \"SPDX-License-Identifier: UNLICENSED\" for non-open-source code. Please see https://spdx.org for more information.\n--> contract.sol\n\n",
      "message": "SPDX license identifier not provided in source file. Before publishing, consider adding a comment containing \"SPDX-License-Identifier: <SPDX-License>\" to each source file. Use \"SPDX-License-Identifier: UNLICENSED\" for non-open-source code. Please see https://spdx.org for more information.",
      "severity": "warning",
      "sourceLocation": {
        "end": -1,
        "file": "contract.sol",
        "start": -1
      },
      "type": "Warning"
    },
    {
      "component": "general",
      "errorCode": "3420",
      "formattedMessage": "Warning: Source file does not specify required compiler version! Consider adding \"pragma solidity ^0.8.6;\"\n--> contract.sol\n\n",
      "message": "Source file does not specify required compiler version! Consider adding \"pragma solidity ^0.8.6;\"",
      "severity": "warning",
      "sourceLocation": {
        "end": -1,
        "file": "contract.sol",
        "start": -1
      },
      "type": "Warning"
    }
  ],
  "sources": {
    "contract.sol": {
      "id": 0
    }
  }
}

@cameel Thanks for this. I’m just wondering if there could be more specification on how this works.

On the command line, I’ll need to run this command, right?

solc --standard-json setting.json

What is in setting.json then? Is the following script sufficient to produce the storage layout?

{
    "language": "Solidity",
    "sources": {
        "ComplicatedContract.sol"
    },
    "settings": {"outputSelection": {"*": { "*": ["storageLayout"]}}}
}

Also running

solc --standard-json setting.json
solcjs --standard-json setting.json

produces different results.

Besides, I never made this “standard” approach work. Is this expired?

solc --storage-layout Contract.sol

Many thanks.

On the command line, I’ll need to run this command, right?

Yes.

Is the following script sufficient to produce the storage layout?

You’re missing the content key under sources. But that requires the full text of the contract and I see you’re trying to use a path instead. For that use urls, e.g. "sources": {"ComplicatedContract.sol": {"urls": ["ComplicatedContract.sol"]}}.

Also running (…) produces different results.

Does it still produce different results with a valid input file?

Besides, I never made this “standard” approach work. Is this expired?

It works for me. Maybe you’re giving it a more complicated path, e.g. with ../ segments or something? The compiler has to normalize paths you give it on the CLI to make them match the way you might import the same file and that can get complicated. To avoid having to deal with that make sure you are compiling a file that’s inside your project dir (i.e. --base-path), which is the current working directory by default.

1 Like

Thanks for the detailed answer. I think more details are still needed.

For a project with a structure like this, where should I put the setting.json file?

├───artifacts
├───cache
├───contracts
│   ├───Contract.sol
├───deploy
├───node_modules
│   ├───@nomiclabs
│   ├───@openzeppelin
│   ├───ethers
│   ├───solc
├───scripts
├───test

Also when I run solc --storage-layout Contract.sol, I’m getting this line at the top of returned messages:

solc --storage-layout Contract.sol
Warning: 'storage-layout' is not in the list of known options, but still passed to Electron/Chromium.

Similarly,

solc --standard-json .\contracts\settings.json
Warning: 'standard-json' is not in the list of known options, but still passed to Electron/Chromium.

I’m really interested in getting a clear understanding on the storage layout to have a clear understanding on the proxy logic upgradeable pattern. Many thanks again.

For a project with a structure like this, where should I put the setting.json file?

Ah, looks like you’re confusing two things: Standard JSON input and framework settings.

You need to pass StandardJSON input to the compiler when you invoke it. Either via standard input or by giving the compiler --standard-json <path> option. There’s no standard location or file name for StandardJSON input because the compiler is agnostic to your project structure and does not even necessarily assume that a filesystem exists at all (when using it via solc-js).

The file structure you’re showing looks like a Hardhat or Truffle project. When you’re using the compiler through a framework, it’s the framework that creates StandardJSON input based on various things and passes it to the compiler. You interact only with the framework. For example the settings key is usually something you can specify directly in the framework’s config file. sources on the other hand is filled out by the framework based on the files you have under contracts/ and what dependencies you have.

As for outputs, that’s also under framework’s control. Usually you’ll find all or parts of the StandardJSON output in the “artifacts” that might be under artifacts/ or build/. The storage layout will be there only if the framework requests it though. Not sure if Hardhat does it by default but it seems to have a plugin for doing that (hardhat-storage-layout).

Also when I run solc --storage-layout Contract.sol, I’m getting this line at the top of returned messages:

From the error message it looks like the solc binary on your system is not the compiler binary. It’s apparently some Electron thing? A broken wrapper script? Try checking what it actually is:

type solc

You should get something like this:

solc is hashed (/usr/bin/solc)

Whatever it is, I’d recommend uninstalling it and getting one of the official binaries from solc-bin.

1 Like

how to get solidity state variable storage layout in solc which version is blew 0.5, for example, how to get weth’s storage layout

You’d have to use a separate tool or calculate that yourself based on variable sizes.

Check if maybe ethers.js or one of the available debuggers can give you that info. Unfortunately the compiler at that version did not have that feature.