Skip to content

fix(security): bound vault and asset decimals to MAX_DECIMALS (closes #84)#233

Open
thedavidmeister wants to merge 7 commits into
mainfrom
issue-84-decimals-bound
Open

fix(security): bound vault and asset decimals to MAX_DECIMALS (closes #84)#233
thedavidmeister wants to merge 7 commits into
mainfrom
issue-84-decimals-bound

Conversation

@thedavidmeister

@thedavidmeister thedavidmeister commented Jun 28, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Adds uint8 constant MAX_DECIMALS = 36 and error UnsupportedDecimals(address token, uint8 decimals) to LibERC4626.sol at file scope.
  • _decode() now reverts with UnsupportedDecimals if vault.decimals() or asset.decimals() exceeds MAX_DECIMALS, closing the griefing vector where a malicious vault could supply an arbitrarily large decimals value to cause toFixedDecimalLossless to overflow uint256 on any non-trivial Float input.
  • Regenerates src/generated/ERC4626Words.pointers.sol with updated BYTECODE_HASH.
  • Adds four mutation-validated tests (testShareDecimalsAboveMaxRevertsConvertToAssets, testShareDecimalsAboveMaxRevertsConvertToShares, testAssetDecimalsAboveMaxRevertsConvertToAssets, testAssetDecimalsAboveMaxRevertsConvertToShares) — each asserts the exact UnsupportedDecimals selector and address; removing either guard causes the corresponding expectRevert to fail.

Closes #84

Test plan

  • forge test — 127 tests passed, 0 failed, 0 skipped.
  • Mutation-validated: removing either decimals guard breaks the corresponding 2 tests.
  • forge fmt — no changes.
  • Pointers regenerated; testBytecodeHashMatchesDeployedCode passes.

Co-Authored-By: Claude noreply@anthropic.com

Summary by CodeRabbit

  • Bug Fixes

    • Added a safeguard that rejects vaults or underlying assets reporting unusually high decimal counts.
    • Conversion flows now fail clearly when unsupported decimals are detected, helping prevent incorrect share/asset calculations.
  • Tests

    • Expanded coverage for conversion failures when either the vault or asset exceeds the supported decimal limit.

…ent overflow DoS

Adds MAX_DECIMALS=36 constant and UnsupportedDecimals error to LibERC4626.
_decode() now reverts if vault.decimals() or asset.decimals() exceeds the
bound, closing the griefing vector where a malicious vault could trigger
toFixedDecimalLossless overflow via an arbitrarily large decimals value.
Regenerates ERC4626Words.pointers.sol with updated BYTECODE_HASH.
Adds four mutation-validated tests for both conversion paths.

Closes #84

Co-Authored-By: Claude <noreply@anthropic.com>
@thedavidmeister thedavidmeister self-assigned this Jun 28, 2026
@coderabbitai

coderabbitai Bot commented Jun 28, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@thedavidmeister, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 46 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 211956ac-5abf-4a02-af89-f4c18f18c6ec

📥 Commits

Reviewing files that changed from the base of the PR and between 5b7ef4f and e22105d.

⛔ Files ignored due to path filters (1)
  • src/generated/ERC4626Words.pointers.sol is excluded by !**/generated/**
📒 Files selected for processing (2)
  • src/lib/erc4626/LibERC4626.sol
  • test/src/lib/erc4626/LibERC4626.t.sol

Walkthrough

LibERC4626 adds a MAX_DECIMALS constant (36) and an UnsupportedDecimals(address, uint8) error. The _decode function now checks both vault.decimals() and asset.decimals() against this bound, reverting if either exceeds it. Four new tests cover these revert paths using MaliciousERC4626 and MockERC20 with decimals set to 255.

Changes

Decimals upper-bound enforcement

Layer / File(s) Summary
MAX_DECIMALS constant, error, and _decode validation
src/lib/erc4626/LibERC4626.sol
Adds uint8 constant MAX_DECIMALS = 36 and error UnsupportedDecimals(address token, uint8 decimals). Updates _decode to validate both shareDecimals and assetDecimals against MAX_DECIMALS, reverting with UnsupportedDecimals if either exceeds the bound. Introduces assetAddr as an intermediate variable before the asset decimals call.
Revert tests for excess share and asset decimals
test/src/lib/erc4626/LibERC4626.t.sol
Imports MaliciousERC4626. Adds testShareDecimalsAboveMaxRevertsConvertToAssets, testShareDecimalsAboveMaxRevertsConvertToShares, testAssetDecimalsAboveMaxRevertsConvertToAssets, and testAssetDecimalsAboveMaxRevertsConvertToShares, each asserting UnsupportedDecimals(address, 255) reverts.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: bounding vault and asset decimals with a security fix.
Linked Issues check ✅ Passed The PR bounds both vault and asset decimals, adds the structured revert, and tests 255-value failures for both paths.
Out of Scope Changes check ✅ Passed The visible changes stay focused on ERC4626 decimal bounds and tests, with no unrelated edits in reviewable files.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch issue-84-decimals-bound

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Vault- and asset-reported decimals trusted unbounded for conversion precision (griefing / silent mis-scaling)

1 participant