You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Clarify the direction of offset in storage regions #307
The segment schema says offset: 0 means the segment "begins at the start of the specified slot", but not whether that's the most or the least significant byte.
The reference implementation (packages/pointers/src/read.ts) slices the word from byte 0, i.e. the most significant byte, and a length that runs past the slot continues into the next one, which also only makes sense that way.
Solidity's storage layout counts from the other end (packed values are "lower-order aligned"), so solc has to convert its offsets when emitting
pointers. This came up in review of that code because the schema text doesn't settle it. It would help if the description said explicitly that offset counts from the most significant byte, ideally with a packed example like a uint8 in the last byte at "offset": 31.
Of course, you can get more creative and have a generalized $difference: [$wordsize, $sum: [<offset>, .length: $this]] or whatever variation you'd like for parameterizing that. Just in case you want to preserve the presentation of solc's own internal layout logic.
What is the motivation for counting from the most significant byte though? Is it to be consistent with memory being big endian?
The problem is that counting from the least significant byte is the prevalent convention so this may be an unnecessary footgun. Fe follows Solidity's convention when specifying offsets. Vyper does not do packing at all AFAIK.
And Solidity's convention is not technically wrong. Storage is slot oriented and you can only read/write whole slots, so it does not have any inherent endianness.
What is the motivation for counting from the most significant byte though? Is it to be consistent with memory being big endian?
Not specifically, although this does help with consistency. The decision is somewhat arbitrary, but mostly it's because I was focusing on string storage semantics, which go the other direction vs. packed slots. Also, since #284, I made it so that offset/length values can extend beyond [0,255] and the format defines that to extend to the next lot naturally... by starting MSB at offset 0, it allows these semantics to work like normal left-to-right reading order.
Activity
gnidan commentedon Sep 30, 2026
Thanks for pointing this out! I'm declaring the reference implementation behavior to be the official format spec.
See #309 for some examples on how to be lazy about the disparity vs. solc in the implementation ;)
gnidan commentedon Sep 30, 2026
Now that the above is merged, see this example for a packed
address a; uint32 u;respectively at ethdebug offsets 12 and 8 and solc offsets 0 and 20:format/schemas/pointer/scheme/segment.schema.yaml
Lines 113 to 126 in 2563d18
Of course, you can get more creative and have a generalized
$difference: [$wordsize, $sum: [<offset>, .length: $this]]or whatever variation you'd like for parameterizing that. Just in case you want to preserve the presentation of solc's own internal layout logic.cameel commentedon Oct 1, 2026
What is the motivation for counting from the most significant byte though? Is it to be consistent with memory being big endian?
The problem is that counting from the least significant byte is the prevalent convention so this may be an unnecessary footgun. Fe follows Solidity's convention when specifying offsets. Vyper does not do packing at all AFAIK.
And Solidity's convention is not technically wrong. Storage is slot oriented and you can only read/write whole slots, so it does not have any inherent endianness.
gnidan commentedon Oct 1, 2026
Not specifically, although this does help with consistency. The decision is somewhat arbitrary, but mostly it's because I was focusing on
string storagesemantics, which go the other direction vs. packed slots. Also, since #284, I made it so that offset/length values can extend beyond [0,255] and the format defines that to extend to the next lot naturally... by starting MSB at offset 0, it allows these semantics to work like normal left-to-right reading order.