|
| 1 | +.. index:: ! custom storage layout, ! storage layout specifier, ! layout at, ! base slot |
| 2 | + |
| 3 | +.. _custom_storage-layout: |
| 4 | + |
| 5 | +********************* |
| 6 | +Custom Storage Layout |
| 7 | +********************* |
| 8 | + |
| 9 | +Contracts can define an arbitrary base slot for its own storage. |
| 10 | +The contract's state variables, including those inherited from base contracts, |
| 11 | +will be stored from the specified slot instead of the default slot zero. |
| 12 | + |
| 13 | +.. code-block:: solidity |
| 14 | +
|
| 15 | + // SPDX-License-Identifier: GPL-3.0 |
| 16 | + pragma solidity ^0.8.29; |
| 17 | +
|
| 18 | + contract C layout at 0xABCD + 0x1234 { } |
| 19 | +
|
| 20 | +As the previous example shows, this can be done by using ``layout at <base-slot-expression>`` |
| 21 | +in the header of a contract definition. |
| 22 | + |
| 23 | +The layout specifier can be placed either before or after the inheritance specifier, and at most once. |
| 24 | +The ``base-slot-expression`` must be an :ref:`integer literal<rational_literals>` expression |
| 25 | +that can be evaluated at compile time and yield a value in the range of ``uint256``. |
| 26 | + |
| 27 | +In the case of a custom storage layout specification which places the contract near the storage end, |
| 28 | +the number of slots available for static objects is determined by ``max storage size - base slot`` and |
| 29 | +the compiler can detect whether the contract extends past the end. |
| 30 | +For dynamic typed variables, they are allocated in random locations of the storage, including those before |
| 31 | +the layout base slot. |
| 32 | +It is also important to mention that, in cases where the contract is near the end of storage, there are |
| 33 | +risks related to upgradeability and inline assembly access beyond allocated space. |
| 34 | + |
| 35 | +The location of a contract's state variable is determined by its position in the hierarchy tree. |
| 36 | +Inherited variables will be stored before the state variables declared by the contract itself and |
| 37 | +that changes the slots where they should be placed. |
| 38 | +Similarly, when a contract specifies a custom storage layout, not only its own storage variables are shifted, |
| 39 | +but also all other variables from contracts in the same inheritance tree. |
| 40 | +Thus, the storage layout can only be specified at the top most contract of the inheritance tree, assuring |
| 41 | +that all contracts of the tree have their layout base properly adjusted. |
| 42 | + |
| 43 | +The storage layout cannot be specified for abstract contracts, interfaces and libraries. |
| 44 | +Also, it is important to note that it does **not** affect transient state variables. |
| 45 | + |
| 46 | +Further details are explained later when :ref:`layout of storage variables<storage-inplace-encoding>` are described. |
| 47 | + |
| 48 | +.. warning:: |
| 49 | + The identifiers ``layout`` and ``at`` are not reserved keywords of the Solidity language, but |
| 50 | + it is strongly recommended to avoid using them since that may change in the future. |
0 commit comments