Skip to content

test(pwq): de-flake test_handleRemainder against fork rounding dust#473

Merged
seongyun-ko merged 1 commit into
seongyun/fuzz/security-upgradesfrom
seongyun/fix/flaky-handle-remainder
Jun 15, 2026
Merged

test(pwq): de-flake test_handleRemainder against fork rounding dust#473
seongyun-ko merged 1 commit into
seongyun/fuzz/security-upgradesfrom
seongyun/fix/flaky-handle-remainder

Conversation

@seongyun-ko

@seongyun-ko seongyun-ko commented Jun 14, 2026

Copy link
Copy Markdown
Contributor

Fix flaky test_handleRemainder (mainnet-fork rounding dust)

test_handleRemainder in test/PriorityWithdrawalQueue.t.sol is flaky on the fork-based CI — it currently fails Foundry project on the security-upgrades line (e.g. PR #470) with:

[FAIL: Remainder should decrease: 1 >= 1] test_handleRemainder()

Root cause (not a contract bug — a test bug)

The test asserted totalRemainderShares strictly decreases after handleRemainder. 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 via sharesForAmount(amount) which rounds down again

So for a 1-wei-share remainder the swept share delta is legitimately zerototalRemainderShares is 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 via sharesForAmount) and assert totalRemainderShares drops by exactly that amount. This is:

  • deterministic / fork-rate independent,
  • strictly stronger than the old assertLt (pins the exact delta, not just a direction),
  • still asserts the strict decrease in the genuinely-sweepable case (expectedSharesMoved > 0).

Verification

  • Reproduced the original failure locally on a mainnet fork.
  • Fixed test passes 3× consecutively on a mainnet fork.
  • src/ untouched — test-only change.

Base: seongyun/fuzz/security-upgrades (same release line as #470/#471/#472). Note: the check_storage_layout CI failure on that line is separate and expected (the release intentionally refactors EETH storage vs master) — not addressed here.


Note

Low Risk
Test-only change to PriorityWithdrawalQueue fork tests; no contract or runtime behavior is modified.

Overview
Stabilizes test_handleRemainder on mainnet-fork CI by replacing a flaky assertLt on totalRemainderShares with assertions that match how handleRemainder actually books shares.

After a fulfill/claim flow, the test still sweeps via getRemainderAmount() when non-zero, but it now computes expectedSharesMoved the same way as production (treasury split with Math.Rounding.Up, burn remainder, both legs through liquidityPool.sharesForAmount) and checks totalRemainderShares drops by exactly that amount. A strict decrease is only required when expectedSharesMoved > 0, covering sub-share dust where double round-down legitimately moves zero shares.

No production code changessrc/ is untouched.

Reviewed by Cursor Bugbot for commit 6272c4c. Bugbot is set up for automated code reviews on this repo. Configure here.

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.
@seongyun-ko seongyun-ko marked this pull request as ready for review June 15, 2026 18:29
@seongyun-ko seongyun-ko merged commit aa298b8 into seongyun/fuzz/security-upgrades Jun 15, 2026
1 check passed
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.

1 participant