Govur University Logo
--> --> --> -->
...

When a contract saves a list of complex items, how are those items put into the contract's storage memory, one after another?



When a contract stores a list of complex items, these items are placed into the contract's persistent storage, which is part of the blockchain state. This storage differs from transient memory used during function execution. Complex items typically refer to custom data structures, most commonly Solidity structs, which group multiple related variables together. A list of such items is usually managed using a dynamic array of these structs.

For a dynamic array of structs, the contract's storage operates in a specific way. First, the declaration slot of the dynamic array state variable itself holds only its current length. The actual data elements of the array, the complex items, do not start at this declaration slot. Instead, the base storage location for the array's elements is derived by calculating the Keccak256 hash of the array's declaration slot. This ensures that dynamic array contents do not conflict with other fixed-size state variables.

Each complex item, such as a struct, occupies one or more 32-byte storage slots. Within a struct, multiple smaller data types (like `uint8`, `bool`, `address`) can be packed together into a single 32-byte slot to optimize gas usage, provided they fit contiguously. However, if a struct contains larger types or enough smaller types to exceed a single slot, it will span multiple consecutive slots. For example, a struct containing a `uint256` and an `address` would occupy two 32-byte slots (one for each field) as they cannot be packed together. The fields within a struct are stored sequentially, starting from the slot allocated for that particular struct instance.

When a new complex item is added to the end of a dynamic array (for instance, using the `push` operation), the process unfolds sequentially. The contract first increments the array's length, which is stored at its declaration slot. Then, it calculates the starting storage slot for this new, incoming item. This calculation determines the next available storage location after all previously stored items in the array. It's based on the array's base element slot (derived from the Keccak256 hash) plus the cumulative size (in 32-byte slots) of all preceding items in the array. Once the starting slot for the new item is determined, each field of the new complex item is written into its respective calculated storage slot(s), sequentially occupying the necessary space. This method ensures that items are stored one after another, preserving their order and allowing for retrieval based on their array index.