Reading a Slot in Yul
Lets start with a Coding Example
contract offsetAndShifting{
uint128 public a = 22;
uint96 public b =15;
uint16 public c = 8;
uint8 public d = 1;
function readValueBySlot(uint256 slot) external view return(bytes32 uint){
assembly{
value := sload(slot)
}
}
function getOffsetOfC() external pure returns(uint256 slot, uint256 offset){
assembly{
slot := c.slot // get the Slot
offset := c.offset // get the exact position of c
}
}
function readValueOfC() external view returns(uint256 e){
assembly{
let value := sload(c.slot) // slot 0
let shifted ;= shr(mul(c.offset,8),value)
e := and(0xffff,shifted) // Masking
}
}
}
We use the
.slot
function to get the Exact slot of our valueTo find the exact position of our variable in a slot we use
.offset
function
In the above code in the readValueOfC()
function we first read the slot of c and then we shift the Pointer to the exact position of C by utilizing the shr
built-in function and Finally we use the masking technique by applying the AND gate to retrieve the Value of C .
Writing to a Slot (Bit Shifting)
function writeToC(uint16 newC) external {
assembly {
// newC = 0x000000000000000000000000000000000000000000000000000000000000000a
let slotValue := sload(C.slot)
// slotValue = 0x0001000800000000000000000000000f00000000000000000000000000000016
let clearedC := and(
slotValue,
0xffff0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff
)
// mask = 0xffff0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff
// slotValue = 0x0001000800000000000000000000000f00000000000000000000000000000016
// clearedC = 0x0001000000000000000000000000000f00000000000000000000000000000016
let shiftedNewC := shl(mul(C.offset, 8), newC)
// shiftedNewC = 0x0000000a00000000000000000000000000000000000000000000000000000000
let newSlotValue := or(shiftedNewC, clearedC)
// shiftedNewC = 0x0000000a00000000000000000000000000000000000000000000000000000000
// clearedC = 0x0001000000000000000000000000000f00000000000000000000000000000016
// newVal = 0x0001000a00000000000000000000000f00000000000000000000000000000016
sstore(C.slot, newSlotValue)
}
}
Okay writing a Slot in Yul is a bit complex , but lets break it into a step by step process
In the previous example we want to edit/write to the variable C , which is packed in the same slot with a,b and d . So how to edit it without changing or affecting a,b and d
Step 1 :
- Load the Slot value of the whole Slot of C
Step 2 :
- Perform an AND gate operation with the Slot Value with a 64-size length-ed hex-decimal string where only the number of bits utilized by the variable along with its offset position must be kept ‘0’ and all other bits shall be ‘f’ or ‘1’ , As a result the whole byte occupied by old value of c are now nullified.
Step 3
- Shift the new value on the exact offset place of c
Step 4
- Perform the OR operation between value obtained from Step 2 & 3
Step 5
- Store the value of Step 4 in the Slot C