Skip to content

Conversation

@salimtb
Copy link
Contributor

@salimtb salimtb commented Nov 11, 2025

Explanation

Current State

The getBalancesInSingleCall function in AssetsContractController was previously using a direct contract call to the single-call balance checker contract (SINGLE_CALL_BALANCES_ADDRESS_BY_CHAINID). This approach had limited chain coverage as the contract was only deployed on a subset of networks.

Solution

This PR refactors getBalancesInSingleCall to use the getTokenBalancesForMultipleAddresses utility function, which leverages Multicall3's aggregate3 method. This provides:

  1. Better chain coverage: Multicall3 is deployed on significantly more networks (30+ chains vs the limited set in the old contract)
  2. Unified multicall infrastructure: Reuses existing multicall utilities instead of maintaining separate balance checking logic
  3. Consistent behavior: Maintains the same external API while improving internal implementation

Key Changes

  1. AssetsContractController.ts

    • Replaced direct contract interaction with getTokenBalancesForMultipleAddresses
    • Added explicit check for Multicall3 support via MULTICALL_CONTRACT_BY_CHAINID before attempting to fetch balances
    • Returns empty object for unsupported chains (maintaining backward compatibility)
    • Updated balance result mapping to correctly transform from tokenAddress -> userAddress -> BN to tokenAddress -> BN
  2. multicall.ts

    • Exported MULTICALL_CONTRACT_BY_CHAINID constant to enable external chain support checks
  3. Test Updates

    • Replaced problematic Web3Provider.prototype.call mocks (which caused stack overflow errors) with direct mocking of getTokenBalancesForMultipleAddresses
    • Added proper test cleanup with afterEach hooks to restore mocks and clean network mocks using nock.cleanAll()
    • Fixed test in AssetsContractControllerWithNetworkClientId.test.ts to correctly reflect that Sepolia now has Multicall3 support
    • Updated assertions to work with BN objects instead of BigNumber

Non-Obvious Changes

  • The test "should not have balance in a single call after switching to network without token detection support" was updated because Sepolia now supports Multicall3, so both networks return balances (previously only mainnet did)
  • Added afterEach cleanup hooks to prevent test pollution from persistent mocks

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, highlighting breaking changes as necessary
  • I've prepared draft pull requests for clients and consumer packages to resolve any breaking changes

@salimtb
Copy link
Contributor Author

salimtb commented Nov 11, 2025

@metamaskbot publish-preview

@github-actions
Copy link
Contributor

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": "3.0.0-preview-ac25cee",
  "@metamask-previews/accounts-controller": "34.0.0-preview-ac25cee",
  "@metamask-previews/address-book-controller": "7.0.0-preview-ac25cee",
  "@metamask-previews/analytics-controller": "0.0.0-preview-ac25cee",
  "@metamask-previews/announcement-controller": "8.0.0-preview-ac25cee",
  "@metamask-previews/app-metadata-controller": "2.0.0-preview-ac25cee",
  "@metamask-previews/approval-controller": "8.0.0-preview-ac25cee",
  "@metamask-previews/assets-controllers": "88.0.0-preview-ac25cee",
  "@metamask-previews/base-controller": "9.0.0-preview-ac25cee",
  "@metamask-previews/bridge-controller": "60.0.0-preview-ac25cee",
  "@metamask-previews/bridge-status-controller": "60.0.0-preview-ac25cee",
  "@metamask-previews/build-utils": "3.0.4-preview-ac25cee",
  "@metamask-previews/chain-agnostic-permission": "1.2.2-preview-ac25cee",
  "@metamask-previews/claims-controller": "0.2.0-preview-ac25cee",
  "@metamask-previews/composable-controller": "12.0.0-preview-ac25cee",
  "@metamask-previews/controller-utils": "11.15.0-preview-ac25cee",
  "@metamask-previews/core-backend": "4.0.0-preview-ac25cee",
  "@metamask-previews/delegation-controller": "1.0.0-preview-ac25cee",
  "@metamask-previews/earn-controller": "10.0.0-preview-ac25cee",
  "@metamask-previews/eip-5792-middleware": "2.0.0-preview-ac25cee",
  "@metamask-previews/eip-7702-internal-rpc-middleware": "0.1.0-preview-ac25cee",
  "@metamask-previews/eip1193-permission-middleware": "1.0.2-preview-ac25cee",
  "@metamask-previews/ens-controller": "18.0.0-preview-ac25cee",
  "@metamask-previews/error-reporting-service": "3.0.0-preview-ac25cee",
  "@metamask-previews/eth-block-tracker": "14.0.0-preview-ac25cee",
  "@metamask-previews/eth-json-rpc-middleware": "21.0.0-preview-ac25cee",
  "@metamask-previews/eth-json-rpc-provider": "5.0.1-preview-ac25cee",
  "@metamask-previews/foundryup": "1.0.1-preview-ac25cee",
  "@metamask-previews/gas-fee-controller": "25.0.0-preview-ac25cee",
  "@metamask-previews/gator-permissions-controller": "0.4.0-preview-ac25cee",
  "@metamask-previews/json-rpc-engine": "10.1.1-preview-ac25cee",
  "@metamask-previews/json-rpc-middleware-stream": "8.0.8-preview-ac25cee",
  "@metamask-previews/keyring-controller": "24.0.0-preview-ac25cee",
  "@metamask-previews/logging-controller": "7.0.0-preview-ac25cee",
  "@metamask-previews/message-manager": "14.0.0-preview-ac25cee",
  "@metamask-previews/messenger": "0.3.0-preview-ac25cee",
  "@metamask-previews/multichain-account-service": "3.0.0-preview-ac25cee",
  "@metamask-previews/multichain-api-middleware": "1.2.4-preview-ac25cee",
  "@metamask-previews/multichain-network-controller": "2.0.0-preview-ac25cee",
  "@metamask-previews/multichain-transactions-controller": "6.0.0-preview-ac25cee",
  "@metamask-previews/name-controller": "9.0.0-preview-ac25cee",
  "@metamask-previews/network-controller": "25.0.0-preview-ac25cee",
  "@metamask-previews/network-enablement-controller": "3.1.0-preview-ac25cee",
  "@metamask-previews/notification-services-controller": "19.0.0-preview-ac25cee",
  "@metamask-previews/permission-controller": "12.1.0-preview-ac25cee",
  "@metamask-previews/permission-log-controller": "5.0.0-preview-ac25cee",
  "@metamask-previews/phishing-controller": "15.0.0-preview-ac25cee",
  "@metamask-previews/polling-controller": "15.0.0-preview-ac25cee",
  "@metamask-previews/preferences-controller": "21.0.0-preview-ac25cee",
  "@metamask-previews/profile-sync-controller": "26.0.0-preview-ac25cee",
  "@metamask-previews/rate-limit-controller": "7.0.0-preview-ac25cee",
  "@metamask-previews/remote-feature-flag-controller": "2.0.0-preview-ac25cee",
  "@metamask-previews/sample-controllers": "3.0.0-preview-ac25cee",
  "@metamask-previews/seedless-onboarding-controller": "6.1.0-preview-ac25cee",
  "@metamask-previews/selected-network-controller": "25.0.0-preview-ac25cee",
  "@metamask-previews/shield-controller": "2.0.0-preview-ac25cee",
  "@metamask-previews/signature-controller": "36.0.0-preview-ac25cee",
  "@metamask-previews/subscription-controller": "4.0.0-preview-ac25cee",
  "@metamask-previews/token-search-discovery-controller": "4.0.0-preview-ac25cee",
  "@metamask-previews/transaction-controller": "61.1.0-preview-ac25cee",
  "@metamask-previews/transaction-pay-controller": "4.0.0-preview-ac25cee",
  "@metamask-previews/user-operation-controller": "40.0.0-preview-ac25cee"
}

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