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
Since we need only a single byte for the null termination, we can store strings up to 31 bytes long in a word.
Why limit strings to 31 bytes?
There is no need to force a null termination on a fixed-length data type if the string fits nicely into it. It can be safely assumed that the non-existent byte 33 is zero. The string already terminates at 32 bytes by definition — there’s no need for a redundant termination byte.
The output of formatBytes32String (v5) and encodeBytes32String (v6) always contains a null character at the last byte. This self-imposed limitation is wasteful and makes no practical sense.
Bytes32String should be able to handle 32 bytes long strings, otherwise it would be more truthful to call it Bytes31String.
If the string is exactly 32 bytes long, you can just use toUtf8Bytes, but what if the string length is variable up to 32 bytes?
Notably, the equivalent function in viem does not have this limitation and accepts 32 bytes long strings as input without issues.
Proposal: Raise the limit from 31 to 32 bytes
Additionally, decodeBytes32String behaves oddly — it searches backwards for the null terminator (assuming zero padding). This is not standard behavior in other languages, where it’s expected that the string would be cut at the first null character, not the first byte of the padding.
The term Byte32String came from the idea that it is a string that fits in Bytes32, not that the length of the string is 32 bytes. At the time it was created, there were a handful of ERC-20 contracts that used a bytes32 (and no meaningful standard) to store their symbol and name; of which no contract used a string anywhere close to that length.
Are there still contracts using this method to store strings?
One concern with this is that Solidity will currently allow a string of up to 31 bytes to fit within a single storage slot (32 bytes), so the null-termination makes it possible for any valid Bytea32String to fit in either a Solidity bytes32 or a Solidity string, consuming only 32 bytes.
Allowing a 32 byte string to be used means that a string could be selected that would require 64 bytes if stored as a Solidity string.
Not a huge issue, but I am curious as to how many contracts are still using this technique for storing strings (and I guess why? :)).
For more information on how Solidity uses a prefix byte (limiting single-slot strings to 31 bytes), here is some info on solidity string storage layout.
I'm not against making the change, I just want to make sure the motivation and consequences are discussed. :)
Ethers Version
6.13.5
Search Terms
Bytes32String
Describe the Problem
Bytes32String Unnecessary Null Termination
bytes32 string must be less than 32 bytes
From the documentation:
Why limit strings to 31 bytes?
There is no need to force a null termination on a fixed-length data type if the string fits nicely into it. It can be safely assumed that the non-existent byte 33 is zero. The string already terminates at 32 bytes by definition — there’s no need for a redundant termination byte.
The output of
formatBytes32String
(v5) andencodeBytes32String
(v6) always contains a null character at the last byte. This self-imposed limitation is wasteful and makes no practical sense.Bytes32String should be able to handle 32 bytes long strings, otherwise it would be more truthful to call it
Bytes31String
.If the string is exactly 32 bytes long, you can just use
toUtf8Bytes
, but what if the string length is variable up to 32 bytes?Notably, the equivalent function in viem does not have this limitation and accepts 32 bytes long strings as input without issues.
Proposal: Raise the limit from 31 to 32 bytes
Additionally,
decodeBytes32String
behaves oddly — it searches backwards for the null terminator (assuming zero padding). This is not standard behavior in other languages, where it’s expected that the string would be cut at the first null character, not the first byte of the padding.This would resolve:
Code Snippet
Contract ABI
Errors
Environment
No response
Environment (Other)
No response
The text was updated successfully, but these errors were encountered: