fix: prevent pendingBridgeFees underflow on truncated batch fees (DEC-820)#775
Open
fix: prevent pendingBridgeFees underflow on truncated batch fees (DEC-820)#775
Conversation
…-820) Per-message fees in handle() are computed via integer division and can truncate to 0 for small message.amount values. The matching subtraction in claim() is computed off the *aggregated* claim amount, where the floor of the sum may exceed the sum of the per-message floors (floor(A) + floor(B) <= floor(A+B)). When the batch fee exceeds what was actually accumulated, pendingBridgeFees -= feeAmount underflows and reverts the claim, locking bridged funds for that origin until unrelated handle() calls happen to bring pendingBridgeFees back up. Track accumulated fees per (chainId, bridge) in addition to the global pendingBridgeFees, and at claim time bound the deduction by what was actually accrued for that origin. This also keeps origins from accidentally consuming each other's pending fees. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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.
Summary
handle()use integer division and truncate to 0 for smallmessage.amount. The batch fee inclaim()is computed off the aggregated claim amount, wherefloor(sum) >= sum(floor). When the gap is non-zero,pendingBridgeFees -= feeAmountunderflows and reverts the claim.(chainId, bridge)and bounds the claim-time subtraction withMath.min(accumulatedFeesByOrigin, batchFee). This also stops one origin from silently consuming another origin's accrued fees.fee-truncation.hardhat.tswith three scenarios: (1) 1000 dust messages — claim panics under old code, succeeds with 0 fee under fix; (2) a dust origin's claim does not eat the OP origin's pending fees; (3) a normal claim still drains accumulated fees.Detail
In
handle():In
_claim():The
processFailedHandlerrescue path is unchanged — it skips fee processing on both sides and so does not need to touch the new mapping (consistent with the DEC-652 fix in #768).Impact
claim()for that origin until unrelated handle() activity refillspendingBridgeFees.Deployment note
RelayPoolis deployed byRelayPoolFactory.deployPoolvianew RelayPool(...)— it is not a proxy and not upgradeable. Already-deployed pools will not pick up this change; only newly deployed pools will. The existing pools should be redeployed if this fix needs to apply to them.Test plan
yarn hardhat test test/RelayPool/*.hardhat.ts— 86 passing, including the 3 new tests infee-truncation.hardhat.tsyarn lint:contracts— 0 errors (warnings unchanged from main)failed-hyperlane.hardhat.tstests still pass, including the cross-origin fee preservation and normal claim path tests🤖 Generated with Claude Code