Repository navigation
Conversation
Post-quote flows use accountOverride as both the quote sender and the output recipient. A Money Account withdrawal to a hardware wallet then quotes and submits the Relay deposit from the hardware account, so the device must sign, even though the Money Account holds the funds. Add an opt-in isAccountOverrideRecipientOnly config. When set on a post-quote transaction, quotes are requested and submitted from the transaction's own from, and accountOverride is only the Relay recipient. The payment token balance is still read for accountOverride.
…Only sender requirement
…de-recipient-only-a87f # Conflicts: # packages/transaction-pay-controller/CHANGELOG.md Co-authored-by: Daniel <[email protected]>
| const recipient = | ||
| isPostQuote && isAccountOverrideRecipientOnly ? accountOverride : undefined; | ||
|
|
||
| const quoteFrom = recipient ? (transaction.txParams.from as Hex) : from; |
There was a problem hiding this comment.
I'm wondering if we can avoid being so explicit with the new config property which adds complexity.
The Perps withdraw goes via signatures, so no gas needed, so from can be Perps account.
Predict withdraw goes via the Polymarket relayer so also gasless so from should be fine as Polymarket account?
And then a normal money account withdraw is sponsored as on Monad so normal from should always be fine?
There was a problem hiding this comment.
Reminder to test the legacy Predict withdraw flow via Safe account also.
…de-recipient-only-a87f
…de-recipient-only-a87f Co-authored-by: Daniel <[email protected]>
…de-recipient-only-a87f
… changelog entry to Unreleased
…de-recipient-only-a87f # Conflicts: # packages/transaction-pay-controller/CHANGELOG.md
…de-recipient-only-a87f
Recipient selection moves into the strategies with #10887, so the explicit config property is no longer needed.
…/account-override-recipient-only-a87f # Conflicts: # packages/transaction-pay-controller/CHANGELOG.md
…ansaction account Post-quote quotes are now requested and submitted from the transaction's own from, and the shared quote recipient resolution pays accountOverride. An account that cannot sign, such as a hardware wallet, can then receive a withdrawal without a dedicated config property.
…de-recipient-only-a87f # Conflicts: # oxlint-suppressions.json # packages/transaction-pay-controller/src/utils/quote-recipient.test.ts # packages/transaction-pay-controller/src/utils/quote-recipient.ts
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
❌ 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 f34790e. Configure here.
…-quote withdrawals Across post-quote quotes now use the shared post-quote recipient lookup, so they pay `accountOverride` like Relay and Server instead of the sending account.
…de-recipient-only-a87f
…de-recipient-only-a87f # Conflicts: # packages/transaction-pay-controller/CHANGELOG.md
|
|
||
| ### Changed | ||
|
|
||
| - **BREAKING:** Request and submit post-quote quotes from the transaction's own `from`, so `accountOverride` only receives the output and never signs ([#10992](https://github.com/MetaMask/core/pull/10992)) |
There was a problem hiding this comment.
How is this breaking? What change is needed in the client?
| const from = accountOverride ?? (transaction.txParams.from as Hex); | ||
|
|
||
| // Post-quote output goes to `accountOverride`, so the funds holder sends. | ||
| const quoteFrom = isPostQuote ? (transaction.txParams.from as Hex) : from; |
There was a problem hiding this comment.
Rather than defining a from and a quoteFrom, could we define a local function like getFrom that early returns for better readability?
| 'TransactionPayController:getState', | ||
| ); | ||
|
|
||
| return transactionData[transaction.id]?.accountOverride ?? request.from; |
There was a problem hiding this comment.
If we're now explicitly getting the account override from the messenger, as it's not always encapsulated behind the from, then should we simply pass the accountOverride explicitly into QuoteRequest and the above resolveQuoteRecipient so it's more readable?
Then we wouldn't need to use request.from at all but make the logic clearer when we're using accountOverride?
| return { | ||
| actions: [], | ||
| recipient, | ||
| recipient: getPostQuoteRecipient({ messenger, request, transaction }), |
There was a problem hiding this comment.
Following the other comment, this could just become request.accountOverride and we wouldn't need to export a getPostQuoteRecipient function?
…From Replace the `from` and `quoteFrom` pair in `updateQuotes` with a local `getFrom` helper that returns early for post-quote flows.
…ote quote requests Add `accountOverride` to `QuoteRequest` for post-quote flows, so `resolveQuoteRecipient` and the Across post-quote destination read it from the request instead of looking it up through the messenger. This removes `getPostQuoteRecipient`.
…t-quote senders Name the concrete client change behind the breaking entry: a Money Account withdrawal that needs a quote must keep the withdrawn mUSD on the transaction's `from`.

Explanation
In post-quote flows,
accountOverridewas both the quote sender and the output recipient, so a Money Account withdrawal to a hardware wallet had to be signed by the hardware wallet even though the Money Account holds the funds.Post-quote quotes are now always requested and submitted from the transaction's own
from. Post-quote requests carryaccountOverride, which Relay and Server pay through the shared recipient resolution from #10887 and Across pays directly. This needs no new config property. Non-post-quote flows are unchanged.This is breaking for clients that move a withdrawal's funds to
accountOverridebefore the Relay deposit: they must leave the funds on the transaction'sfrom. For example, a Money Account withdrawal that needs a quote must no longer transfer the withdrawn mUSD toaccountOverridein its nested calls.References
Checklist
Note
Medium Risk
Breaking contract for post-quote fund placement and signing; wrong client nesting could leave quotes unfunded or sent from the wrong account.
Reviewed by Cursor Bugbot for commit e1c2e9e. Bugbot is set up for automated code reviews on this repo. Configure here.