Skip to content

Fix use effective recipient for first-time interaction check on token transfers#8130

Merged
vinistevam merged 16 commits intomainfrom
fix/first-time-interaction-erc20-recipient-check
Mar 10, 2026
Merged

Fix use effective recipient for first-time interaction check on token transfers#8130
vinistevam merged 16 commits intomainfrom
fix/first-time-interaction-erc20-recipient-check

Conversation

@vinistevam
Copy link
Contributor

@vinistevam vinistevam commented Mar 6, 2026

Explanation

Fixes the first-time interaction logic so the "first time interaction" alert correctly triggers when sending ERC20/ERC721 tokens to a new address. Previously, the alert could be skipped if the user had ever sent the same token to any other address, because the existing-transaction check compared txParams.to (the token contract for ERC20) instead of the actual recipient.

Problem

  • For ERC20/ERC721 transfers, txParams.to is the token contract, not the recipient.
  • The code that skips the accounts API call when an "existing" transaction is found was comparing txParams.to for both the current and existing transactions.
  • So any prior send of the same token (to any address) was treated as "same recipient" and the API call to determine isFirstTimeInteraction was skipped, so the alert never showed for a new recipient.

Solution

  • Introduce getEffectiveRecipient(tx): for token transfer types, decode txParams.data and use the _to/to argument as the effective recipient; otherwise use txParams.to.
  • When looking for an existing transaction to skip the API call, compare effective recipient (and chain + from) instead of txParams.to.
  • Result: we only skip when there is already a tx with the same actual recipient (e.g. duplicate or pending). Sending the same token to a different address no longer suppresses the first-time interaction check.

Changes

  • first-time-interaction.ts: Added TOKEN_TRANSFER_TYPES and getEffectiveRecipient(), and updated the existingTransactions.find() to use effective recipient for comparison.
  • first-time-interaction.test.ts: Added tests for (1) proceeding when existing tx has same contract but different decoded recipient, and (2) returning early when existing tx has same effective recipient.

References

Fixes MetaMask/metamask-mobile#26319

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

Medium Risk
Changes how updateFirstTimeInteraction decides to skip the accounts-API call by decoding token-transfer recipients; this affects when first-time-interaction warnings are set and may increase API calls for token transfers if decoding differs or fails.

Overview
Fixes first-time interaction detection for token transfers by comparing effective recipients (decoded from txParams.data) rather than txParams.to when deciding whether an existing transaction already covers the interaction.

Adds getEffectiveRecipient and updates the existing-transaction short-circuit to match on chainId + from + decoded recipient, plus new tests covering ERC20 same-contract/different-recipient vs same-recipient behavior; changelog updated.

Written by Cursor Bugbot for commit 9117a7e. This will update automatically on new commits. Configure here.

@vinistevam vinistevam marked this pull request as ready for review March 6, 2026 11:51
@vinistevam vinistevam requested review from a team as code owners March 6, 2026 11:51
@vinistevam
Copy link
Contributor Author

@metamaskbot publish-previews

Copy link

@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.

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

@github-actions
Copy link
Contributor

github-actions bot commented Mar 6, 2026

Preview builds have been published. See these instructions for more information about preview builds.

Expand for full list of packages and versions.
{
  "@metamask-previews/account-tree-controller": "4.1.1-preview-327d86601",
  "@metamask-previews/accounts-controller": "36.0.1-preview-327d86601",
  "@metamask-previews/address-book-controller": "7.0.1-preview-327d86601",
  "@metamask-previews/ai-controllers": "0.2.0-preview-327d86601",
  "@metamask-previews/analytics-controller": "1.0.0-preview-327d86601",
  "@metamask-previews/analytics-data-regulation-controller": "0.0.0-preview-327d86601",
  "@metamask-previews/announcement-controller": "8.0.0-preview-327d86601",
  "@metamask-previews/app-metadata-controller": "2.0.0-preview-327d86601",
  "@metamask-previews/approval-controller": "8.0.0-preview-327d86601",
  "@metamask-previews/assets-controller": "2.2.0-preview-327d86601",
  "@metamask-previews/assets-controllers": "100.1.0-preview-327d86601",
  "@metamask-previews/base-controller": "9.0.0-preview-327d86601",
  "@metamask-previews/base-data-service": "0.0.0-preview-327d86601",
  "@metamask-previews/bridge-controller": "68.0.0-preview-327d86601",
  "@metamask-previews/bridge-status-controller": "68.0.0-preview-327d86601",
  "@metamask-previews/build-utils": "3.0.4-preview-327d86601",
  "@metamask-previews/chain-agnostic-permission": "1.4.0-preview-327d86601",
  "@metamask-previews/claims-controller": "0.4.2-preview-327d86601",
  "@metamask-previews/client-controller": "1.0.0-preview-327d86601",
  "@metamask-previews/compliance-controller": "1.0.1-preview-327d86601",
  "@metamask-previews/composable-controller": "12.0.0-preview-327d86601",
  "@metamask-previews/config-registry-controller": "0.1.0-preview-327d86601",
  "@metamask-previews/connectivity-controller": "0.1.0-preview-327d86601",
  "@metamask-previews/controller-utils": "11.19.0-preview-327d86601",
  "@metamask-previews/core-backend": "6.0.0-preview-327d86601",
  "@metamask-previews/delegation-controller": "2.0.1-preview-327d86601",
  "@metamask-previews/earn-controller": "11.1.1-preview-327d86601",
  "@metamask-previews/eip-5792-middleware": "3.0.0-preview-327d86601",
  "@metamask-previews/eip-7702-internal-rpc-middleware": "0.1.0-preview-327d86601",
  "@metamask-previews/eip1193-permission-middleware": "1.0.3-preview-327d86601",
  "@metamask-previews/ens-controller": "19.0.3-preview-327d86601",
  "@metamask-previews/error-reporting-service": "3.0.1-preview-327d86601",
  "@metamask-previews/eth-block-tracker": "15.0.1-preview-327d86601",
  "@metamask-previews/eth-json-rpc-middleware": "23.1.0-preview-327d86601",
  "@metamask-previews/eth-json-rpc-provider": "6.0.0-preview-327d86601",
  "@metamask-previews/foundryup": "1.0.1-preview-327d86601",
  "@metamask-previews/gas-fee-controller": "26.0.3-preview-327d86601",
  "@metamask-previews/gator-permissions-controller": "2.0.0-preview-327d86601",
  "@metamask-previews/geolocation-controller": "0.1.0-preview-327d86601",
  "@metamask-previews/json-rpc-engine": "10.2.3-preview-327d86601",
  "@metamask-previews/json-rpc-middleware-stream": "8.0.8-preview-327d86601",
  "@metamask-previews/keyring-controller": "25.1.0-preview-327d86601",
  "@metamask-previews/logging-controller": "7.0.1-preview-327d86601",
  "@metamask-previews/message-manager": "14.1.0-preview-327d86601",
  "@metamask-previews/messenger": "0.3.0-preview-327d86601",
  "@metamask-previews/multichain-account-service": "7.0.0-preview-327d86601",
  "@metamask-previews/multichain-api-middleware": "1.2.7-preview-327d86601",
  "@metamask-previews/multichain-network-controller": "3.0.4-preview-327d86601",
  "@metamask-previews/multichain-transactions-controller": "7.0.1-preview-327d86601",
  "@metamask-previews/name-controller": "9.0.0-preview-327d86601",
  "@metamask-previews/network-controller": "30.0.0-preview-327d86601",
  "@metamask-previews/network-enablement-controller": "4.2.0-preview-327d86601",
  "@metamask-previews/notification-services-controller": "22.0.0-preview-327d86601",
  "@metamask-previews/permission-controller": "12.2.0-preview-327d86601",
  "@metamask-previews/permission-log-controller": "5.0.0-preview-327d86601",
  "@metamask-previews/perps-controller": "1.0.0-preview-327d86601",
  "@metamask-previews/phishing-controller": "16.3.0-preview-327d86601",
  "@metamask-previews/polling-controller": "16.0.3-preview-327d86601",
  "@metamask-previews/preferences-controller": "22.1.0-preview-327d86601",
  "@metamask-previews/profile-metrics-controller": "3.0.1-preview-327d86601",
  "@metamask-previews/profile-sync-controller": "27.1.0-preview-327d86601",
  "@metamask-previews/ramps-controller": "10.2.0-preview-327d86601",
  "@metamask-previews/rate-limit-controller": "7.0.0-preview-327d86601",
  "@metamask-previews/remote-feature-flag-controller": "4.1.0-preview-327d86601",
  "@metamask-previews/sample-controllers": "4.0.3-preview-327d86601",
  "@metamask-previews/seedless-onboarding-controller": "8.1.0-preview-327d86601",
  "@metamask-previews/selected-network-controller": "26.0.3-preview-327d86601",
  "@metamask-previews/shield-controller": "5.0.1-preview-327d86601",
  "@metamask-previews/signature-controller": "39.0.4-preview-327d86601",
  "@metamask-previews/storage-service": "1.0.0-preview-327d86601",
  "@metamask-previews/subscription-controller": "6.0.0-preview-327d86601",
  "@metamask-previews/transaction-controller": "62.20.0-preview-327d86601",
  "@metamask-previews/transaction-pay-controller": "16.3.0-preview-327d86601",
  "@metamask-previews/user-operation-controller": "41.0.3-preview-327d86601"
}

jpuri
jpuri previously approved these changes Mar 9, 2026
tx.txParams.to?.toLowerCase() === to?.toLowerCase() &&
tx.id !== transactionId,
tx.txParams?.from?.toLowerCase() === from?.toLowerCase() &&
getEffectiveRecipient(tx)?.toLowerCase() === recipientLower,
Copy link
Member

Choose a reason for hiding this comment

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

Nice fix!

Comment on lines 84 to 92
Copy link
Member

Choose a reason for hiding this comment

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

Shall we use new getEffectiveRecipient utility to prevent duplication?

recipient = getEffectiveRecipient(transactionMeta);

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Great catch! I pushed the changes here 80b82cc

OGPoyraz
OGPoyraz previously approved these changes Mar 10, 2026
@vinistevam vinistevam requested a review from OGPoyraz March 10, 2026 10:37
@vinistevam vinistevam added this pull request to the merge queue Mar 10, 2026
Merged via the queue into main with commit 5d62abd Mar 10, 2026
322 checks passed
@vinistevam vinistevam deleted the fix/first-time-interaction-erc20-recipient-check branch March 10, 2026 11:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Issues with 1st time interacting with alert

3 participants