Fix BooleanCoder.decode to error on non-zero padding and invalid boolean values #5001
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
During fuzzing, I discovered that bug. Ethers.js currently decodes a bool by treating any non-zero 32-byte word as true, but go-ethereum’s readBool requires the first 31 bytes to be zero and the final byte to be exactly
0x00
or0x01
, throwing an error otherwise. This mismatch can lead to silent misinterpretation of invalid boolean data, cross-client inconsistencies, and hidden bugs, so we must enforce strict padding and value checks inBooleanCoder.decode
.Go Bool type - Go-Ethereum
Go-Ethereum
In the Ethereum ABI, the
bool
type is encoded as a 32-byte word, similar touint256
, and the value is restricted to 0 or 1. The decoder in geth enforces this strictly. The upper 31 bytes must all be 0, and the last byte must be either0x00
or0x01
.If any of the first 31 bytes is non-zero, or the last byte is not 0 or 1, Go will return an error called
💡errBadBool
.Ex)
0x000...002
→ If the last byte is0x02
, it returnserrBadBool
JS - ethers.js
readValue()
directly returns aBigInt
.!!BigInt(0)
→false
,!!BigInt(nonzero)
→true
This treats any non-zero 32-byte word as true.
It ignores the standard ABI requirement that the first 31 bytes must be zero and the last byte must be exactly 0x00 or 0x01.
Solution
Changes
Update
packages/abi/src/coders/boolean.ts
!!reader.readValue()
with explicit padding + value checks.Add unit tests for:
0x02
) → throws “Boolean value error”0x00
→false
,0x01
→true
)This ensures ethers.js boolean decoding is fully compliant with the Ethereum ABI spec and consistent with Go-Ethereum’s implementation.