decimals || "18" appears in src/shared/transactions.js and src/shared/balances.js. Zero decimals is legal ERC-20.
Not a live bug: Blockscout sends decimals as a string, and "0" is truthy, so absent and zero stay distinct today. The defect is latent — a backend that sends numeric 0, or any change that coerces the field before it reaches this line, silently turns a 0-decimal token into an 18-decimal one. That misreports every balance and every amount for that token by a factor of 10^18, in a wallet, with no error.
Found during the coercion sweep in #244 and deliberately left out of its scope as a different field.
Implementation requirements
Distinguish absent from zero explicitly rather than relying on "0" being truthy — the current correctness depends on an upstream serialisation detail nobody controls.
Apply it at both call sites.
Check whether any other consumer of decimals makes the same assumption.
Definition of done
An explicitly-zero decimals, as both the string "0" and the number 0, yields 0 rather than 18.
An absent or null decimals still falls back to 18.
Tests cover both spellings of zero and the absent case.
TODO.md updated in the same commit.
make check passes.
`decimals || "18"` appears in `src/shared/transactions.js` and `src/shared/balances.js`. Zero decimals is legal ERC-20.
Not a live bug: Blockscout sends `decimals` as a string, and `"0"` is truthy, so absent and zero stay distinct today. The defect is latent — a backend that sends numeric `0`, or any change that coerces the field before it reaches this line, silently turns a 0-decimal token into an 18-decimal one. That misreports every balance and every amount for that token by a factor of 10^18, in a wallet, with no error.
Found during the coercion sweep in https://git.eeqj.de/sneak/AutistMask/pulls/244 and deliberately left out of its scope as a different field.
## Implementation requirements
- Distinguish absent from zero explicitly rather than relying on `"0"` being truthy — the current correctness depends on an upstream serialisation detail nobody controls.
- Apply it at both call sites.
- Check whether any other consumer of `decimals` makes the same assumption.
## Definition of done
- [ ] An explicitly-zero `decimals`, as both the string `"0"` and the number `0`, yields 0 rather than 18.
- [ ] An absent or null `decimals` still falls back to 18.
- [ ] Tests cover both spellings of zero and the absent case.
- [ ] `TODO.md` updated in the same commit.
- [ ] `make check` passes.
Closing: resolved by #349, which removed every || "18" from src/ and made the shared toDecimals() answer 0 for a real scale of zero.
model: claude-fable-5
Closing: resolved by https://git.eeqj.de/sneak/AutistMask/issues/349, which removed every `|| "18"` from `src/` and made the shared `toDecimals()` answer `0` for a real scale of zero.
model: claude-fable-5
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
decimals || "18"appears insrc/shared/transactions.jsandsrc/shared/balances.js. Zero decimals is legal ERC-20.Not a live bug: Blockscout sends
decimalsas a string, and"0"is truthy, so absent and zero stay distinct today. The defect is latent — a backend that sends numeric0, or any change that coerces the field before it reaches this line, silently turns a 0-decimal token into an 18-decimal one. That misreports every balance and every amount for that token by a factor of 10^18, in a wallet, with no error.Found during the coercion sweep in #244 and deliberately left out of its scope as a different field.
Implementation requirements
"0"being truthy — the current correctness depends on an upstream serialisation detail nobody controls.decimalsmakes the same assumption.Definition of done
decimals, as both the string"0"and the number0, yields 0 rather than 18.decimalsstill falls back to 18.TODO.mdupdated in the same commit.make checkpasses.Closing: resolved by #349, which removed every
|| "18"fromsrc/and made the sharedtoDecimals()answer0for a real scale of zero.model: claude-fable-5