0

For optimal storage optimization, it is ideal to put smaller data types together.

For example do:

uint128 x;
unit 128 y;
unit 256 z;

Instead of:

uint128 x;
unit 256 z;
unit 128 y;

But how do mappings work in storage? How much storage does one mapping take? And how does it work when we add new records into it? And how to properly optimize them?

1 Answer 1

1

Based on the documentation, mappings and dynamic arrays cannot be stored in between regular state variables, due to their unpredictable size.

So, they are assigned a 32 bytes slot in the place they are declared. For arrays, the size of the array is placed in this slot. For mapping, the slot stays empty but its position is needed to ensure if other mapping are placed one next to the other, their elements would be placed in different slots.

The storage is like an array where each slot is of 32 bytes (256 bits) and with a size of 2**256 (about 115792089237316195423570985008687907853269984665640564039457584007913129639936). So, it's huge, you can fit a lot of 32 bytes data there.

So, to calculate where the element of an array will be put, the keccak256 hash of the array index in the storage concatenated with the element index will be used. This will provide a 256 bit hash that will be the starting index of the array data in storage. Arrays can be optimized with their elements types. Check this article, in the "Reference Type storage layout" section.

For a mapping, the index of one of its elements is calculated with the keccak256 hash of its key concatenated with the mapping index in the storage (the mapping index in storage is used to differentiate it from another mapping with exactly the same key/value type that may be placed close to it, since the keccak256 hash will be totally different with this data).

So, coming back to your question, there is not much we can do to optimize a mapping. So don't worry too much about that. A mapping can take as many elements as the storage size allows it to have.

Check the documentation for this concept: https://docs.soliditylang.org/en/v0.8.7/internals/layout_in_storage.html#mappings-and-dynamic-arrays

2
  • 1
    Thank you. Based on what you wrote, it doesn't really make any sense to for example use mapping (uint32 => uint32) instead of mapping (uint => uint) correct?
    – David
    Aug 7, 2022 at 10:45
  • Exactly, because each element will kind of be placed in a "random" location, due to the keccak256 hash, and the probability of 2 or more different elements sharing the same slot is really small. But, anyways, try to use the correct type for your use case. If you know that you need a number type that will never be greater than a uint32, then use a uint32 type, and so on. Aug 7, 2022 at 16:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.