fix: ignore saved advanced gas fees for bridge transactions#9401
Merged
Conversation
Bridge and bridge approval transactions applied the user's saved advanced gas fees, which swaps already deliberately ignore. A user with a low saved max base fee (e.g. 0.05 gwei on mainnet) would therefore submit underpriced bridge transactions that fail or get stuck as pending. Introduce a dedicated SAVED_GAS_FEES_IGNORED_TRANSACTION_TYPES list (swap + bridge types) to decide whether saved gas fees apply, keeping the "ignore saved gas fees" concern decoupled from SWAP_TRANSACTION_TYPES, which also gates swap-specific behavior.
chaitanyapotti
previously approved these changes
Jul 7, 2026
matthewwalsh0
requested changes
Jul 7, 2026
| * fees are dictated by the swap/bridge aggregator or relay; applying saved gas | ||
| * fees could underprice the transaction and cause it to fail or get stuck. | ||
| */ | ||
| const SAVED_GAS_FEES_IGNORED_TRANSACTION_TYPES: TransactionType[] = [ |
Member
There was a problem hiding this comment.
Rather than doing this per type, should we just exclude based on isInternal so it only applies to dApp transactions as was the intent?
Contributor
Author
There was a problem hiding this comment.
Sounds good, even simpler! I made the change
Per review feedback, skip user-saved (advanced) gas fees for all internal transactions rather than maintaining a list of swap/bridge types. Saved gas fees are only intended for dApp transactions; internal transactions (swaps, bridges, etc.) have their fees dictated by the aggregator or relay.
matthewwalsh0
approved these changes
Jul 7, 2026
pull Bot
pushed a commit
to dmrazzy/core
that referenced
this pull request
Jul 7, 2026
## Explanation Releases two packages needed to fix stuck/underpriced bridge smart transactions in the clients (extension + mobile). ### `@metamask/transaction-controller` — `68.2.2` → `68.3.0` (minor) - **Added:** `failTransaction` method + `TransactionController:failTransaction` messenger action ([MetaMask#9400](MetaMask#9400)) — fails a tx through the standard path, emitting `transactionFailed`/`transactionStatusUpdated`/`transactionFinished`. - **Fixed:** Only apply user-saved (advanced) gas fees to dApp transactions; ignored for internal (`isInternal`) txs such as swaps and bridges ([MetaMask#9401](MetaMask#9401)). - **Changed:** Bump `@metamask/messenger` `^1.2.0` → `^2.0.0` ([MetaMask#9392](MetaMask#9392)). ### `@metamask/smart-transactions-controller` — `24.2.4` → `25.0.0` (major) - **Changed (BREAKING):** Fail the associated regular transaction via `TransactionController:failTransaction` instead of `updateTransaction` when a smart transaction is cancelled ([MetaMask#9400](MetaMask#9400)). Consumers must now grant the STX messenger access to `TransactionController:failTransaction`. - **Changed:** Bump `@metamask/messenger` `^1.2.0` → `^2.0.0` ([MetaMask#9392](MetaMask#9392)). All other changed packages are `intentionally-skip` (owned by other teams); dependent version ranges were updated automatically. ## References - Fixes stuck-pending bridge STX (root cause in MetaMask#9400) and underpriced bridge gas (MetaMask#9401). ## Checklist - [x] I've followed the [release process](https://github.com/MetaMask/core/blob/main/docs/processes/releasing.md) - [x] Changelogs reviewed and categorized (no `Uncategorized`; breaking change marked) - [x] Version bumps follow SemVer (STX major for the breaking messenger change) <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Touches transaction failure signaling and gas on internal bridge flows; STX **25.0.0** is a breaking messenger permission change for extension/mobile integrators. > > **Overview** > **Monorepo release `1102.0.0`** that publishes **`@metamask/transaction-controller` `68.3.0`** and **`@metamask/smart-transactions-controller` `25.0.0`**, and rolls **`@metamask/transaction-controller` `^68.2.2` → `^68.3.0`** through dependent packages and **`yarn.lock`**. > > **`transaction-controller` `68.3.0`** (documented in its changelog for this release): adds **`failTransaction`** / **`TransactionController:failTransaction`** so out-of-band failures emit normal lifecycle events; fixes **advanced gas fees** so they apply only to dApp txs, not **`isInternal`** bridge/swap txs. > > **`smart-transactions-controller` `25.0.0` (breaking):** on smart-tx cancel, calls **`failTransaction`** instead of **`updateTransaction`**; hosts must delegate **`TransactionController:failTransaction`** on the STX messenger. > > Other touched packages in the diff are mainly **version/changelog dependency bumps** tied to this release, not new feature code in those files. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit c423a08. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.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.
Explanation
Bridge transactions apply the user's saved advanced gas fees, whereas swaps deliberately ignore them.
In
updateGasFees, saved gas fees are skipped only forSWAP_TRANSACTION_TYPES(swap,swapAndSend,swapApproval).bridge/bridgeApprovalare not in that list, so a user's saved advanced gas fees are applied to bridge transactions.For a user who has saved a low max base fee (observed in production:
maxBaseFee: "0.05"gwei,priorityFee: "0"for mainnet), every bridge is submitted underpriced — below the current base fee — causing it to fail (GAS_TOO_LOWon the relay) or get stuck as pending. This is exactly the failure swaps were already protected from.Fix
Ignore saved gas fees for bridge transactions as well, via a dedicated list:
I intentionally did not add the bridge types to
SWAP_TRANSACTION_TYPESitself, because that constant also gates swap-specific behavior inupdateSwapsTransaction(e.g. thesimulationFailscancel-and-throw, andtransactionNewSwap*events). Keeping a separate, purpose-named list decouples "ignore saved gas fees" from "is a swap".References
maxFeePerGas: 0x2faf080(0.05 gwei) /maxPriorityFeePerGas: 0x0, sourced fromadvancedGasFee["0x1"] = { maxBaseFee: "0.05", priorityFee: "0" }.Changelog
@metamask/transaction-controllerbridgeandbridgeApprovaltransactions now ignore user-saved (advanced) gas fees, matching swaps.Checklist
Note
Medium Risk
Changes gas pricing for all internal transactions (bridges, swaps, etc.); behavior is intentional but affects submission paths where wrong fees caused production failures.
Overview
updateGasFeesno longer applies user-saved (advanced) gas fees whentxMeta.isInternalis true. Saved fees are only loaded for non-internal (dApp) transactions.The previous logic skipped saved fees only for
SWAP_TRANSACTION_TYPES, so bridge and other internal flows could inherit a low saved max base fee and submit underpriced txs. The swap-type check andSWAP_TRANSACTION_TYPESimport were removed in favor ofisInternal.Tests cover applying saved fees for non-internal txs and ignoring them (without calling
getSavedGasFees) for internal txs. The changelog documents the fix.Reviewed by Cursor Bugbot for commit eb622eb. Bugbot is set up for automated code reviews on this repo. Configure here.