Skip to content

Commit

Permalink
chore(cherry-pick): fix erc20 token balances showing 0 (#29365)
Browse files Browse the repository at this point in the history
cherry picks #29361
to v12.9.3
  • Loading branch information
bergeron authored Dec 19, 2024
1 parent 9e42c34 commit 46562e0
Show file tree
Hide file tree
Showing 6 changed files with 342 additions and 3 deletions.
61 changes: 61 additions & 0 deletions .yarn/patches/@metamask-assets-controllers-patch-d6ed5f8213.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
diff --git a/dist/multicall.cjs b/dist/multicall.cjs
index bf9aa5e86573fc1651f421cc0b64f5af121c3ab2..43a0531ed86cd3ee1774dcda3f990dd40f7f52de 100644
--- a/dist/multicall.cjs
+++ b/dist/multicall.cjs
@@ -342,9 +342,22 @@ const multicallOrFallback = async (calls, chainId, provider, maxCallsPerMultical
return [];
}
const multicallAddress = MULTICALL_CONTRACT_BY_CHAINID[chainId];
- return await (multicallAddress
- ? multicall(calls, multicallAddress, provider, maxCallsPerMulticall)
- : fallback(calls, maxCallsParallel));
+ if (multicallAddress) {
+ try {
+ return await multicall(calls, multicallAddress, provider, maxCallsPerMulticall);
+ }
+ catch (error) {
+ // Fallback only on revert
+ // https://docs.ethers.org/v5/troubleshooting/errors/#help-CALL_EXCEPTION
+ if (!error ||
+ typeof error !== 'object' ||
+ !('code' in error) ||
+ error.code !== 'CALL_EXCEPTION') {
+ throw error;
+ }
+ }
+ }
+ return await fallback(calls, maxCallsParallel);
};
exports.multicallOrFallback = multicallOrFallback;
//# sourceMappingURL=multicall.cjs.map
\ No newline at end of file
diff --git a/dist/multicall.mjs b/dist/multicall.mjs
index 8fbe0112303d5df1d868e0357a9d31e43a3b6cf9..860dfdbddd813659cb2be5f7faed5d4016db5966 100644
--- a/dist/multicall.mjs
+++ b/dist/multicall.mjs
@@ -339,8 +339,21 @@ export const multicallOrFallback = async (calls, chainId, provider, maxCallsPerM
return [];
}
const multicallAddress = MULTICALL_CONTRACT_BY_CHAINID[chainId];
- return await (multicallAddress
- ? multicall(calls, multicallAddress, provider, maxCallsPerMulticall)
- : fallback(calls, maxCallsParallel));
+ if (multicallAddress) {
+ try {
+ return await multicall(calls, multicallAddress, provider, maxCallsPerMulticall);
+ }
+ catch (error) {
+ // Fallback only on revert
+ // https://docs.ethers.org/v5/troubleshooting/errors/#help-CALL_EXCEPTION
+ if (!error ||
+ typeof error !== 'object' ||
+ !('code' in error) ||
+ error.code !== 'CALL_EXCEPTION') {
+ throw error;
+ }
+ }
+ }
+ return await fallback(calls, maxCallsParallel);
};
//# sourceMappingURL=multicall.mjs.map
\ No newline at end of file
185 changes: 185 additions & 0 deletions app/scripts/migrations/133.2.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
import { migrate, version } from './133.2';

const oldVersion = 133.1;

describe(`migration #${version}`, () => {
it('updates the version metadata', async () => {
const oldStorage = {
meta: { version: oldVersion },
data: {},
};
const newStorage = await migrate(oldStorage);
expect(newStorage.meta).toStrictEqual({ version });
});

it('does nothing if theres no tokens controller state defined', async () => {
const oldStorage = {
meta: { version: oldVersion },
data: {},
};
const newStorage = await migrate(oldStorage);
expect(newStorage.data).toStrictEqual(oldStorage.data);
});

it('does nothing if theres empty tokens controller state', async () => {
const oldStorage = {
meta: { version: oldVersion },
data: {
TokensController: {},
},
};
const newStorage = await migrate(oldStorage);
expect(newStorage.data).toStrictEqual(oldStorage.data);
});

it('does nothing if theres empty tokens controller state for allTokens', async () => {
const oldStorage = {
meta: { version: oldVersion },
data: {
TokensController: {
allTokens: {},
},
},
};
const newStorage = await migrate(oldStorage);
expect(newStorage.data).toStrictEqual(oldStorage.data);
});

it('does nothing if theres empty tokens controller state for mainnet', async () => {
const oldStorage = {
meta: { version: oldVersion },
data: {
TokensController: {
allTokens: {
'0x1': {},
},
},
},
};
const newStorage = await migrate(oldStorage);
expect(newStorage.data).toStrictEqual(oldStorage.data);
});

it('Does nothing if theres no tokens with empty address', async () => {
const oldStorage = {
meta: { version: oldVersion },
data: {
TokensController: {
allTokens: {
'0x1': {
'0x123': [
{ address: '0x1', symbol: 'TOKEN1', decimals: 18 },
{ address: '0x2', symbol: 'TOKEN2', decimals: 18 },
],
'0x123456': [
{ address: '0x3', symbol: 'TOKEN3', decimals: 18 },
{ address: '0x4', symbol: 'TOKEN4', decimals: 18 },
],
},
},
},
},
};
const newStorage = await migrate(oldStorage);
expect(newStorage.data).toStrictEqual(oldStorage.data);
});

it('Removes tokens with empty address', async () => {
const oldStorage = {
meta: { version: oldVersion },
data: {
TokensController: {
allTokens: {
'0x1': {
'0x123': [
{
address: '0x0000000000000000000000000000000000000000',
symbol: 'eth',
decimals: 18,
},
{ address: '0x2', symbol: 'TOKEN2', decimals: 18 },
],
},
},
},
},
};
const newStorage = await migrate(oldStorage);
expect(newStorage.data).toStrictEqual({
TokensController: {
allTokens: {
'0x1': {
'0x123': [{ address: '0x2', symbol: 'TOKEN2', decimals: 18 }],
},
},
},
});
});

it('Removes tokens with empty address across multiple accounts', async () => {
const oldStorage = {
meta: { version: oldVersion },
data: {
TokensController: {
allTokens: {
'0x1': {
'0x123': [
{
address: '0x0000000000000000000000000000000000000000',
symbol: 'eth',
decimals: 18,
},
{ address: '0x2', symbol: 'TOKEN2', decimals: 18 },
],
'0x456': [
{
address: '0x0000000000000000000000000000000000000000',
symbol: 'eth',
decimals: 18,
},
{ address: '0x3', symbol: 'TOKEN3', decimals: 18 },
],
'0x789': [{ address: '0x4', symbol: 'TOKEN4', decimals: 18 }],
},
},
},
},
};
const newStorage = await migrate(oldStorage);
expect(newStorage.data).toStrictEqual({
TokensController: {
allTokens: {
'0x1': {
'0x123': [{ address: '0x2', symbol: 'TOKEN2', decimals: 18 }],
'0x456': [{ address: '0x3', symbol: 'TOKEN3', decimals: 18 }],
'0x789': [{ address: '0x4', symbol: 'TOKEN4', decimals: 18 }],
},
},
},
});
});

it('Does not change state on chains other than mainnet', async () => {
const oldStorage = {
meta: { version: oldVersion },
data: {
TokensController: {
allTokens: {
'0x999': {
'0x123': [
{
address: '0x0000000000000000000000000000000000000000',
symbol: 'eth',
decimals: 18,
},
{ address: '0x2', symbol: 'TOKEN2', decimals: 18 },
],
},
},
},
},
};
const newStorage = await migrate(oldStorage);
expect(newStorage.data).toStrictEqual(oldStorage.data);
});
});
53 changes: 53 additions & 0 deletions app/scripts/migrations/133.2.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { hasProperty, isObject } from '@metamask/utils';
import { cloneDeep } from 'lodash';

type VersionedData = {
meta: { version: number };
data: Record<string, unknown>;
};

export const version = 133.2;

/**
* This migration removes tokens on mainnet with the
* zero address, since this is not a valid erc20 token.
*
* @param originalVersionedData - Versioned MetaMask extension state, exactly
* what we persist to disk.
* @returns Updated versioned MetaMask extension state.
*/
export async function migrate(
originalVersionedData: VersionedData,
): Promise<VersionedData> {
const versionedData = cloneDeep(originalVersionedData);
versionedData.meta.version = version;
transformState(versionedData.data);
return versionedData;
}

function transformState(state: Record<string, unknown>): void {
if (
!hasProperty(state, 'TokensController') ||
!isObject(state.TokensController) ||
!isObject(state.TokensController.allTokens)
) {
return;
}

const chainIds = ['0x1'];

for (const chainId of chainIds) {
const allTokensOnChain = state.TokensController.allTokens[chainId];

if (isObject(allTokensOnChain)) {
for (const [account, tokens] of Object.entries(allTokensOnChain)) {
if (Array.isArray(tokens)) {
allTokensOnChain[account] = tokens.filter(
(token) =>
token?.address !== '0x0000000000000000000000000000000000000000',
);
}
}
}
}
}
1 change: 1 addition & 0 deletions app/scripts/migrations/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ const migrations = [
require('./132'),
require('./133'),
require('./133.1'),
require('./133.2'),
];

export default migrations;
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@
"@metamask/address-book-controller": "^6.0.0",
"@metamask/announcement-controller": "^7.0.0",
"@metamask/approval-controller": "^7.0.0",
"@metamask/assets-controllers": "patch:@metamask/assets-controllers@npm%3A45.1.0#~/.yarn/patches/@metamask-assets-controllers-npm-45.1.0-d914c453f0.patch",
"@metamask/assets-controllers": "patch:@metamask/assets-controllers@patch%3A@metamask/assets-controllers@npm%253A45.1.0%23~/.yarn/patches/@metamask-assets-controllers-npm-45.1.0-d914c453f0.patch%3A%3Aversion=45.1.0&hash=cfcadc#~/.yarn/patches/@metamask-assets-controllers-patch-d6ed5f8213.patch",
"@metamask/base-controller": "^7.0.0",
"@metamask/bitcoin-wallet-snap": "^0.8.2",
"@metamask/browser-passworder": "^4.3.0",
Expand Down
43 changes: 41 additions & 2 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4985,7 +4985,7 @@ __metadata:
languageName: node
linkType: hard

"@metamask/assets-controllers@patch:@metamask/assets-controllers@npm%3A45.1.0#~/.yarn/patches/@metamask-assets-controllers-npm-45.1.0-d914c453f0.patch":
"@metamask/assets-controllers@patch:@metamask/assets-controllers@npm%3A45.1.0#~/.yarn/patches/@metamask-assets-controllers-npm-45.1.0-d914c453f0.patch::version=45.1.0&hash=cfcadc":
version: 45.1.0
resolution: "@metamask/assets-controllers@patch:@metamask/assets-controllers@npm%3A45.1.0#~/.yarn/patches/@metamask-assets-controllers-npm-45.1.0-d914c453f0.patch::version=45.1.0&hash=cfcadc"
dependencies:
Expand Down Expand Up @@ -5024,6 +5024,45 @@ __metadata:
languageName: node
linkType: hard

"@metamask/assets-controllers@patch:@metamask/assets-controllers@patch%3A@metamask/assets-controllers@npm%253A45.1.0%23~/.yarn/patches/@metamask-assets-controllers-npm-45.1.0-d914c453f0.patch%3A%3Aversion=45.1.0&hash=cfcadc#~/.yarn/patches/@metamask-assets-controllers-patch-d6ed5f8213.patch":
version: 45.1.0
resolution: "@metamask/assets-controllers@patch:@metamask/assets-controllers@patch%3A@metamask/assets-controllers@npm%253A45.1.0%23~/.yarn/patches/@metamask-assets-controllers-npm-45.1.0-d914c453f0.patch%3A%3Aversion=45.1.0&hash=cfcadc#~/.yarn/patches/@metamask-assets-controllers-patch-d6ed5f8213.patch::version=45.1.0&hash=4e79dd"
dependencies:
"@ethereumjs/util": "npm:^8.1.0"
"@ethersproject/abi": "npm:^5.7.0"
"@ethersproject/address": "npm:^5.7.0"
"@ethersproject/bignumber": "npm:^5.7.0"
"@ethersproject/contracts": "npm:^5.7.0"
"@ethersproject/providers": "npm:^5.7.0"
"@metamask/abi-utils": "npm:^2.0.3"
"@metamask/base-controller": "npm:^7.0.2"
"@metamask/contract-metadata": "npm:^2.4.0"
"@metamask/controller-utils": "npm:^11.4.3"
"@metamask/eth-query": "npm:^4.0.0"
"@metamask/metamask-eth-abis": "npm:^3.1.1"
"@metamask/polling-controller": "npm:^12.0.1"
"@metamask/rpc-errors": "npm:^7.0.1"
"@metamask/utils": "npm:^10.0.0"
"@types/bn.js": "npm:^5.1.5"
"@types/uuid": "npm:^8.3.0"
async-mutex: "npm:^0.5.0"
bn.js: "npm:^5.2.1"
cockatiel: "npm:^3.1.2"
immer: "npm:^9.0.6"
lodash: "npm:^4.17.21"
multiformats: "npm:^13.1.0"
single-call-balance-checker-abi: "npm:^1.0.0"
uuid: "npm:^8.3.2"
peerDependencies:
"@metamask/accounts-controller": ^20.0.0
"@metamask/approval-controller": ^7.0.0
"@metamask/keyring-controller": ^19.0.0
"@metamask/network-controller": ^22.0.0
"@metamask/preferences-controller": ^15.0.0
checksum: 10/26260472e67d0995b3730870fed99ba081c421ea64e8ca70f02ca8184fb9350fd2c607b75f45507743ba73d7336e831cc55a7aaf9a32f569a58eb7abb9275451
languageName: node
linkType: hard

"@metamask/auto-changelog@npm:^2.1.0":
version: 2.6.1
resolution: "@metamask/auto-changelog@npm:2.6.1"
Expand Down Expand Up @@ -26596,7 +26635,7 @@ __metadata:
"@metamask/announcement-controller": "npm:^7.0.0"
"@metamask/api-specs": "npm:^0.9.3"
"@metamask/approval-controller": "npm:^7.0.0"
"@metamask/assets-controllers": "patch:@metamask/assets-controllers@npm%3A45.1.0#~/.yarn/patches/@metamask-assets-controllers-npm-45.1.0-d914c453f0.patch"
"@metamask/assets-controllers": "patch:@metamask/assets-controllers@patch%3A@metamask/assets-controllers@npm%253A45.1.0%23~/.yarn/patches/@metamask-assets-controllers-npm-45.1.0-d914c453f0.patch%3A%3Aversion=45.1.0&hash=cfcadc#~/.yarn/patches/@metamask-assets-controllers-patch-d6ed5f8213.patch"
"@metamask/auto-changelog": "npm:^2.1.0"
"@metamask/base-controller": "npm:^7.0.0"
"@metamask/bitcoin-wallet-snap": "npm:^0.8.2"
Expand Down

0 comments on commit 46562e0

Please sign in to comment.