On Uniswap V3 Pool contract, we have slot0 struct which is located on slot 0 of the storage

    struct Slot0 {
        // the current price
        uint160 sqrtPriceX96;
        // the current tick
        int24 tick;
        // the most-recently updated index of the observations array
        uint16 observationIndex;
        // the current maximum number of observations that are being stored
        uint16 observationCardinality;
        // the next maximum number of observations to store, triggered in observations.write
        uint16 observationCardinalityNext;
        // the current protocol fee as a percentage of the swap fee taken on withdrawal
        // represented as an integer denominator (1/x)%
        uint8 feeProtocol;
        // whether the pool is locked
        bool unlocked;
    /// @inheritdoc IUniswapV3PoolState
    Slot0 public override slot0;

I use web3.eth.getStorageAt(contractAddress, 0) to get the storage data, example are like this example 0x0001001c201c200eb8ff799900000000000000002dd4311936cf0097586f377c

the question is, how to decode that hex value ? tried to decode it to number which is not mean anything ..

I have read few article like this https://medium.com/@dariusdev/how-to-read-ethereum-contract-storage-44252c8af925 , but I'm stuck with finding the key of the storage, which is I don't know if that key is the correct answer for my problem ..

This is the contract that I use as my example https://arbiscan.io/address/0xb52781c275431bd48d290a4318e338fe0df89eb9#code

Also, I know about calling slot0 function on the contract to get the value. But All I want is able to decode the value on the storage ..

1 Answer 1


First of all, a struct is just the logical grouping, from the storage perspective the structs can be omitted. So just the variables/property types define how the storage is packed.

A slot occupies 32Bytes

uint160 sqrtPriceX96;              // 160/8 = 20B
int24 tick;                        // 24/8 = 3B
uint16 observationIndex;           // 2B
uint16 observationCardinality;     // 2B
uint16 observationCardinalityNext; // 2B
uint8 feeProtocol;                 // 1B
bool unlocked;                     // 1B

Altogether it requires 31 Bytes, so indeed can be packed into a single slot. The values are packed(aligned) from right to left. In hex format, a byte has 2 chars.

  • sqrtPriceX96:

  • 0x0001001c201c200eb8ff799900000000000000002dd4311936cf0097586f377c

  • sqrtPriceX96:

  • 0x0001001c201c200eb8ff799900000000000000002dd4311936cf0097586f377c

  • observationIndex:

  • 0x0001001c201c200eb8ff799900000000000000002dd4311936cf0097586f377c

  • observationCardinality:

  • 0x0001001c201c200eb8ff799900000000000000002dd4311936cf0097586f377c

  • observationCardinalityNext:

  • 0x0001001c201c200eb8ff799900000000000000002dd4311936cf0097586f377c

  • feeProtocol:

  • 0x0001001c201c200eb8ff799900000000000000002dd4311936cf0097586f377c

  • unlocked:

  • 0x0001001c201c200eb8ff799900000000000000002dd4311936cf0097586f377c

  • unused storage:

  • 0x0001001c201c200eb8ff799900000000000000002dd4311936cf0097586f377c

  • I was wrong then, I also tried to unpack the value from left to right. I read somewhere about get the storage layout from remix by compile the contract and get the offset of the slot storage. I thought the offset was left to right .. Commented Dec 6, 2023 at 12:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.