Storage
Storage Basics
.slot- returns the slot location (in uint256) that the variable is located in. Determined at compile-time and doesn’t changesstorehas no consideration for existing variables already declared or stored in the contract, so using it may override values that are already there
contract YulStorage {
uint x = 2; // slot 0
uint y = 5; // slot 1
uint z = 10; // slot 2
function getXYul() external view returns (uint256 ret) {
assembly {
ret := sload(x.slot)
}
}
function getVarYul(uint256 slot) external view returns (bytes32 ret) {
assembly {
ret := sload(slot)
}
}
// risky, shouldn't be used unless you know what you're doing
function setVarYul(uint256 slot, uint256 value) external {
assembly {
sstore(slot, value)
}
}
} Storage Offsets & Bitshifting
Multiple variables can be stored within a slot
Calling readBySlot returns the below bytes32 data, where all variables C to F are stored in slot 0:
To derive the specific values with Yul, we have to use the
.offsethelper.offsetis the number of bytes to the left in a bytes32 object that we have to look in order to find the location of the variable we want
To obtain the value of E:
shr(x, y)- shift value y right by x number of bits
andis a bitwise operation that compares values bit by bit1 and 0 returns 0
0 and F returns 0
0 and 8 returns 8 → we get
E = 8
In order to write to specific values in a slot (while not overriding all the values in the slot), we need to use bit masking & bit shifting
first load the slot that contains E
selectively delete the bytes that represent E by using bitwise
andto conduct maskingshift the new E value by 28 bytes and conduct bitwise
orto combine the E value and current slot values togethercall
sstoreto set the new value into the storage slot
Storage of Arrays & Mappings
For fixed arrays, essentially the same as declaring 3
uint256variables that will take up slots 0, 1 and 2.
For dynamic arrays, the data that’s being stored in the storage slot is the length of the array.
Items in a dynamic array will not be stored sequentially down the slots, like in a fixed array, because the array could overrun and clash with other variables in the following slots
Solidity stores values of dynamic arrays by taking the
keccak256hash of the array’s length, then adding the index of the value to the hash
For mappings, Solidity takes the hash of the mapping’s storage slot, and concatenates it with the mapping key, then stores the value in the corresponding slot location
Nested mappings: hashes of hashes
Keys have to be hashed in order of operation
Last updated