Part III took us off the stack and into the world of memory.
This lesson will explore storage, and will complete the tour of the separate areas given to EVM developers.
EIP-1153 added a second type of storage called Transient Storage, and it was included in the Cancun hardfork. Transient storage is scoped to the transaction, is cleared after each transaction, and does not persist in blocks.
I wrote about using transient storage in Vyper last year. It is not required reading for this lesson, but you may find it interesting to explore transient storage from the perspective of a high level language.
The ergonomics of accessing both storage types are similar, so I will address both in this lesson instead of covering them separately. I will refer to the original storage type as simply “storage”, and will add the “transient” convention whenever referring to the post EIP-1153 type.
Storage Opcodes
Compared to the complexity of the manipulating the stack, you might find storage refreshing. There are only two opcodes — SSTORE and SLOAD — and they do exactly what you expect. SSTORE takes a 32-byte value from the stack and records it to storage at some key. SLOAD retrieves a 32-byte value from storage at some key and places it on the stack.
The equivalent transient storage opcodes — TSTORE and TLOAD — operate the same way. The differences are the durability of the values written to transient storage and the reduced gas cost.
Storage Costs
A full accounting of storage gas costs are complex and better covered by the notes below each opcode on evm.codes (SSTORE example).
The minimum gas cost for the four opcodes is 100, and EVM assigns gas costs in addition depending on the starting and ending state of that storage.
Instead of getting out the calculator, simply remember these rules of thumb:
Storing a new value at a previously empty key is very expensive (cold write)
Storing a value at the same key in the same transaction is inexpensive (warm write)
Clearing a previously-set storage value results in a gas refund
Reading a value from storage for the first time is expensive (cold read)
Reading a value from storage in the same transaction is inexpensive (warm read)
Storage gas costs can be reduced by adding an access (added in EIP-2930) list to your transaction. We cannot do anything related to access lists within the EVM, so this is an upstream topic that you should explore on the side.
Storage Layout
The storage address of any given value is relative to the global chain state. Each storage key is hashed against the contract address, which minimizes the chance of collosion. I wrote about storage keys in a lesson covering honeypot tokens:
However when we are operating at the EVM level, we are limited to only the storage exposed through a simple key-value abstraction. This hides the complexity of the storage key hashing method discussed in that other lesson.
Since EVM can only access storage as a given key, and the global indexing is hidden, this means that a contract only has access to storage slots associated with its particular address. This feature prevents other contracts from performing an uninitiated access of a particular 3rd party contract’s storage keys.
Note that a contract can allow others to access its storage keys by doing a DELEGATECALL. But that is an advanced topic that we will cover later in the series.
Keep reading with a 7-day free trial
Subscribe to Degen Code to keep reading this post and get 7 days of free access to the full post archives.