feat(lint): detect balance reentrancy - #15769
Merged
mablr merged 11 commits intoJul 22, 2026
Merged
Conversation
Extend the existing reentrancy analysis to track locals derived from address(this).balance and report reentrant calls followed by stale balance guards. Register the high-severity lint and add documentation plus focused true- and false-path UI coverage.
Track native self-balance values across casts, tuples, helper boundaries, operand ordering, and loop control flow. Resolve external calls semantically while preserving view, static, storage, and stipend-capped exclusions.
mattsse
requested review from
0xrusowsky,
DaniPopes,
figtracer,
grandizzy,
mablr and
stevencartavia
as code owners
July 15, 2026 15:23
This was referenced Jul 15, 2026
mattsse
marked this pull request as draft
July 15, 2026 16:10
mattsse
marked this pull request as ready for review
July 15, 2026 16:52
94 tasks
figtracer
reviewed
Jul 15, 2026
mablr
reviewed
Jul 15, 2026
Require fresh and stale balances on opposite comparison operands, model standard state-lock guards across effective entry points, restore bounded recursive entry analysis, and account for value-call gas stipends.
mablr
reviewed
Jul 16, 2026
Carry stale-balance comparison and boolean path provenance through helper returns, compound assignments, and control-flow joins. This avoids false positives on complementary conditions without hiding reachable callback paths.
mablr
reviewed
Jul 16, 2026
Preserve address(this) provenance through locals, tuples, helper and modifier parameters, and branch-correlated call paths. Invalidate aliases on observable writes and assembly reassignment.
mablr
reviewed
Jul 17, 2026
Propagate path constraints and self-address provenance through short-circuit expressions and helper returns so balance reentrancy diagnostics follow feasible paths.
mablr
self-requested a review
July 17, 2026 15:48
mablr
reviewed
Jul 17, 2026
Track internal function-pointer targets through assignments and control-flow joins so helper callbacks remain visible to the balance analysis. Recognize standard lock modifiers whose sole placeholder is nested in an unconditional block. Amp-Thread-ID: https://ampcode.com/threads/T-019f896c-fd1a-745b-be37-de6016df1dbb Co-authored-by: Amp <amp@ampcode.com>
mablr
enabled auto-merge (squash)
July 22, 2026 11:54
figtracer
reviewed
Jul 22, 2026
Include statements before a nested modifier placeholder when recognizing reentrancy guards. This prevents an unlock inside the nested block from suppressing reentrancy-balance diagnostics.
mablr
previously approved these changes
Jul 22, 2026
Preserve normalized equality predicates in reentrancy balance path state so complementary == and != branches remain mutually exclusive. Invalidate those predicates when either local operand is reassigned.
stevencartavia
approved these changes
Jul 22, 2026
mablr
approved these changes
Jul 22, 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.
This adds the high-severity
reentrancy-balancelint from #14381. It reports reentrant external calls between savingaddress(this).balanceand comparing a fresh contract balance against that stale local value on the opposite comparison operand.The analysis follows casts, tuples, derived locals, helper parameters and returns, modifiers, inherited dispatch, loops, and both operand orders while excluding token balances, mutable storage baselines, view/static calls, overwritten baselines, and mutually exclusive checks. Explicit gas caps include the value-transfer stipend. Strict standard state-lock modifiers suppress this detector only when the same lock protects every effective mutable re-entry point, and bounded recursion remains available to the existing reentrancy detectors. Fresh-context review additionally corrected modifier ordering around the lock model.
The companion Book documentation is in foundry-rs/book#1984, with the lock and stipend follow-up in foundry-rs/book#1993. This PR was implemented with Codex assistance across code, tests, and lint documentation, then independently reviewed and corrected by fresh Codex contexts.