From 9b098fb4467827b8962eefb2193126d32bc7c99c Mon Sep 17 00:00:00 2001 From: Pedro Figueiredo Date: Tue, 28 Jul 2026 16:29:45 +0100 Subject: [PATCH 1/3] fix(transaction-controller): scope saved gas exclusions --- packages/transaction-controller/CHANGELOG.md | 4 ++++ .../src/utils/gas-fees.test.ts | 24 ++++++++++++++++++- .../src/utils/gas-fees.ts | 19 +++++++++++---- 3 files changed, 41 insertions(+), 6 deletions(-) diff --git a/packages/transaction-controller/CHANGELOG.md b/packages/transaction-controller/CHANGELOG.md index 01fce8cb00e..f40e1eed098 100644 --- a/packages/transaction-controller/CHANGELOG.md +++ b/packages/transaction-controller/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Fixed + +- Apply saved gas fee preferences to wallet-initiated transfers while continuing to ignore them for swaps and bridge transactions. + ### Changed - Bump `@metamask/gas-fee-controller` from `^26.2.4` to `^26.3.0` ([#9629](https://github.com/MetaMask/core/pull/9629)) diff --git a/packages/transaction-controller/src/utils/gas-fees.test.ts b/packages/transaction-controller/src/utils/gas-fees.test.ts index 55deb04f5fb..49b9bc5f6d7 100644 --- a/packages/transaction-controller/src/utils/gas-fees.test.ts +++ b/packages/transaction-controller/src/utils/gas-fees.test.ts @@ -169,9 +169,31 @@ describe('gas-fees', () => { ); }); - it('are ignored for internal transactions (e.g. swaps and bridges)', async () => { + it('are applied for internal wallet transactions', async () => { + updateGasFeeRequest.txMeta.isInternal = true; + updateGasFeeRequest.txMeta.type = TransactionType.simpleSend; + updateGasFeeRequest.getSavedGasFees.mockReturnValueOnce( + SAVED_GAS_FEES_MOCK, + ); + + await updateGasFees(updateGasFeeRequest); + + expect(updateGasFeeRequest.getSavedGasFees).toHaveBeenCalledTimes(1); + expect(updateGasFeeRequest.txMeta.txParams.maxFeePerGas).toBe( + '0x1ca35f0e00', // 123 gwei + ); + }); + + it.each([ + TransactionType.swap, + TransactionType.swapAndSend, + TransactionType.swapApproval, + TransactionType.bridge, + TransactionType.bridgeApproval, + ])('are ignored for %s transactions', async (type) => { mockGasFeeFlowMockResponse(FLOW_RESPONSE_FEE_MARKET_MOCK); updateGasFeeRequest.txMeta.isInternal = true; + updateGasFeeRequest.txMeta.type = type; updateGasFeeRequest.getSavedGasFees.mockReturnValueOnce( SAVED_GAS_FEES_MOCK, ); diff --git a/packages/transaction-controller/src/utils/gas-fees.ts b/packages/transaction-controller/src/utils/gas-fees.ts index 0c4adab24ff..2c053823ba5 100644 --- a/packages/transaction-controller/src/utils/gas-fees.ts +++ b/packages/transaction-controller/src/utils/gas-fees.ts @@ -17,9 +17,11 @@ import type { import { GasFeeEstimateLevel, GasFeeEstimateType, + TransactionType, UserFeeLevel, } from '../types.js'; import { getGasFeeFlow } from './gas-flow.js'; +import { SWAP_TRANSACTION_TYPES } from './swaps.js'; import { rpcRequest } from './provider.js'; export type UpdateGasFeesRequest = { @@ -57,6 +59,12 @@ type SuggestedGasFees = { const log = createModuleLogger(projectLogger, 'gas-fees'); +const SAVED_GAS_FEES_IGNORED_TRANSACTION_TYPES = [ + ...SWAP_TRANSACTION_TYPES, + TransactionType.bridge, + TransactionType.bridgeApproval, +]; + /** * Update the gas fee properties of the provided transaction meta. * @@ -68,12 +76,13 @@ export async function updateGasFees( const { txMeta } = request; const initialParams = { ...txMeta.txParams }; - // User-saved (advanced) gas fees only apply to dApp transactions. Internal - // transactions (e.g. swaps and bridges) have their fees dictated by the - // aggregator or relay, so applying saved gas fees could underprice them and - // cause them to fail or get stuck. + const shouldIgnoreSavedGasFees = + SAVED_GAS_FEES_IGNORED_TRANSACTION_TYPES.includes( + txMeta.type as TransactionType, + ); + const savedGasFees = - txMeta.isInternal || hasInitialGasFeeParams(initialParams) + shouldIgnoreSavedGasFees || hasInitialGasFeeParams(initialParams) ? undefined : request.getSavedGasFees(txMeta); From f6e87cd7a960b48d815ab847d5057f8153be2fea Mon Sep 17 00:00:00 2001 From: Pedro Figueiredo Date: Tue, 28 Jul 2026 16:29:45 +0100 Subject: [PATCH 2/3] fix(transaction-controller): scope saved gas exclusions --- packages/transaction-controller/CHANGELOG.md | 4 ++++ .../src/utils/gas-fees.test.ts | 24 ++++++++++++++++++- .../src/utils/gas-fees.ts | 19 +++++++++++---- 3 files changed, 41 insertions(+), 6 deletions(-) diff --git a/packages/transaction-controller/CHANGELOG.md b/packages/transaction-controller/CHANGELOG.md index 01fce8cb00e..26c47049336 100644 --- a/packages/transaction-controller/CHANGELOG.md +++ b/packages/transaction-controller/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Fixed + +- Apply saved gas fee preferences to wallet-initiated transfers while continuing to ignore them for swaps and bridge transactions ([#9682](https://github.com/MetaMask/core/pull/9682)). + ### Changed - Bump `@metamask/gas-fee-controller` from `^26.2.4` to `^26.3.0` ([#9629](https://github.com/MetaMask/core/pull/9629)) diff --git a/packages/transaction-controller/src/utils/gas-fees.test.ts b/packages/transaction-controller/src/utils/gas-fees.test.ts index 55deb04f5fb..49b9bc5f6d7 100644 --- a/packages/transaction-controller/src/utils/gas-fees.test.ts +++ b/packages/transaction-controller/src/utils/gas-fees.test.ts @@ -169,9 +169,31 @@ describe('gas-fees', () => { ); }); - it('are ignored for internal transactions (e.g. swaps and bridges)', async () => { + it('are applied for internal wallet transactions', async () => { + updateGasFeeRequest.txMeta.isInternal = true; + updateGasFeeRequest.txMeta.type = TransactionType.simpleSend; + updateGasFeeRequest.getSavedGasFees.mockReturnValueOnce( + SAVED_GAS_FEES_MOCK, + ); + + await updateGasFees(updateGasFeeRequest); + + expect(updateGasFeeRequest.getSavedGasFees).toHaveBeenCalledTimes(1); + expect(updateGasFeeRequest.txMeta.txParams.maxFeePerGas).toBe( + '0x1ca35f0e00', // 123 gwei + ); + }); + + it.each([ + TransactionType.swap, + TransactionType.swapAndSend, + TransactionType.swapApproval, + TransactionType.bridge, + TransactionType.bridgeApproval, + ])('are ignored for %s transactions', async (type) => { mockGasFeeFlowMockResponse(FLOW_RESPONSE_FEE_MARKET_MOCK); updateGasFeeRequest.txMeta.isInternal = true; + updateGasFeeRequest.txMeta.type = type; updateGasFeeRequest.getSavedGasFees.mockReturnValueOnce( SAVED_GAS_FEES_MOCK, ); diff --git a/packages/transaction-controller/src/utils/gas-fees.ts b/packages/transaction-controller/src/utils/gas-fees.ts index 0c4adab24ff..2c053823ba5 100644 --- a/packages/transaction-controller/src/utils/gas-fees.ts +++ b/packages/transaction-controller/src/utils/gas-fees.ts @@ -17,9 +17,11 @@ import type { import { GasFeeEstimateLevel, GasFeeEstimateType, + TransactionType, UserFeeLevel, } from '../types.js'; import { getGasFeeFlow } from './gas-flow.js'; +import { SWAP_TRANSACTION_TYPES } from './swaps.js'; import { rpcRequest } from './provider.js'; export type UpdateGasFeesRequest = { @@ -57,6 +59,12 @@ type SuggestedGasFees = { const log = createModuleLogger(projectLogger, 'gas-fees'); +const SAVED_GAS_FEES_IGNORED_TRANSACTION_TYPES = [ + ...SWAP_TRANSACTION_TYPES, + TransactionType.bridge, + TransactionType.bridgeApproval, +]; + /** * Update the gas fee properties of the provided transaction meta. * @@ -68,12 +76,13 @@ export async function updateGasFees( const { txMeta } = request; const initialParams = { ...txMeta.txParams }; - // User-saved (advanced) gas fees only apply to dApp transactions. Internal - // transactions (e.g. swaps and bridges) have their fees dictated by the - // aggregator or relay, so applying saved gas fees could underprice them and - // cause them to fail or get stuck. + const shouldIgnoreSavedGasFees = + SAVED_GAS_FEES_IGNORED_TRANSACTION_TYPES.includes( + txMeta.type as TransactionType, + ); + const savedGasFees = - txMeta.isInternal || hasInitialGasFeeParams(initialParams) + shouldIgnoreSavedGasFees || hasInitialGasFeeParams(initialParams) ? undefined : request.getSavedGasFees(txMeta); From 61d407435e6ada2aae13a8edd82db770f01e3313 Mon Sep 17 00:00:00 2001 From: Pedro Figueiredo Date: Tue, 28 Jul 2026 17:02:52 +0100 Subject: [PATCH 3/3] chore(transaction-controller): fix validation --- packages/transaction-controller/CHANGELOG.md | 8 ++++---- packages/transaction-controller/src/utils/gas-fees.ts | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/transaction-controller/CHANGELOG.md b/packages/transaction-controller/CHANGELOG.md index 26c47049336..13e264935fa 100644 --- a/packages/transaction-controller/CHANGELOG.md +++ b/packages/transaction-controller/CHANGELOG.md @@ -7,14 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -### Fixed - -- Apply saved gas fee preferences to wallet-initiated transfers while continuing to ignore them for swaps and bridge transactions ([#9682](https://github.com/MetaMask/core/pull/9682)). - ### Changed - Bump `@metamask/gas-fee-controller` from `^26.2.4` to `^26.3.0` ([#9629](https://github.com/MetaMask/core/pull/9629)) +### Fixed + +- Apply saved gas fee preferences to wallet-initiated transfers while continuing to ignore them for swaps and bridge transactions ([#9682](https://github.com/MetaMask/core/pull/9682)). + ## [69.2.1] ### Changed diff --git a/packages/transaction-controller/src/utils/gas-fees.ts b/packages/transaction-controller/src/utils/gas-fees.ts index 2c053823ba5..82f00daeca7 100644 --- a/packages/transaction-controller/src/utils/gas-fees.ts +++ b/packages/transaction-controller/src/utils/gas-fees.ts @@ -21,8 +21,8 @@ import { UserFeeLevel, } from '../types.js'; import { getGasFeeFlow } from './gas-flow.js'; -import { SWAP_TRANSACTION_TYPES } from './swaps.js'; import { rpcRequest } from './provider.js'; +import { SWAP_TRANSACTION_TYPES } from './swaps.js'; export type UpdateGasFeesRequest = { eip1559: boolean;