An overview of how arrays work in Solidity.
storage
, memory
, or calldata
keywords are required when declaring a new reference type variable. This keyword determines the data location where the variable is stored and how long it will persist.
storage
keyword is used to assign state variables that become a part of the blockchain as a part of the storage for your contract. These remain as assigned until modified, for the lifetime of the contract.
Storage is very expensive compared to most other environments. It costs a minimum of 20000 gas to store a value in a new storage slot, though it’s cheaper to update that value after the initial assignment (~5000+ gas).
This cost isn’t a reason to be afraid of using storage. In the long run, writing clear, maintainable, and logical code will always cost less than jumping through hoops to save gas here and there. Just be as thoughtful with storage on the EVM as you would be with computation in most other environments.
memory
keyword creates temporary variables that only exist within the scope in which they are created. Memory is less expensive than storage, although this is relative. There are often circumstances where it is cheaper to work directly in storage rather than convert to memory and back. Copying from one location to another can be quite expensive!
calldata
storage location is where function arguments are stored. It is non-modifiable and the Solidity docs recommend using it where possible to avoid unnecessary copying, because it can’t be modified. You’ll learn more about this later, but doing so can help prevent confusing bugs when calling a function from another contract that takes in values from that contract’s storage
.
- Assignments between
storage
andmemory
(or fromcalldata
) always create an independent copy.- Assignments from
memory
tomemory
only create references. This means that changes to one memory variable are also visible in all other memory variables that refer to the same data.- Assignments from
storage
to a local storage variable also only assign a reference.- All other assignments to
storage
always copy. Examples for this case are assignments to state variables or to members of local variables of storage struct type, even if the local variable itself is just a reference.
storage
are passed by reference. In other words, if you assign a storage array half a dozen names, any changes you make will always modify the original, underlying storage array.
storage
array as a function parameter, and you cannot write a function that return
s a storage
array.
Storage arrays are dynamic, unless they are declared with an explicit size. However, their functionality is limited compared to other languages. The .push(value)
function works as expected. The .pop()
function removes the last value of an array, but it does not return that value. You also may not use .pop()
with an index to remove an element from the middle of an array, or to remove more than one element.
You can use the delete
keyword with an array. Doing so on an entire array will reset the array to zero length. Calling it on an element within the array will reset that value to its default. It will not resize the array!
memory
arrays.
memory
are temporary and only exist within the scope in which they are created. Arrays in memory
are not dynamic and must be declared with a fixed size. This can be done at compile time, by declaring a size inside the []
or during runtime by using the new
keyword. Finally, memory
arrays can be implicitly cast from storage
arrays.
memory
arrays can require some gymnastics if you need to create an array where the size is not initially known. Depending on the specific needs of the problem, valid solutions for filtering an array and returning a smaller array could include:
<type>[] memory filteredArray = new <type>[](numX);
calldata
are read only. Otherwise, they function the same as any other array.
Array slices are currently only implemented for calldata
arrays.
memory
, storage
, and calldata
data locations. You’ve also learned how they apply to arrays, with each having its own properties, restrictions, and costs.