> For the complete documentation index, see [llms.txt](https://intrinsic-1.gitbook.io/untitled/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://intrinsic-1.gitbook.io/untitled/axiom-architecture/verifying-storage-proofs/how-do-i-find-storage-slots.md).

# How do I find storage slots?

Translating account storage from Solidity to the EVM

Storage variables for contracts written in higher level languages like Solidity, Vyper, or even Yul are stored in **slots**.  Slots are keys in account storage, which is a  `uint256 => uint256` mapping, and their mapping to variables in higher level languages is determined by the language compiler.  Here we explain how to find this mapping in Solidity.

### Storage Variable Layout

The rules for laying out storage are summarized in the [Solidity documentation](https://docs.soliditylang.org/en/v0.8.17/internals/layout_in_storage.html). For a particular smart contract, the storage layout can be found by using the [`storageLayout`](https://docs.soliditylang.org/en/v0.8.17/using-the-compiler.html) option in `solc`. To summarize:

* Slots have size 32 bytes.
* Multiple variables can be stored in a single slot, in which case they are concatenated (without RLP, in **right-to-left** order).
* New variables are aligned to the start of a slot.
* `mappings`, `string`, and dynamic array are considered to occupy 32 bytes. If they are in slot `p`, then:
  * For dynamic arrays:
    * Slot `p` stores the length.
    * Array data is stored starting at `keccak256(p)` sequentially, sharing slots if elements are at most 16 bytes.
    * Nested arrays apply this recursively.
  * For mappings:
    * Slot `p` is empty.
    * The value of key `k` starts at `keccak256(h(k) || p)`, where:
      * `h(k)` pads `k` to 32 bytes if `k` is a value type
      * `h(k)` is the unpadded `keccak256` hash for strings or byte arrays
  * For bytes/string (`string` is viewed as `bytes1[]`):
    * If length is 32 or more bytes, slot `p` stores `length * 2 + 1` and data is in `keccak256(p)`.
    * If length is at most 31 bytes, the lowest order byte stores `length * 2` and the highest order bytes store the raw data.

We give a worked example for the CryptoPunks smart contract.

* Contract is at: <https://etherscan.io/address/0xb47e3cd837ddf8e4c57f05d70ab865de6e193bbb#code>
* The state variables start with:
  * string public imageHash = "ac39af4793119ee46bbff351d8cb6b5f23da60222126add4268e261199a2921b";
  * address owner;
  * string public standard = 'CryptoPunks';
  * string public name;
  * string public symbol;
  * uint8 public decimals;
  * uint256 public totalSupply;
  * uint public nextPunkIndexToAssign = 0;
  * bool public allPunksAssigned = false;
  * uint public punksRemainingToAssign = 0;
  * mapping (uint => address) public punkIndexToAddress;
  * mapping (address => uint256) public balanceOf;

| Variable               | type                         | size (bytes) | slot | data slot                        |
| ---------------------- | ---------------------------- | ------------ | ---- | -------------------------------- |
| imageHash              | string                       | 32           | 0    | `keccak(0)..`                    |
| owner                  | address                      | 20           | 1    |                                  |
| standard               | string                       | 32           | 2    |                                  |
| name                   | string                       | 32           | 3    |                                  |
| symbol                 | string                       | 32           | 4    |                                  |
| decimals               | uint8                        | 1            | 5    |                                  |
| totalSupply            | uint256                      | 32           | 6    |                                  |
| nextPunkIndexToAssign  | uint                         | 32           | 7    |                                  |
| allPunksAssigned       | bool                         | 1/8          | 8    |                                  |
| punksRemainingToAssign | uint                         | 32           | 9    |                                  |
| punkIndexToAddress     | mapping (uint => address)    | 32           | 10   | `keccak(index . 10)..`           |
| balanceOf              | mapping (address => uint256) | 32           | 11   | \`keccak(address . 0..0 . 11) .. |
