Advance Solidity Assembly: Bit Shifting and Storage Offsets
Published: 2023-04-21 17:13:02

## **Bit Shifting Overview**

Bit shifting is an important notion in Solidity that enables for efficient binary data manipulation. In this blog post, we will look into bit shifting in Solidity and how it may be used. It can be used to transform data kinds, extract individual bits, and set specific bits. Understanding bit shifting is critical for producing efficient and optimized code.

**Bit shifting** is the process of shifting the bits of a binary number to the left or right. This procedure can be used to manipulate binary data, such as converting between data types, extracting certain bits, or setting specific bits.

We can execute bit shifting in Solidity by using the and **>>** operators. The operator shifts a number's bits to the left, whereas the **>>** operator shifts the bits to the right.

## **Packed Variables**

You will occasionally need to access or write variables while using assembly.

There is a specific instance in which numerous variables are packed.

Because the EVM has 256 bits (32bytes) slots, you can't directly access the packed variables; instead, you'll access the storage slot and find the offset of said variable.

Then, shift the bits right until you reach the offset where the variable was stored inside the slot.

If necessary, mask some bits so that it returns the expected value.

```solidity

uint128 public A = 2;
uint104 public D = 6;
uint16  public E = 4;
uint8   public G = 1;

function readBySlot(uint slot) external view returns(bytes32 value){
    assembly{
        value := sload(slot)
    }
} 
// return 0x0100040000000000000000000000000600000000000000000000000000000002

```

All of the variables are crammed into the same **32-byte slot**.Variables will always be packed from the bottom to the top.

> How can we get the value of the **variable E** ? To do so, we need to know the variable offset, which is the location of the variable in bytes from right to left.

```solidity
function offsetE() external pure returns(uint256 _off){
    assembly{
        // return 29 bytes left
        _off := E.offset
    }
}
```

Now that we have everything we require, we will begin the **shiffting** process.We need to move the E value **29 bytes** to the right in order to return it. We'll need to use **shr** to determine the number of bits to shift right. Because we have **bytes**, we must multiply that amount by **8**:

```solidity
function shiftE() external view returns(bytes32 e){
    assembly{
        let slot  := sload(E.slot)
        e := shr(mul(E.offset, 8), slot)
    }
}
```

> return **0x0000000000000000000000000000000000000000000000000000000000010004**

We're getting there; we now have **E** in the last byte, but there's something unusual going on. We still have the **G variable 1**.We shall now begin **masking**.

```solidity
function shiftE() external view returns(bytes32 e,uint256 v){
    assembly{
        let slot  := sload(E.slot)
        e := shr(mul(E.offset, 8), slot)
        v := and(0xffff,e)
    }
}
```

> return 
1:**0x0000000000000000000000000000000000000000000000000000000000010004**.
2:**4**

## Write to storage without causing any problems with the code

Because the EVM can only write in **32-byte** increments, writing can be challenging.We're going to write to a packed variable, say E, which is uint16.Let's put something in storage! Change the **E** value to **4**.

```solidity
function setE(uint16 newE)external  returns(bytes32 value,bytes32 clearedE, bytes32 newV, bytes32 shifted){
    assembly{

        value:= sload(E.slot)
        //VALUE -> 0x0100040000000000000000000000000600000000000000000000000000000002

        //WE WANT TO DELETE E
        clearedE := and(0xff0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff, value)
        //CLEARED E -> 0x0100000000000000000000000000000600000000000000000000000000000002

        shifted := shl(mul(E.offset,8),newE)
        //0x0000030000000000000000000000000000000000000000000000000000000000

        newV := or(shifted,clearedE)
        //NEW VALUE -> 0x0100030000000000000000000000000600000000000000000000000000000002
        sstore(E.slot,newV)
    }
}
```

Follow me on Twitter and wait for the next serie !!
https://twitter.com/web3_ruud

I’m on @buymeacoffee. If you like my work, you can buy me a and share your thoughts 🎉☕ https://www.buymeacoffee.com/officialsa4