Skip to content

fix: transaction parameters for batch swap transactions#8979

Merged
GeorgeGkas merged 6 commits into
mainfrom
swaps-fix-stx-batch-sell
Jun 3, 2026
Merged

fix: transaction parameters for batch swap transactions#8979
GeorgeGkas merged 6 commits into
mainfrom
swaps-fix-stx-batch-sell

Conversation

@micaelae
Copy link
Copy Markdown
Member

@micaelae micaelae commented Jun 2, 2026

Explanation

Fixes batch-sell submission edge case which causes tx failure if gasIncluded7702=true and STX is enabled. See changelog for exact parameters changed

In addition to these changes, clients need to update the TransactionController publishHook to prioritize publishing via 7702 if isGasFeeIncluded=true. The current logic submits using STX although the quote requires 7702 processing

Example transaction-controller-init change

+  const isSwapGasIncluded7702 = transactionMeta.isGasFeeIncluded;
   let attemptedHook = false;
 
   if (
     keyringSupports7702 &&
     !isRevokeDelegation &&
-    (!isSmartTransaction || !sendBundleSupport || isExternalSign)
+    (isSwapGasIncluded7702 || !isSmartTransaction || !sendBundleSupport || isExternalSign)
    ) {
     const hook = new Delegation7702PublishHook({
      messenger: initMessenger,
    }).getHook();

References

Checklist

  • I've updated the test suite for new or updated code as appropriate
  • I've updated documentation (JSDoc, Markdown, etc.) for new or updated code as appropriate
  • I've communicated my changes to consumers by updating changelogs for packages I've changed
  • I've introduced breaking changes in this PR and have prepared draft pull requests for clients and consumer packages to resolve them

Note

High Risk
Changes how batched swaps choose 7702 vs STX paths and how fees are paid; misconfiguration can cause submission failures, and full behavior depends on a coordinated TransactionController publishHook update in clients.

Overview
Fixes gas and EIP-7702 batch options passed from BridgeStatusController into TransactionController for batched swaps and batch-sell flows, addressing failures when quotes use gas-included 7702 with STX enabled or ERC-20–denominated fees.

Batch swap strategy now derives gasFeeToken from the quote’s TX_FEE asset (omitted when the fee asset is native), and sets skipInitialGasEstimate / excludeNativeTokenForFee from that token and from gasIncluded7702 plus whether the account is already delegated. shouldDisable7702 is tightened so delegated accounts only keep 7702 enabled when the quote is not plain gasIncluded STX gasless.

Batch-sell uses the same skipInitialGasEstimate and excludeNativeTokenForFee rules. toTransactionParams accepts bridge-api fee fields whether they are already hex or numeric strings.

Tests and snapshots cover native vs ERC-20 gasless swaps and the updated batch params. Clients still need a separate publishHook change so isGasFeeIncluded quotes publish via 7702 instead of STX when required.

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

@micaelae micaelae marked this pull request as ready for review June 2, 2026 23:12
@micaelae micaelae requested a review from a team as a code owner June 2, 2026 23:12
@micaelae micaelae temporarily deployed to default-branch June 2, 2026 23:12 — with GitHub Actions Inactive
@micaelae micaelae requested a review from a team as a code owner June 3, 2026 00:58
skipInitialGasEstimate: quoteResponse.quote.gasIncluded7702
? isDelegatedAccount
: Boolean(gasFeeToken),
excludeNativeTokenForFee: !gasFeeToken,
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inverted excludeNativeTokenForFee flag

High Severity

Batch submission sets excludeNativeTokenForFee to !gasFeeToken, so when an ERC20 gasFeeToken is provided the flag is false. TransactionController only forces fee payment via gasFeeToken when excludeNativeTokenForFee is true with a token set, so ERC20 gasless swaps can fall back to native balance.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 9e44080. Configure here.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is intentional. Prevents failures if the user has a native balance but it's not enough to cover network fees

Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

There are 2 total unresolved issues (including 1 from previous review).

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 402df45. Configure here.

quoteResponse.quote.feeData[FeeType.TX_FEE]?.asset?.address &&
isNativeAddress(quoteResponse.quote.feeData[FeeType.TX_FEE].asset.address)
? undefined
: (quoteResponse.quote.feeData[FeeType.TX_FEE]?.asset?.address as Hex);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Empty native fee sets gasFeeToken

Low Severity

When TX_FEE uses a native asset with an empty-string address (valid per isNativeAddress), the gasFeeToken expression falls through to the else branch and passes an empty hex string instead of undefined, so batch params can carry a bogus gasFeeToken rather than treating the fee as native.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 402df45. Configure here.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not possible, it's either zero address or a hex

@micaelae micaelae enabled auto-merge June 3, 2026 01:53
@micaelae micaelae added this pull request to the merge queue Jun 3, 2026
@GeorgeGkas GeorgeGkas removed this pull request from the merge queue due to a manual request Jun 3, 2026
@GeorgeGkas GeorgeGkas added this pull request to the merge queue Jun 3, 2026
Merged via the queue into main with commit 87c98fa Jun 3, 2026
370 checks passed
@GeorgeGkas GeorgeGkas deleted the swaps-fix-stx-batch-sell branch June 3, 2026 13:49
@GeorgeGkas GeorgeGkas mentioned this pull request Jun 3, 2026
4 tasks
pull Bot pushed a commit to dmrazzy/core that referenced this pull request Jun 3, 2026
## Explanation

**Current state:** When submitting batch and batch-sell swap
transactions, the gas-related transaction options were not being set
correctly in several edge cases:

1. When the bridge fee is paid in an ERC20 token, the `gasFeeToken`
field was not being populated, causing the TransactionController to
default to native token fee payment.
2. The `excludeNativeTokenForFee` flag was not being set when a
`gasFeeToken` was present, meaning the TransactionController might fall
back to native assets even when an ERC20 gas fee token was explicitly
specified.
3. For `gasIncluded7702` quotes submitted to accounts that haven't yet
been upgraded to a smart account, `skipInitialGasEstimate` was
incorrectly set, which could cause gas estimation issues.

**Solution:** This release fixes all three cases in the gas-related
transaction option construction for batch and batch-sell swaps:
- `gasFeeToken` is now set from the quote's fee token when fees are paid
in ERC20.
- `excludeNativeTokenForFee` is set to `true` whenever `gasFeeToken` is
populated, ensuring the ERC20 token is always used for fee payment in
that scenario.
- `skipInitialGasEstimate` is set to `false` when submitting
`gasIncluded7702` quotes and the account has not yet been upgraded to a
smart account, ensuring correct gas estimation for those transactions.

## References

- [MetaMask#8979](MetaMask#8979)

## Checklist

- [ ] I've updated the test suite for new or updated code as appropriate
- [ ] I've updated documentation (JSDoc, Markdown, etc.) for new or
updated code as appropriate
- [ ] I've communicated my changes to consumers by [updating changelogs
for packages I've
changed](https://github.com/MetaMask/core/tree/main/docs/processes/updating-changelogs.md)
- [ ] I've introduced [breaking
changes](https://github.com/MetaMask/core/tree/main/docs/processes/breaking-changes.md)
in this PR and have prepared draft pull requests for clients and
consumer packages to resolve them

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> The release carries a targeted fix to how gas/fee options are passed
into TransactionController for batch and batch-sell swaps, which can
change fee token selection and estimation behavior at submit time.
> 
> **Overview**
> **Release `1019.0.0`** bumps the core monorepo and publishes
**`@metamask/bridge-status-controller@72.0.1`**, documenting the
gas-option fix from [MetaMask#8979](MetaMask#8979)
for **batch** and **batch-sell** swaps: ERC20-paid fees set
**`gasFeeToken`**, **`excludeNativeTokenForFee=true`** when that token
is used, and **`skipInitialGasEstimate=false`** for
**`gasIncluded7702`** on accounts not yet upgraded to a smart account.
> 
> **`@metamask/transaction-pay-controller`** is updated to depend on
**`@metamask/bridge-status-controller@^72.0.1`** (changelog +
`package.json` + `yarn.lock`). No application source changes appear in
this diff—only version and release metadata.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
ed18202. 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>
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.

2 participants