Skip to content

Conversation

DeVikingMark
Copy link

Summary

Fixes arithmetic overflow vulnerability in VestingWallet.vestedAmount() that could brick the contract when balance + released exceeds type(uint256).max.

Changes

  • Add overflow protection in vestedAmount() functions for both ETH and ERC20 tokens
  • Cap total allocation at type(uint256).max when overflow would occur
  • Fix multiplication overflow in _vestingSchedule() with alternative calculation method
  • Handle edge case where timeElapsed = 0 to prevent division by zero

Fixes #5793

@DeVikingMark DeVikingMark requested a review from a team as a code owner September 20, 2025 22:35
Copy link

changeset-bot bot commented Sep 20, 2025

⚠️ No Changeset found

Latest commit: 9058959

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

Copy link

coderabbitai bot commented Sep 22, 2025

Walkthrough

  • Updated VestingWallet.sol to use saturating addition when computing total vested base amounts:
    • ETH: address(this).balance saturatingAdd released()
    • ERC20: IERC20(token).balanceOf(address(this)) saturatingAdd released(token)
  • Replaced linear vesting math (totalAllocation * (timestamp - start()) / duration()) with mulDiv(totalAllocation, timestamp - start(), duration()).
  • Changes applied to both ETH and token vesting calculations.
  • Aims to prevent overflows from aggregate inbound transfers exceeding type(uint256).max, as described in linked issue VestingWallet bricked if aggregate of transfers in exceed type(uint256).max #5793.

Pre-merge checks and finishing touches

✅ Passed checks (5 passed)
Check name Status Explanation
Linked Issues Check ✅ Passed The changes in the summary—replacing unsafe addition with a saturating add/cap at type(uint256).max and switching to a mulDiv-based vesting calculation to avoid multiplication overflow—directly address the bricking scenario described in issue #5793 by preventing balance+released overflow and fixing vesting math. These code-level fixes target the exact failure mode reproduced in the issue and therefore satisfy the primary coding objectives.
Out of Scope Changes Check ✅ Passed All modifications described in the raw summary are limited to VestingWallet's vestedAmount and vesting calculation and align with the linked issue's scope; there is no indication of unrelated files or functionality being changed. The changes appear focused and in-scope.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
Title Check ✅ Passed The title succinctly and accurately captures the primary change: preventing VestingWallet from becoming unusable due to a uint256 overflow in vestedAmount. It is specific, directly related to the changeset, and concise enough for teammates scanning the history.
Description Check ✅ Passed The description clearly explains the intent and the concrete changes: adding overflow protection for ETH and ERC20 vestedAmount calculations, capping total allocation, switching the vesting arithmetic to a safer method, handling timeElapsed == 0, and referencing the related issue; these points align with the raw_summary and PR objectives.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Tip

👮 Agentic pre-merge checks are now available in preview!

Pro plan users can now enable pre-merge checks in their settings to enforce checklists before merging PRs.

  • Built-in checks – Quickly apply ready-made checks to enforce title conventions, require pull request descriptions that follow templates, validate linked issues for compliance, and more.
  • Custom agentic checks – Define your own rules using CodeRabbit’s advanced agentic capabilities to enforce organization-specific policies and workflows. For example, you can instruct CodeRabbit’s agent to verify that API documentation is updated whenever API schema files are modified in a PR. Note: Upto 5 custom checks are currently allowed during the preview period. Pricing for this feature will be announced in a few weeks.

Please see the documentation for more information.

Example:

reviews:
  pre_merge_checks:
    custom_checks:
      - name: "Undocumented Breaking Changes"
        mode: "warning"
        instructions: |
          Pass/fail criteria: All breaking changes to public APIs, CLI flags, environment variables, configuration keys, database schemas, or HTTP/GraphQL endpoints must be documented in the "Breaking Change" section of the PR description and in CHANGELOG.md. Exclude purely internal or private changes (e.g., code not exported from package entry points or explicitly marked as internal).

Please share your feedback with us on this Discord post.


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 and usage tips.

@ernestognw ernestognw changed the title fix: prevent VestingWallet bricking from uint256 overflow in vestedAmount Prevent VestingWallet bricking from uint256 overflow in vestedAmount Sep 24, 2025
@ernestognw
Copy link
Member

The only downside of this change is that it makes the release function slightly more expensive (< 100 gas) on average. The previous version was audited and the risk of overflow was not considered realistic, so this would punish users without a clear reason

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

Successfully merging this pull request may close these issues.

VestingWallet bricked if aggregate of transfers in exceed type(uint256).max
3 participants