# Understand Solidity Storage in depth

## Introduction&#x20;

The slots in **storage** are stored as key-value pairs with a length of 256 bits (32 bytes). The default value of each slot is always 0, so we do not need to assign a value to 0 when the new declaration.

Basically, we can barely understand that variables in a contract will be stored in storage as follows:

* Storage only stores variables, not *constant*
* Each slot can store up to 256 bits (32 bytes)
* The variables in turn are in slot in the order of lower-order (ie from right to left).
* If the size of the variable exceeds the remaining size of the slot, this variable will be passed to the new slot.
* Struct creates a new slot, the struct elements are put into the slot in the same way as above.
* Fixed size array creates a new slot, struct elements are put into the slot in the same way as above.
* Dynamic size array creates a new slot, this slot only stores **the length** of the array, while the **values** in the array will be stored at other locations (we will talk more in detail later)
* Mapping always creates a new slot to hold a place, the values ​​in the array will be stored in other locations, we will talk more in detail later.
* String creates a new slot, this slot stores both data & data length, we will talk more in detail later.

Going into practice, we will see that the combination of data types becomes much more complicated.&#x20;

**You may not know:**

* All variables in the contract are stored in storage and are accessible
* Regardless of whether you have declared the variable `private`or `internal`not, it only works within the scope of the contract only, on the blockchain are all public. Of course, depending on the data type, there will be different encryption, but basically nothing is private at all.

## Fixed size variables

The fixed size variables are single variables, using the basic data types such as `uint8, uint16, uint24, uint32, uint64, uint128, uint256, bool, address`\
we have a sample contract:

```javascript
contract StorageTest {
  uint256 a;
  uint256[2] b;

  struct Entry {
    uint256 id;
    uint256 value;
  }
  Entry c;
}
```

The variables will be stored in storage as follows:

* `a`is stored in slot 0 and it occupies this slot due to the size of `a`256 bits (uint256)
* `b`occupies a new slot (slot 1) which contains 2 elements. Because the data type of b is `uint256`, each element will occupy a slot. This means that b \[0] will occupy slot 1, and b \[1] will occupy slot 2
* Struct Entry has just been declared, it does not count
* `c`will occupy a new slot (slot 3) and then put 2 elements in the struct in. Just like `b`the above, every element is `uint256`so each will occupy a slot. The result is `c.id`occupied slot 3 and `c.value`occupied slot 4

Another example:

```javascript
pragma solidity ^0.5.9;

contract StorageTest {
  uint8 public a = 7; //0
  uint16 public b =10; //0
  address public d = 0xbE03bCA4D65A86114668697867982Ecfc76f15F8; //0
  bool public bb = true; //0
  uint64 public c = 15; //0
  uint256 public e = 200; //1
  uint8 public f = 40; //2
  uint256 public g = 789; //3
}
```

In this contract the variable is not full-slot size as before, so how is it arranged in storage?&#x20;

* `a` 8 bit size, put into slot 0
* `b` 16 bit size, put into slot 0
* `d` is the address. The address has 40 hexadecimal characters, so 160 bits
* `bb` is bool type, only need 1 bit to store, but in solidity, the smallest data type is 8 bits, so bool will also occupy 8 bits; we put it into slot 0
* `c` 64 bit, we still can put it into slot 0 because (a+b+d+bb+c = 256 bit)
* `e` 256 bit, because slot 0 has been filled by (a,b,d,bb,c) with 256 bit, so e will be stored in slot 1
* `f` 8 bit, f has to be stored in slot 2 because of a full of 256 bit of `e`&#x20;
* `g` 256 bit, put in slot 3

How do we verify this? We will deploy to a testnet network (here I use Ropsten) and then get the data to try.

![](https://1935782820-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LejI2We-R9d3LmZiE0r%2F-LvnMXoG8G52FdXZPcoR%2F-LvnX5G2VSer_Ro8oWn6%2Fimage.png?alt=media\&token=4fa9d0ef-308b-4a60-9639-0c5c61a83f01)

Slot 0:

```
truffle(ropsten)> web3.eth.getStorageAt('0x9129970dce1274D3D6FB94B705F21eaAe8fABF1F', 0)
'0x000000000000000f01be03bca4d65a86114668697867982ecfc76f15f8000a07
```

So, as I've described earlier. It's stored from right to left in Hexadecimal, let's dive right into the analysis

```
0x000000000000000f01be03bca4d65a86114668697867982ecfc76f15f8000a070x000000000000000f01be03bca4d65a86114668697867982ecfc76f15f8000a07
```

`a`  is 7 = 07 (Hex to Dec)

`b` is 10 = 0a (10 hex to Dec is a)

`c` is 0xbE03bCA4D65A86114668697867982Ecfc76f15F8

`d` is True = 01

`bb` is 15 = 0f

```
truffle(ropsten)> web3.utils.fromDecimal("0xbe03bca4d65a86114668697867982ecfc76f15f800")
'0xbe03bca4d65a86114668697867982ecfc76f15f800'
```

Slot 1:

`e` 200 = c8 (Hex to Dec)

```
truffle(ropsten)> web3.eth.getStorageAt('0x9129970dce1274D3D6FB94B705F21eaAe8fABF1F', 1)
'0x00000000000000000000000000000000000000000000000000000000000000c8'
```

Slot :2

`f` 40 = 28 (Hex to Dec)

```
truffle(ropsten)> web3.eth.getStorageAt('0x9129970dce1274D3D6FB94B705F21eaAe8fABF1F', 2)
'0x0000000000000000000000000000000000000000000000000000000000000028'
```

Slot 3:

`g` 789 = 315 (Hex to Dec)

```
truffle(ropsten)> web3.eth.getStorageAt('0x9129970dce1274D3D6FB94B705F21eaAe8fABF1F', 3)
'0x0000000000000000000000000000000000000000000000000000000000000315'
```

## Dynamic Size variables

Dynamic arrays always occupies a new slot, and this slot will store the length of the array.

Assuming there is an X array, the element in the dynamic array will be stored sequentially from `keccak256(X)`, one important note X is the *string of* 64 hexa (256 bit) characters, not the uint values.

```javascript
pragma solidity ^0.5.9;

contract StorageTest {
  uint256 a;     // slot 0
  uint256[3] b;  // slots 1-2-3

  struct Entry {
    uint256 id;
    uint256 value;
  }
  
  Entry c;       // slots 4-5
  uint256[] d;
  Entry[] e;

  constructor () public {
    d.push(1);
    d.push(2);
    d.push(3);
    e.push(Entry(4, 5));
  }
}
```

Length of `d`&#x20;

```
truffle(ropsten)> web3.eth.getStorageAt("0x22a77C59ab77B431E5c7236A531D032551cc0aD5",6)
'0x0000000000000000000000000000000000000000000000000000000000000003'
```

Value of \`d\[0]\`

```
lengthof6="0x0000000000000000000000000000000000000000000000000000000000000006"
d0=web3.utils.soliditySha3(lengthof6)
'0xf652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f'
```

```
truffle(ropsten)> web3.eth.getStorageAt("0x22a77C59ab77B431E5c7236A531D032551cc0aD5",d0)
'0x0000000000000000000000000000000000000000000000000000000000000001'
```

Value of `d[1]`= d0 + 1

Convert `d0` to Decimal to make a summation operation

111414077815863400510004064629973595961579173665589224203503662149373724986687 + 1 = 111414077815863400510004064629973595961579173665589224203503662149373724986688

Decimal of `d[1]` is 111414077815863400510004064629973595961579173665589224203503662149373724986688

The address of `d[1]` should be presented in Hexadecimal

```
d1 = "0xF652222313E28459528D920B65115C16C04F3EFC82AAEDC97BE59F3F377C0D40"
```

```
truffle(ropsten)> web3.eth.getStorageAt("0x22a77C59ab77B431E5c7236A531D032551cc0aD5",d1)
'0x0000000000000000000000000000000000000000000000000000000000000002'
```

Similar to `d[2]`, d\[2] = d\[1] + 1

111414077815863400510004064629973595961579173665589224203503662149373724986688 + 1 = 111414077815863400510004064629973595961579173665589224203503662149373724986689

Decimal of `d[1]` is 111414077815863400510004064629973595961579173665589224203503662149373724986689

```
d2="0xF652222313E28459528D920B65115C16C04F3EFC82AAEDC97BE59F3F377C0D41"
```

```
truffle(ropsten)> web3.eth.getStorageAt("0x22a77C59ab77B431E5c7236A531D032551cc0aD5",d2)
'0x0000000000000000000000000000000000000000000000000000000000000003'
```

Check length of `e`

```
truffle(ropsten)> web3.eth.getStorageAt("0x22a77C59ab77B431E5c7236A531D032551cc0aD5",7)
'0x0000000000000000000000000000000000000000000000000000000000000001'
```

Value of `e[0].id`

```
truffle(ropsten)> lengthof7="0000000000000000000000000000000000000000000000000000000000000007"
'0000000000000000000000000000000000000000000000000000000000000007'
truffle(ropsten)> e0=web3.utils.soliditySha3(lengthof7)
'0xa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c688'
truffle(ropsten)> web3.eth.getStorageAt("0x22a77C59ab77B431E5c7236A531D032551cc0aD5",e0)
'0x0000000000000000000000000000000000000000000000000000000000000004'
```

Value of `e[0].value`

e\[0].value = e\[0].id + 1&#x20;

0xa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c688 + 1 = 0xA66CC928B5EDB82AF9BD49922954155AB7B0942694BEA4CE44661D9A8736C689

```
truffle(ropsten)> e1="0xA66CC928B5EDB82AF9BD49922954155AB7B0942694BEA4CE44661D9A8736C689"
'0xA66CC928B5EDB82AF9BD49922954155AB7B0942694BEA4CE44661D9A8736C689'
truffle(ropsten)> web3.eth.getStorageAt("0x22a77C59ab77B431E5c7236A531D032551cc0aD5",e1)
'0x0000000000000000000000000000000000000000000000000000000000000005'
```

Eg:

```javascript
bool public contact;
bytes32[] public codex;
```

![](https://1935782820-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LejI2We-R9d3LmZiE0r%2F-MewoTeb2kyrcepe8mL1%2F-Mewoo8bsg10883vtDs5%2FScreen%20Shot%202021-07-19%20at%2010.33.15%20AM.png?alt=media\&token=ec7770cb-ef69-4988-9851-c36d56c10bea)

## Mapping

Mapping always takes up a new slot, but this slot doesn't store any value at all!&#x20;

We have a contract which comprises the mapping `f`

```javascript
pragma solidity ^0.5.9;

contract StorageTest {
  uint256 a;     // slot 0
  uint256[2] b;  // slots 1-2

  mapping (uint256 => uint256) f; //slot 3

  constructor () public {
    f[20] = 8;
    f[567] = 133;
  }
}
```

As we can straightforwardly realize that the mapping `f` allocated in slot 3

* `f` will occupy slot 3
* `f[20]` will occupy slot `keccak256(hex(20) + hex(7))`
* `f[567]` will occupy slot `keccak256(hex(567) + hex(7))`

After an above contract deployed, we check the information of the contract as follows


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://enderspub.kubertu.com/understand-solidity-storage-in-depth.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
