DEV Community

Ruud Christopher Saimplice
Ruud Christopher Saimplice

Posted on • Updated on

Advance Solidity Assembly: Storage Slots Part 2

Arrays with Fixed Sized

In Solidity, fixed-size arrays are stored in memory as contiguous blocks of memory. Each element in the array is stored in the next available memory slot, starting from the base memory address of the array.

uint256[3] public fixedArray = [1,2,3];

function fixedArraySlot() external pure returns(uint256 _slot){
   assembly{
     //return 0
     _slot:= fixedArray.slot
   }
} 

Enter fullscreen mode Exit fullscreen mode

To read a specific element of a fixed-size array in Solidity, you need to calculate the memory location of the element by adding the memory slot of the start of the array to the index of the element you want to access. This calculation is necessary because fixed-size arrays in Solidity are stored in contiguous blocks of memory, with each element occupying a fixed amount of space. By adding the appropriate offset to the start of the array, you can find the memory location of the element you want to read or modify.

function fixedArrayView(uint256 index) external view returns(uint256 _value){
   assembly{
     _value:= sload(add(fixedArray.slot,index))
   }
} 
Enter fullscreen mode Exit fullscreen mode

Arrays with No-Fixed Size

To obtain the length of a dynamic array in Solidity, you need to access the slot in memory where the length of the array is stored.

uint256[]  public bigArray   = [14,1,9];
bigArray.slot // return 3
Enter fullscreen mode Exit fullscreen mode

The keccak256 function is used to generate a unique identifier for the storage slot where the dynamic array is stored. This identifier, represented as a bytes32 value, is then used to determine the precise location of the array within the storage space. By using this identifier to calculate the location of the array in storage, you can access its elements or modify its contents using Solidity assembly code.

function readBigArray(uint index)  external view returns(uint256 _data,bytes32 location){

    uint256 _slot ;

    assembly {
        _slot:= bigArray.slot
    }

    //hash of the slot give us the location
    location = keccak256(abi.encode(_slot));

    assembly {
        _data:= sload(add(location,index))
    }
}
Enter fullscreen mode Exit fullscreen mode

Small Arrays !! It's the same process

uint8[]  public smallArray = [1,5,4,7];

function readSmallArrayLocation(uint256 index) external view returns (bytes32 ret) {
    uint256 slot;
    assembly {
        slot := smallArray.slot
    }
    bytes32 location = keccak256(abi.encode(slot));

    assembly {
        ret := sload(add(location, index))
    }
}
Enter fullscreen mode Exit fullscreen mode

Mapping

When a mapping is declared, Solidity reserves a space in storage to store the mapping data. The location of this space is determined by a unique identifier generated by the keccak256 function, which is concatenated with the key of the storage slot and the slot.

function getMapping(uint256 key) external view returns (uint256 ret) {

    uint256 slot;
    assembly {
        slot := myMapping.slot
    }

    bytes32 location = keccak256(abi.encode(key, uint256(slot)));

    assembly {
        ret := sload(location)
    }
}
Enter fullscreen mode Exit fullscreen mode

Follow me on Twitter !! 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

Top comments (0)