Background

During the development and testing of Datona Labs’ Solidity smart data access contract (S-DAC) templates, we often need to handle data with a small but unknown number of items, such as user IDs. Ideally, these are stored in small dynamic arrays of small values.

In the examples for this article, we investigate whether using dynamic value arrays helps us to do that more efficiently than using reference arrays or similar solutions in Solidity.


Discussion

Where we have data comprising a known small number of small numbers, we can employ a value array in Solidity, as per the article “Value Arrays in Solidity” by the author, in which we provide and measure Solidity value arrays. We concluded, amongst other things, that we can reduce my storage space and gas consumption using value arrays in many circumstances.

This conclusion was reached because Solidity runs on the Ethereum Virtual Machine (EVM) which has a very large machine word of 256bits (32bytes). This feature, combined with high gas consumption for reference array handling, encourages us to consider using value arrays.

However, if we are providing our own libraries for fixed value array manipulation, let us determine whether it is feasible to provide dynamic value arrays as well.

Let us compare dynamic value arrays with fixed value arrays and Solidity’s own fixed and dynamic arrays.

We shall also compare a struct containing a length and a fixed array, as well as a struct containing a value array.


Possible Dynamic Value Arrays

In Solidity, it is only possible to have dynamic storage arrays. Memory arrays have a fixed size and are not permitted to use push() in order to append additional elements.

Since we are providing our own code for dynamic value arrays in Solidity libraries, we can also provide push()(and pop()) to be used on both storage and memory arrays.

Dynamic value arrays will need to record and manipulate the current length of the array. In the following code, we have chosen to store the length in the top bits of the 256bit-, 32byte-machine word value.

Dynamic value arrays

These are dynamic value arrays that match some of the Solidity available types:

Dynamic Value Arrays

Type           Type Name   Description
uint128[](1)   uint128d1   one 128bit element value
uint64[](3)    uint64d3    three 64bit element values
uint32[](7)    uint32d7    seven 32bit element values
uint16[](15)   uint16d15   fifteen 16bit element values
uint8[](31)    uint8d31    thirty-one 8bit element values

We propose the Type Name as shown above, which is used throughout this article, but you may find a preferable naming convention.

We will be looking at uint8d31 in more detail, below.

More dynamic value arrays

Obviously, there more possible value arrays. Assuming that we are reserving the top bits of the 256bit value to hold the maximum dynamic array length, the number of bits in the X value multiplied by the number of Y elements must be less than or equal to 256 minus enough bits to hold the array length, L:

More Dynamic Value Arrays

Type           Type Name  Len  Description
uintX[](Y)     uintXdY     L   X * Y <= 256 - L
uint255[](1)   uint255d1   1   one 248bit element value
uint126[](2)   uint126a2   2   two 124bit element values
uint84[](3)    uint84d3    2   three 82bit element values
uint63[](4)    uint63d4    3   four 62bit element values
uint50[](5)    uint50d5    3   five 51bit element values
uint42[](6)    uint42d6    3   six 42bit element values
uint36[](7)    uint36d7    3   seven 36bit element values
uint31[](8)    uint31d8    4   eight 31bit element values
uint28[](9)    uint28d9    4   nine 28bit element values
uint25[](10)   uint25d10   4   ten 25bit element values
uint22[](11)   uint22d11   4   eleven 22bit element values
uint21[](12)   uint21d12   4   twelve 21bit element values
uint19[](13)   uint19d13   4   thirteen 19bit element values
uint18[](14)   uint18d14   4   fourteen 18bit element values
uint16[](15)   uint16d15   4   as above
uint15[](16)   uint15d16   5   sixteen 15bit element values
uint14[](17)   uint14d17   5   seventeen 14bit element values
uint13[](19)   uint13d19   5   nineteen 13bit element values
uint12[](20)   uint12d20   5   twenty 12bit element values
uint11[](22)   uint11d22   5   twenty-two 11bit element values
uint10[](25)   uint10d25   5   twenty-five 10bit element values
uint9[](27)    uint9d27    5   twenty-seven 9bit element values
uint8[](31)    uint8d31    5   as above
uint7[](35)    uint7d35    6   thirty-five 7bit element values
uint6[](41)    uint6d41    6   forty-one 6bit element values
uint5[](50)    uint5d50    6   fifty 5bit element values
uint4[](62)    uint4d62    6   sixty-two 4bit element values
uint3[](83)    uint3d83    7   eighty-three 3bit element values
uint2[](124)   uint2d124   7   one-hundred & twenty-four 2bit EVs
uint1[](248)   uint1d248   8   two-hundred & forty-eight 1bit EVs

The array type needed is project-specific. Additionally, multiple array types may be needed, for instance, uint8d31 for user IDs and uint5d50 for roles.

Note the uint1d248 value array. That allows us to efficiently encode up to 248 one-bit element values, which represent booleans, into one EVM word. Compare that with Solidity’s bool[248] which consumes 248 times as much space in memory and even eight times as much space in storage.

#ethereum #blockchain #solidity #smart-contracts #programming

Dynamic Value Arrays in Solidity
5.50 GEEK