fix(widget): parse fee/gas wei amounts without overflowing BigInt - #860
Open
gomesalexandre wants to merge 1 commit into
Open
gomesalexandre wants to merge 1 commit into
gomesalexandre wants to merge 1 commit into
Conversation
fees.ts and useGasSufficiency.ts round-tripped LI.FI's integer wei strings through Number().toFixed(0) before parsing to BigInt. toFixed() switches to exponential notation above 1e21 (e.g. "1.25e+24"), and BigInt() rejects exponential-notation strings, throwing SyntaxError. A live GET https://li.quest/v1/quote for SHIB -> USDT returns a "LIFI Fixed Fee" of 2500000000000000000000000 wei (2.5e24) with included: true - confirmed this crashes getAccumulatedFeeCostsBreakdown(route, true), the public @lifi/widget/shared export, on real production data. Added parseAmountToBigInt(amount: string): bigint, which parses the integer part of the wei string directly (no Number round-trip), and replaced all three call sites of the buggy pattern (grepped the whole repo to confirm no others remain). Also fixes the sub-2^53 precision drift the Number round-trip caused on smaller amounts (confirmed with a real Polygon gas cost above Number.MAX_SAFE_INTEGER). Honest scoping: all current in-widget render call sites use the default included=false and none of five probed routes produced a non-included fee crossing the threshold, so this is a proven crash on the public getAccumulatedFeeCostsBreakdown(route, true) API surface, not an observed in-widget render crash - though there is no ErrorBoundary anywhere in packages/widget/src, so an included:false fee crossing the threshold in the future would take down the whole tree with no recovery.
gomesalexandre
marked this pull request as ready for review
September 1, 2026 14:42
🦋 Changeset detectedLatest commit: b631d94 The changes in this PR will be included in the next version bump. This PR includes changesets to release 20 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
This branch has not been deployed
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.
What
getAccumulatedFeeCostsBreakdown(exported publicly from@lifi/widget/shared) anduseGasSufficiencythrowSyntaxError: Cannot convert Xe+Y to a BigIntfor any real fee or gas amount at or above 1e21 wei. This is not a corner case — routes involving high-supply, low-value tokens (SHIB, PEPE, and similar) routinely cross this threshold.Root cause
Three sites (
packages/widget/src/utils/fees.ts:117,packages/widget/src/hooks/useGasSufficiency.ts:109and:137) parsed integer wei strings like this:Number.prototype.toFixedswitches to exponential notation for values>= 1e21(e.g."1.25e+24"), andBigInt()rejects exponential-notation strings. Separately, round-tripping throughNumberat all loses precision aboveNumber.MAX_SAFE_INTEGER(2^53) even for values that don't crash.Evidence — real production data, not synthetic
Live
GET https://li.quest/v1/quotefor SHIB → USDT (chain 1 → 56):{ "name": "LIFI Fixed Fee", "token": { "symbol": "SHIB", "decimals": 18 }, "amount": "2500000000000000000000000", "included": true }2500000000000000000000000= 2.5e24, well past the crash threshold.Confirmed this crashes
getAccumulatedFeeCostsBreakdown(route, true)when fed a route carrying this real fee.Fix
Added
parseAmountToBigInt(amount: string): bigintinfees.ts, exported and reused at all three sites:No
Numberround-trip, so no exponential-notation crash and no precision loss. Grepped the whole repo (grep -rn "BigInt(Number" --include="*.ts" --include="*.tsx") to confirm these were the only three occurrences of the buggy pattern — all three are fixed.Honest scoping
All current in-widget render call sites of
getAccumulatedFeeCostsBreakdown(RouteCard.tsx,RouteCardEssentials.tsx,RouteDetails.tsx,TransactionReview.tsx,TokenValueBottomSheet.tsx,TransactionFailedButtons.tsx,RouteProviderCard.tsx) use the defaultincluded = false, and across five routes I probed I could not produce a non-included fee crossing the threshold — so this is a proven crash on the publicgetAccumulatedFeeCostsBreakdown(route, true)API surface, not an observed in-widget render crash today. Worth noting: there is noErrorBoundaryanywhere inpackages/widget/src(confirmed via grep), so if a non-included fee or a gas cost ever does cross the threshold, the crash would unmount the whole integrator tree with no recovery —getGasCostsBreakdownin particular processes gas costs through the same buggy expression completely unfiltered byincluded(that field doesn't apply to gas costs at all), on every single call regardless of theincludedparam passed in.One minor, unreachable-with-real-data behavior change worth flagging in review:
"5.999".split('.')truncates to5, where the oldNumber(...).toFixed(0)rounded to6. LI.FI wei amounts are always integers on the wire (confirmed via the live capture above), so this isn't reachable in practice, but noting it for transparency.receipts
Red-before/green-after independently confirmed: stashed the fix and re-ran the same test file against the unmodified code — 7/8 tests failed, including the exact production crash:
Full package suite after the fix:
pnpm check:typesandbiome checkclean on all changed files (pre-existing implicit-any warnings elsewhere inuseGasSufficiency.ts, unrelated to the two lines touched here, are unchanged from baseline).Codex adversarial review timed out with no output after 5 minutes; killed it and did a thorough self-review instead (edge cases tested directly: negative amounts, leading
+, scientific-notation input, whitespace,null/undefined, leading zeros — all match or strictly improve on prior behavior, no new failure modes; confirmed via repo-wide grep that no other instance of the buggy pattern remains).risk
Low — pure parsing fix, no behavior change for any value below the crash threshold, no new dependencies.