0

In the following code the 3 declared variables will be packed and stored in one slot together.

When the slot 0 zero is accessed to get the value we get an encoded value, like here we get 0x000000000000000000001f0190416e8285169f15346fcf9e336b6e1443b8c30a

What should we do so that we can deocode the returned data into 3 seperate readable values?

contract Storage {
    // slot 0
    address private owner = msg.sender; // 20 bytes
    bool private isTrue = true;  // 1 byte
    uint16 private u16 = 31;  // 2 bytes
}

1 Answer 1

0

The rules on storage slot packing can be found in the Solidity documentation ("Layout of State Variables in Storage"):

Multiple, contiguous items that need less than 32 bytes are packed into a single storage slot if possible, according to the following rules:

  • The first item in a storage slot is stored lower-order aligned.
  • Value types use only as many bytes as are necessary to store them.
  • If a value type does not fit the remaining part of a storage slot, it is stored in the next storage slot.
  • Structs and array data always start a new slot and their items are packed tightly according to these rules.
  • Items following struct or array data always start a new storage slot.

"Lower-order aligned" means the first variable (owner) will be the right-most value in the storage slot, and each subsequent variable is filled from right to left.

The rest of the rules should be self-explanatory.

Visualization of the storage slot:

0x 000000000000000000 001f 01 90416e8285169f15346fcf9e336b6e1443b8c30a
  └─────────┬────────┴──┬─┴┬─┴──────────────────┬─────────────────────┘
       empty padding    │  └isTrue            owner
                        └u16

To decode the data, cast the hexadecimal value from the appropriate place in the storage slot to the desired type. For example, in JavaScript:

const value = '0x000000000000000000001f0190416e8285169f15346fcf9e336b6e1443b8c30a';

const owner = `0x${value.substring(26)}`; // '0x90416e8285169f15346fcf9e336b6e1443b8c30a'
const isTrue = Boolean(Number(value.substring(24, 26))); // true
const u16 = parseInt(value.substring(20, 24), 16); // 31
1
  • Thanks for the answer bro! That was very informative and on-point, exactly what I wanted to know Commented Feb 20 at 4:59

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.