fix(b20-stablecoin): hard-code decimals to 6 to eliminate zero-return window#3385
Merged
Conversation
… window (BOP-349/PSRC-27) `B20StablecoinToken::decimals()` previously delegated to the storage adapter via `TokenAccounting::decimals()`, which returns 0 for an uninitialized slot. During the factory bootstrap window -- after `set_code` installs the marker bytecode but before `initCalls` writes the token fields -- any call to `decimals()` would return 0 instead of the correct stablecoin precision of 6. Replace the storage read with a compile-time constant sourced from `B20Variant::Stablecoin::decimals()`, which already encodes the fixed 6-decimal precision used by all stablecoin tokens. This matches the protocol spec, removes a storage read from a hot path, and closes the zero-return window entirely. Add a unit test that asserts `decimals()` returns 6 regardless of the value stored in the backing accounting (0 or 18), covering both the uninitialized and post-init cases.
Collaborator
✅ Heimdall Review Status
|
Contributor
Review SummaryNo issues found. The change is correct and well-scoped. What was reviewed:
Assessment:
|
Contributor
✅ base-std fork tests: all 610 passedbase/base is fully in sync with the base-std spec. |
refcell
added a commit
that referenced
this pull request
Jun 10, 2026
refcell
added a commit
that referenced
this pull request
Jun 10, 2026
rayyan224
added a commit
that referenced
this pull request
Jun 11, 2026
…oin dispatch Remove stray <<<<<<< HEAD marker left by cherry-pick conflict resolution and restore make_token() helper and dispatch_rejects_call_with_nonzero_value test that were accidentally dropped when taking the incoming side of the #3385 conflict. Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
This was referenced Jun 11, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
BOP-342 BOP-349
Motivation
B20StablecoinToken::decimals()previously delegated to the storage adapter viaTokenAccounting::decimals(), which returns0for an uninitialized slot. During the factory bootstrap window -- afterset_codeinstalls the marker bytecode but before theinitCallschain writes the token fields -- any external call todecimals()would return0instead of the correct stablecoin precision of6. This is incorrect: stablecoin precision is a protocol-level constant, not a per-token configuration value.What changed
B20StablecoinToken's dispatch, thedecimalsselector now returnsB20Variant::Stablecoin.decimals()(always6) instead of reading from theTokenAccountingstorage adapter.decimals()returns6regardless of the value held in the backing accounting (including0, which simulates the uninitialized-slot case).What was tried / considered
The recommendation in the audit finding suggested adding a method override directly on
B20StablecoinToken. Because the dispatch layer already handles per-variant logic andB20Variant::Stablecoin.decimals()already encodes this constant (used by the factory storage when emittingB20Created), routing through that existing constant keeps the source of truth in one place and avoids adding a new method to the trait hierarchy.