Skip to content

Commit e633eb4

Browse files
committed
fixup! Storage layout specifier docs
1 parent 3d09047 commit e633eb4

File tree

1 file changed

+49
-31
lines changed

1 file changed

+49
-31
lines changed

docs/internals/layout_in_storage.rst

Lines changed: 49 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -52,73 +52,91 @@ the value specified by ``C``.
5252
pragma solidity ^0.8.29;
5353
5454
struct S {
55-
int32 a;
56-
bool b;
55+
int32 x;
56+
bool y;
5757
}
5858
5959
contract A {
60-
uint x;
61-
uint transient y;
62-
uint constant w = 10;
63-
uint immutable z = 12;
60+
uint a;
61+
uint128 transient b;
62+
uint constant c = 10;
63+
uint immutable d = 12;
6464
}
6565
6666
contract B {
67-
uint16 i;
68-
uint16 j;
67+
uint8[] e;
68+
mapping(uint => S) f;
69+
uint16 g;
70+
uint16 h;
71+
bytes16 transient i;
6972
S s;
7073
int8 k;
7174
}
7275
7376
contract C is A, B layout at 42 {
74-
uint8[10] register;
75-
bool flag;
77+
bytes21 l;
78+
uint8[10] m;
79+
bytes5[8] n;
80+
bytes5 o;
7681
}
7782
7883
In the example, the storage layout starts with the inherited
79-
state variable ``x`` stored directly inside the base slot (slot ``42``).
84+
state variable ``a`` stored directly inside the base slot (slot ``42``).
8085
Transient, constant and immutable variables are stored in separate
81-
locations and, thus, ``y``, ``w`` and ``z`` have no effect on the storage layout.
82-
The next two variables, ``i`` and ``j``, need 2 bytes each and can be packed together into
83-
slot ``43``, at offsets ``0`` and ``2`` respectively.
86+
locations, and thus, ``b``, ``i``, ``c`` and ``d`` have no effect on the storage layout.
87+
Then we get to the dynamic array ``e`` and mapping ``f``.
88+
They both reserve a whole slot whose address will be used to :ref:`calculate<storage-hashed-encoding>`
89+
the location where their data is actually stored.
90+
The slot cannot be shared with any other variable, because the resulting addresses must be unique.
91+
The next two variables, ``g`` and ``h``, need 2 bytes each and can be packed together into
92+
slot ``45``, at offsets ``0`` and ``2`` respectively.
8493
Since ``s`` is a struct, its two members are packed contiguously, each taking up 5 bytes.
85-
Even though they both would still fit in slot ``43``, structs and arrays always start a new slot.
86-
Therefore, ``s`` is placed in slot ``44`` and the next variable, ``k``, in slot ``45``.
87-
Then, variable ``register`` which is an array of 10 items, gets into slot ``46`` and takes up 80 bytes.
88-
Finally, variable ``flag`` ends up in slot ``47``, because,
89-
as explained before, variables after structs and arrays always start a new slot.
94+
Even though they both would still fit in slot ``45``, structs and arrays always start a new slot.
95+
Therefore, ``s`` is placed in slot ``46`` and the next variable, ``k``, in slot ``47``.
96+
Base contracts, on the other hand, can share slots with derived ones, so ``l`` does not require an new one.
97+
Then variable ``m``, which is an array of 10 items, gets into slot ``48`` and takes up 10 bytes.
98+
``n`` is an array as well, but due to the size of its items, cannot fill its first slot perfectly
99+
and spills over to the next one.
100+
Finally, variable ``o`` ends up in slot ``51``, even though it is of the same type as items of ``n``.
101+
As explained before, variables after structs and arrays always start a new slot.
90102

91-
Overall the storage and transient storage layouts of contract ``C`` can be illustrated as follows:
103+
Putting it all together, the storage and transient storage layouts of contract ``C`` can be illustrated as follows:
92104

93105
- Storage:
94106
::
95107

96-
42 [xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx]
97-
43 [ jjii]
98-
44 [ baaaa]
99-
45 [ k]
100-
46 [ rrrrrrrrrr]
101-
47 [ f]
108+
42 [aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]
109+
43 [eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee]
110+
44 [ffffffffffffffffffffffffffffffff]
111+
45 [ hhgg]
112+
46 [ yxxxx]
113+
47 [ lllllllllllllllllllllk]
114+
48 [ mmmmmmmmmm]
115+
49 [ nnnnnnnnnnnnnnnnnnnnnnnnnnnnnn]
116+
50 [ nnnnnnnnnn]
117+
51 [ ooooo]
102118

103119
- Transient storage:
104120
::
105121

106-
00 [yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy]
122+
00 [iiiiiiiiiiiiiiiibbbbbbbbbbbbbbbb]
107123

108124
Note that the storage specifier affects ``A`` and ``B`` only as a part of ``C``'s inheritance hierarchy.
109125
When deployed independently, their storage starts at ``0``:
110126

111127
- Storage layout of ``A``:
112128
::
113129

114-
00 [xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx]
130+
00 [aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]
115131

116132
- Storage layout of ``B``:
117133
::
118134

119-
00 [ jjii]
120-
01 [ baaaa]
121-
02 [ k]
135+
00 [eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee]
136+
01 [ffffffffffffffffffffffffffffffff]
137+
02 [ hhgg]
138+
03 [ yxxxx]
139+
04 [ k]
122140

123141
.. warning::
124142
When using elements that are smaller than 32 bytes, your contract's gas usage may be higher.

0 commit comments

Comments
 (0)