test(pwq): de-flake test_handleRemainder against fork rounding dust#473
Merged
seongyun-ko merged 1 commit intoJun 15, 2026
Merged
Conversation
test_handleRemainder asserted totalRemainderShares strictly DECREASES after handleRemainder. On a mainnet fork the remainder is sub-share rounding dust: getRemainderAmount() rounds shares->amount DOWN, and handleRemainder converts amount->shares via sharesForAmount() rounding DOWN again, so the swept share delta can legitimately be ZERO. The strict-decrease assertion then fails non-deterministically depending on the live fork share rate (observed: 'Remainder should decrease: 1 >= 1'). Fix: replicate handleRemainder's exact share accounting (treasury split rounds up, burn gets the rest, both converted via sharesForAmount) and assert totalRemainderShares drops by EXACTLY that amount -- deterministic, fork-rate independent, and strictly stronger than the old inequality. Keep the strict decrease only in the genuinely-sweepable case (>=1 share moved). No src change; verified passing 3x on a mainnet fork.
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.
Fix flaky
test_handleRemainder(mainnet-fork rounding dust)test_handleRemainderintest/PriorityWithdrawalQueue.t.solis flaky on the fork-based CI — it currently failsFoundry projecton the security-upgrades line (e.g. PR #470) with:Root cause (not a contract bug — a test bug)
The test asserted
totalRemainderSharesstrictly decreases afterhandleRemainder. But the remainder on a mainnet fork is sub-share rounding dust, and there's a shares↔amount rounding asymmetry:getRemainderAmount()=amountForShare(shares)rounds down (shares → eEth amount)handleRemainder(amount)converts back viasharesForAmount(amount)which rounds down againSo for a 1-wei-share remainder the swept share delta is legitimately zero →
totalRemainderSharesis unchanged → the strict-decrease assertion fails. Whether it fails depends on the live fork share rate at the latest block, so it's non-deterministic. (An earlier attempt — "sweep the full remainder" — didn't help, because the second round-down still yields 0.)Fix
Replicate
handleRemainder's exact share accounting in the test (treasury split rounds up, burn gets the rest, both viasharesForAmount) and asserttotalRemainderSharesdrops by exactly that amount. This is:assertLt(pins the exact delta, not just a direction),expectedSharesMoved > 0).Verification
src/untouched — test-only change.Base:
seongyun/fuzz/security-upgrades(same release line as #470/#471/#472). Note: thecheck_storage_layoutCI failure on that line is separate and expected (the release intentionally refactorsEETHstorage vsmaster) — not addressed here.Note
Low Risk
Test-only change to PriorityWithdrawalQueue fork tests; no contract or runtime behavior is modified.
Overview
Stabilizes
test_handleRemainderon mainnet-fork CI by replacing a flakyassertLtontotalRemainderShareswith assertions that match howhandleRemainderactually books shares.After a fulfill/claim flow, the test still sweeps via
getRemainderAmount()when non-zero, but it now computesexpectedSharesMovedthe same way as production (treasury split withMath.Rounding.Up, burn remainder, both legs throughliquidityPool.sharesForAmount) and checkstotalRemainderSharesdrops by exactly that amount. A strict decrease is only required whenexpectedSharesMoved > 0, covering sub-share dust where double round-down legitimately moves zero shares.No production code changes —
src/is untouched.Reviewed by Cursor Bugbot for commit 6272c4c. Bugbot is set up for automated code reviews on this repo. Configure here.