mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Documents storage layout of mappings and dynamic arrays.
This commit is contained in:
parent
06200b4b64
commit
c32e6f8d5f
@ -34,18 +34,20 @@ Statically-sized variables (everything except mapping and dynamically-sized arra
|
||||
|
||||
The elements of structs and arrays are stored after each other, just as if they were given explicitly.
|
||||
|
||||
Mappings and Dynamic Arrays
|
||||
===========================
|
||||
|
||||
Due to their unpredictable size, mapping and dynamically-sized array types use a Keccak-256 hash
|
||||
computation to find the starting position of the value or the array data. These starting positions are always full stack slots.
|
||||
|
||||
The mapping or the dynamic array itself
|
||||
occupies an (unfilled) slot in storage at some position ``p`` according to the above rule (or by
|
||||
recursively applying this rule for mappings to mappings or arrays of arrays). For a dynamic array, this slot stores the number of elements in the array (byte arrays and strings are an exception here, see below). For a mapping, the slot is unused (but it is needed so that two equal mappings after each other will use a different hash distribution).
|
||||
Array data is located at ``keccak256(p)`` and the value corresponding to a mapping key
|
||||
The mapping or the dynamic array itself occupies a slot in storage at some position ``p``
|
||||
according to the above rule (or by recursively applying this rule for mappings of mappings or arrays of arrays). For dynamic arrays,
|
||||
this slot stores the number of elements in the array (byte arrays and strings are an exception, see :ref:`below <bytes-and-string>`).
|
||||
For mappings, the slot is unused (but it is needed so that two equal mappings after each other will use a different
|
||||
hash distribution). Array data is located at ``keccak256(p)`` and the value corresponding to a mapping key
|
||||
``k`` is located at ``keccak256(k . p)`` where ``.`` is concatenation. If the value is again a
|
||||
non-elementary type, the positions are found by adding an offset of ``keccak256(k . p)``.
|
||||
|
||||
``bytes`` and ``string`` store their data in the same slot where also the length is stored if they are short. In particular: If the data is at most ``31`` bytes long, it is stored in the higher-order bytes (left aligned) and the lowest-order byte stores ``length * 2``. If it is longer, the main slot stores ``length * 2 + 1`` and the data is stored as usual in ``keccak256(slot)``.
|
||||
|
||||
So for the following contract snippet::
|
||||
|
||||
pragma solidity >=0.4.0 <0.6.0;
|
||||
@ -58,6 +60,21 @@ So for the following contract snippet::
|
||||
|
||||
The position of ``data[4][9].b`` is at ``keccak256(uint256(9) . keccak256(uint256(4) . uint256(1))) + 1``.
|
||||
|
||||
.. _bytes-and-string:
|
||||
|
||||
``bytes`` and ``string``
|
||||
------------------------
|
||||
|
||||
``bytes`` and ``string`` are encoded identically. For short byte arrays, they store their data in the same
|
||||
slot where the length is also stored. In particular: if the data is at most ``31`` bytes long, it is stored
|
||||
in the higher-order bytes (left aligned) and the lowest-order byte stores ``length * 2``.
|
||||
For byte arrays that store data which is ``32`` or more bytes long, the main slot stores ``length * 2 + 1`` and the data is
|
||||
stored as usual in ``keccak256(slot)``. This means that you can distinguish a short array from a long array
|
||||
by checking if the lowest bit is set: short (not set) and long (set).
|
||||
|
||||
.. note::
|
||||
Handling invalidly encoded slots is currently not supported but may be added in the future.
|
||||
|
||||
.. index: memory layout
|
||||
|
||||
****************
|
||||
|
Loading…
Reference in New Issue
Block a user