docs/book/src/blockchain-development/storage.md
When developing a smart contract, you will typically need some sort of persistent storage. In this case, persistent storage, often just called storage in this context, is a place where you can store values that are persisted inside the contract itself. This is in contrast to a regular value in memory, which disappears after the contract exits.
Put in conventional programming terms, contract storage is like saving data to a hard drive. That data is saved even after the program that saved it exits. That data is persistent. Using memory is like declaring a variable in a program: it exists for the duration of the program and is non-persistent.
Some basic use cases of storage include declaring an owner address for a contract and saving balances in a wallet.
<!-- storage:example:end -->storage KeywordDeclaring variables in storage requires a storage block that contains a list of all your variables, their types, and their initial values. The initial value can be any expression that can be evaluated to a constant during compilation, as follows:
{{#include ../../../../examples/basic_storage_variables/src/main.sw:basic_storage_declaration}}
To write into a storage variable, you need to use the storage keyword as follows:
{{#include ../../../../examples/basic_storage_variables/src/main.sw:basic_storage_write}}
To read a storage variable, you also need to use the storage keyword. You may use read() or try_read(), however we recommend using try_read() for additional safety.
{{#include ../../../../examples/basic_storage_variables/src/main.sw:basic_storage_read}}
To store a struct in storage, each variable must be assigned in the storage block. This can be either my assigning the fields individually or using a public constructor that can be evaluated to a constant during compilation.
{{#include ../../../../examples/struct_storage_variables/src/main.sw:struct_storage_declaration}}
You may write to both fields of a struct and the entire struct as follows:
{{#include ../../../../examples/struct_storage_variables/src/main.sw:struct_storage_write}}
The same applies to reading structs from storage, where both the individual and struct as a whole may be read as follows:
{{#include ../../../../examples/struct_storage_variables/src/main.sw:struct_storage_read}}
We support the following common storage collections:
StorageMap<K, V>StorageVec<T>StorageBytesStorageStringPlease note that these types are not initialized during compilation. This means that if you try to access a key from a storage map before the storage has been set, for example, the call will revert.
Declaring these variables in storage requires a storage block as follows:
{{#include ../../../../examples/advanced_storage_variables/src/main.sw:advanced_storage_declaration}}
StorageMaps<K, V>Generic storage maps are available in the standard library as StorageMap<K, V> which have to be defined inside a storage block and allow you to call insert() and get() to insert values at specific keys and get those values respectively. Refer to Storage Maps for more information about StorageMap<K, V>.
Warning While the StorageMap<K, V> is currently included in the prelude, to use it the Hash trait must still be imported. This is a known issue and will be resolved.
{{#include ../../../../examples/advanced_storage_variables/src/main.sw:temp_hash_import}}
To write to a storage map, call either the insert() or try_insert() functions as follows:
{{#include ../../../../examples/advanced_storage_variables/src/main.sw:map_storage_write}}
The following demonstrates how to read from a storage map:
{{#include ../../../../examples/advanced_storage_variables/src/main.sw:map_storage_read}}
StorageVec<T>Generic storage vectors are available in the standard library as StorageVec<T> which have to be defined inside a storage block and allow you to call push() and pop() to push and pop values from a vector respectively. Refer to Storage Vector for more information about StorageVec<T>.
The following demonstrates how to import StorageVec<T>:
{{#include ../../../../examples/advanced_storage_variables/src/main.sw:storage_vec_import}}
NOTE: When importing the
StorageVec<T>, please be sure to use the glob operator:use std::storage::storage_vec::*.
The following demonstrates how to write to a StorageVec<T>:
{{#include ../../../../examples/advanced_storage_variables/src/main.sw:vec_storage_write}}
The following demonstrates how to read from a StorageVec<T>:
{{#include ../../../../examples/advanced_storage_variables/src/main.sw:vec_storage_read}}
StorageBytesStorage of Bytes is available in the standard library as StorageBytes which have to be defined inside a storage block. StorageBytes cannot be manipulated in the same way a StorageVec<T> or StorageMap<K, V> can but stores bytes more efficiently thus reducing gas. Only the entirety of a Bytes may be read/written to storage. This means any changes would require loading the entire Bytes to the heap, making changes, and then storing it once again. If frequent changes are needed, a StorageVec<u8> is recommended.
The following demonstrates how to import StorageBytes:
{{#include ../../../../examples/advanced_storage_variables/src/main.sw:storage_bytes_import}}
NOTE: When importing the
StorageBytes, please be sure to use the glob operator:use std::storage::storage_bytes::*.
The following demonstrates how to write to a StorageBytes:
{{#include ../../../../examples/advanced_storage_variables/src/main.sw:bytes_storage_write}}
The following demonstrates how to read from a StorageBytes:
{{#include ../../../../examples/advanced_storage_variables/src/main.sw:bytes_storage_read}}
StorageStringStorage of String is available in the standard library as StorageString which have to be defined inside a storage block. StorageString cannot be manipulated in the same way a StorageVec<T> or StorageMap<K, V>. Only the entirety of a String may be read/written to storage.
The following demonstrates how to import StorageString:
{{#include ../../../../examples/advanced_storage_variables/src/main.sw:storage_string_import}}
NOTE: When importing the
StorageString, please be sure to use the glob operator:use std::storage::storage_string::*.
The following demonstrates how to write to a StorageString:
{{#include ../../../../examples/advanced_storage_variables/src/main.sw:string_storage_write}}
The following demonstrates how to read from a StorageString:
{{#include ../../../../examples/advanced_storage_variables/src/main.sw:string_storage_read}}
For more advanced storage techniques please refer to the Advanced Storage page.