Skip to content

chore(runway): cherry-pick feat: block MetaMask Pay submissions without quotes and handle no-op quotes#33371

Open
runway-github[bot] wants to merge 1 commit into
release/8.3.0from
cherry-pick-8-3-0-234a682
Open

chore(runway): cherry-pick feat: block MetaMask Pay submissions without quotes and handle no-op quotes#33371
runway-github[bot] wants to merge 1 commit into
release/8.3.0from
cherry-pick-8-3-0-234a682

Conversation

@runway-github

@runway-github runway-github Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Description

Mobile side of MetaMask/core#9484, which makes "no conversion needed" an
explicit no-op quote and requires quotes at publish time for MetaMask
Pay transactions.

  • Bump @metamask/transaction-pay-controller to ^25.0.0 (includes the
    no-op quote change) and @metamask/transaction-controller to 69.0.0
    (required by the new pay controller).
  • validateRequiredQuote now also requires quotes for post-quote
    withdraw types when the post-quote flag is enabled; direct routes are
    allowed only when the controller state confirms them.
  • validateRequiredQuote also covers pay deposit and conversion types
    (perps deposits, predict deposits, mUSD conversion): they may submit
    without a quote only when the user pays with the required token itself
    and no conversion is pending, or the deposit is funded by a fiat on-ramp
    order.
  • New blocking legs in useNoPayTokenQuotesAlert: withdraw flows where
    the pay config or destination token is not set on the controller yet,
    and pay deposit/conversion flows where neither a payment token nor a
    fiat payment method is set.
  • No-op quotes (strategy none) are filtered everywhere: fee, duration,
    and step UI, metrics, and the publish guard. A no-op quote never counts
    as an executable quote; direct routes are validated from controller
    state instead, keeping the publish guard consistent with the
    confirmation alerts.
  • Metrics: add mm_pay_quote_skipped; strategy and step totals count
    only executable quotes.

Changelog

CHANGELOG entry: Improved quote validation for MetaMask Pay deposits,
conversions and withdrawals

Related issues

Refs: MetaMask/core#9484

Manual testing steps

Feature: MetaMask Pay quote validation

  Scenario: user withdraws to a different destination token
    Given the user has a Predict, Perps, or Money account balance
    When the user enters an amount and a quote is available
    Then the confirmation completes with the selected destination token

  Scenario: user withdraws to the same token and chain
    Given the user selects the source token as the destination
    Then the withdrawal completes as a direct transfer

  Scenario: user deposits or converts paying with another token
    Given the user selects a payment token on a different chain
    When a quote is available
    Then the transaction completes with the conversion

  Scenario: user deposits or converts paying with the required token
    Given the user selects the required token itself as the payment token
    Then the transaction completes as a direct transfer

  Scenario: user deposits paying with fiat
    Given the user selects a fiat payment method
    Then the confirmation is not blocked by the payment token alert

Screenshots/Recordings

N/A

Before

N/A

After

N/A

Pre-merge author checklist

Performance checks (if applicable)

  • I've tested on Android
    • Ideally on a mid-range device; emulator is acceptable
  • I've tested with a power user scenario
  • Use these power-user
    SRPs

    to import wallets with many accounts and tokens
  • I've instrumented key operations with Sentry traces for production
    performance metrics
  • See trace() for usage and
    addToken
    for an example

For performance guidelines and tooling, see the Performance
Guide
.

Pre-merge reviewer checklist

  • I've manually tested the PR (e.g. pull and build branch, run the
    app, test code being changed).
  • I confirm that this PR addresses all acceptance criteria described
    in the ticket it closes and includes the necessary testing evidence such
    as recordings and or screenshots.

Note

High Risk
Changes transaction publish and confirmation blocking for MetaMask Pay
funding paths; incorrect direct-route exceptions could still allow
unfunded submissions or block legitimate flows.

Overview
Bumps @metamask/transaction-pay-controller to ^25.0.0 (no-op
quotes for direct routes) and aligns mobile with stricter publish-time
and confirmation-time Pay guards.

No-op quotes (strategy: none) are treated as non-executable
everywhere: the quote selector filters them for UI,
validateRequiredQuote and metrics only count executable quotes,
and mm_pay_quote_skipped is set when no-op quotes were present.

Publish (validateRequiredQuote) now also applies to
pay-token-required deposits/conversions (perps/predict/mUSD, etc.)
and post-quote withdraws when the feature flag is on. Submission
without an executable quote is allowed only for validated direct routes
(required token, no pending conversion), fiat orders with orderId,
or post-quote withdraws with isPostQuote and no pending
sourceAmounts—including withdraws with no destination token
selected.

Confirmation adds blocking NoPayTokenQuotes cases: withdraws
with token selection enabled before Pay config is initialised
(!isPostQuote), and pay-token-required types with no payment token and
no fiat method—mirroring publish rules so users cannot confirm timing
races that used to submit unfunded txs.

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

[234a682](https://github.com/MetaMask/metamask-mobile/commit/234a6829b8ac0d054cc946e806e7fcb360662318)

…quotes cp-8.3.0 (#33194)

Mobile side of MetaMask/core#9484, which makes "no conversion needed" an
explicit no-op quote and requires quotes at publish time for MetaMask
Pay transactions.

- Bump `@metamask/transaction-pay-controller` to `^25.0.0` (includes the
no-op quote change) and `@metamask/transaction-controller` to `69.0.0`
(required by the new pay controller).
- `validateRequiredQuote` now also requires quotes for post-quote
withdraw types when the post-quote flag is enabled; direct routes are
allowed only when the controller state confirms them.
- `validateRequiredQuote` also covers pay deposit and conversion types
(perps deposits, predict deposits, mUSD conversion): they may submit
without a quote only when the user pays with the required token itself
and no conversion is pending, or the deposit is funded by a fiat on-ramp
order.
- New blocking legs in `useNoPayTokenQuotesAlert`: withdraw flows where
the pay config or destination token is not set on the controller yet,
and pay deposit/conversion flows where neither a payment token nor a
fiat payment method is set.
- No-op quotes (strategy `none`) are filtered everywhere: fee, duration,
and step UI, metrics, and the publish guard. A no-op quote never counts
as an executable quote; direct routes are validated from controller
state instead, keeping the publish guard consistent with the
confirmation alerts.
- Metrics: add `mm_pay_quote_skipped`; strategy and step totals count
only executable quotes.

CHANGELOG entry: Improved quote validation for MetaMask Pay deposits,
conversions and withdrawals

Refs: MetaMask/core#9484

```gherkin
Feature: MetaMask Pay quote validation

  Scenario: user withdraws to a different destination token
    Given the user has a Predict, Perps, or Money account balance
    When the user enters an amount and a quote is available
    Then the confirmation completes with the selected destination token

  Scenario: user withdraws to the same token and chain
    Given the user selects the source token as the destination
    Then the withdrawal completes as a direct transfer

  Scenario: user deposits or converts paying with another token
    Given the user selects a payment token on a different chain
    When a quote is available
    Then the transaction completes with the conversion

  Scenario: user deposits or converts paying with the required token
    Given the user selects the required token itself as the payment token
    Then the transaction completes as a direct transfer

  Scenario: user deposits paying with fiat
    Given the user selects a fiat payment method
    Then the confirmation is not blocked by the payment token alert
```

N/A

N/A

N/A

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

- [ ] I've tested on Android
  - Ideally on a mid-range device; emulator is acceptable
- [ ] I've tested with a power user scenario
- Use these [power-user
SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example

For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **High Risk**
> Changes transaction publish and confirmation blocking for MetaMask Pay
funding paths; incorrect direct-route exceptions could still allow
unfunded submissions or block legitimate flows.
>
> **Overview**
> Bumps **`@metamask/transaction-pay-controller`** to **^25.0.0** (no-op
quotes for direct routes) and aligns mobile with stricter publish-time
and confirmation-time Pay guards.
>
> **No-op quotes** (`strategy: none`) are treated as non-executable
everywhere: the quote selector filters them for UI,
**`validateRequiredQuote`** and metrics only count executable quotes,
and **`mm_pay_quote_skipped`** is set when no-op quotes were present.
>
> **Publish** (`validateRequiredQuote`) now also applies to
**pay-token-required** deposits/conversions (perps/predict/mUSD, etc.)
and **post-quote withdraws** when the feature flag is on. Submission
without an executable quote is allowed only for validated direct routes
(required token, no pending conversion), fiat orders with **`orderId`**,
or post-quote withdraws with **`isPostQuote`** and no pending
**`sourceAmounts`**—including withdraws with no destination token
selected.
>
> **Confirmation** adds blocking **`NoPayTokenQuotes`** cases: withdraws
with token selection enabled before Pay config is initialised
(`!isPostQuote`), and pay-token-required types with no payment token and
no fiat method—mirroring publish rules so users cannot confirm timing
races that used to submit unfunded txs.
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
cd7b38f. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
@runway-github runway-github Bot requested a review from a team as a code owner July 15, 2026 17:23
@github-actions

Copy link
Copy Markdown
Contributor

CLA Signature Action: All authors have signed the CLA. You may need to manually re-run the blocking PR check if it doesn't pass in a few minutes.

@metamask-ci metamask-ci Bot added the team-bots Bot team (for MetaMask Bot, Runway Bot, etc.) label Jul 15, 2026
@github-actions

Copy link
Copy Markdown
Contributor

🔍 Smart E2E Test Selection

⏭️ Smart E2E selection skipped - PR targets a release or stable branch (release/* or stable)

All E2E tests pre-selected.

View GitHub Actions results

@github-actions github-actions Bot added size-L risk:high AI analysis: high risk labels Jul 15, 2026
@socket-security

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Updatednpm/​@​metamask/​transaction-pay-controller@​23.17.4 ⏵ 25.0.09910081 +1100 +1100

View full report

@socket-security

Copy link
Copy Markdown

Warning

MetaMask internal reviewing guidelines:

  • Do not ignore-all
  • Each alert has instructions on how to review if you don't know what it means. If lost, ask your Security Liaison or the supply-chain group
  • Copy-paste ignore lines for specific packages or a group of one kind with a note on what research you did to deem it safe.
    @SocketSecurity ignore npm/PACKAGE@VERSION
Action Severity Alert  (click "▶" to expand/collapse)
Warn Low
Potential code anomaly (AI signal): npm @metamask/transaction-pay-controller is 62.0% likely to have a medium risk anomaly

Notes: No overt malware primitives (eval, obfuscated payloads, command execution) are present in this snippet. However, it signs typed data via KeyringController and then posts signature/authorization material to step.post.endpoint using successfulFetch, where the endpoint is derived from quote config without visible allowlisting. It also submits high-privilege delegation/authorization data to a server relay and drives TransactionController:addTransaction/addTransactionBatch with overwriteUpgrade and other powerful options. This creates a plausible supply-chain attack surface if the quote/step configuration can be attacker-controlled; signed artifacts could be exfiltrated to arbitrary URLs. Impact and likelihood depend on validation outside this module.

Confidence: 0.62

Severity: 0.60

From: package.jsonnpm/@metamask/transaction-pay-controller@25.0.0

ℹ Read more on: This package | This alert | What is an AI-detected potential code anomaly?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: An AI system found a low-risk anomaly in this package. It may still be fine to use, but you should check that it is safe before proceeding.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/@metamask/transaction-pay-controller@25.0.0. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

View full report

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

risk:high AI analysis: high risk size-L team-bots Bot team (for MetaMask Bot, Runway Bot, etc.)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant