fix: the bundled token list names tokens on Ethereum Mainnet only (closes #632)
bundledToken(address, chainId) in tokenList.js answers only for Ethereum Mainnet's chain id. Every reader of TOKEN_BY_ADDRESS now goes through it, with the chain id of the transaction, balance or history entry it draws. The token sources the screens build carry that chain id. The Uniswap decoder sets the transaction's chain id on them. fetchTokenBalances() takes the chain id of the network it asks about. isSpoofedSymbol() takes the chain id of the token's network. It checks the bundled list's symbols only on Ethereum Mainnet. The native asset's labels stay reserved on every network. Twenty existing tests and four shared test helpers read the bundled list without naming a network. Each now names Ethereum Mainnet. Model: opus-5-5
This commit was merged in pull request #703.
This commit is contained in:
@@ -1188,11 +1188,12 @@ The wallet takes the `decimals` from these sources, in this order
|
||||
"Use Blockscout" is on (`tokenSourcesByChainId()` in
|
||||
`src/popup/views/helpers.js`).
|
||||
|
||||
The token's name comes from the same sources. While "Use Blockscout" is off, a
|
||||
token gets a line under it when the bundled list and the tracked tokens lack its
|
||||
name or decimals. The line says "Blockscout's report of your balances is not
|
||||
used to name this token, because "Use Blockscout" is off in Settings." These
|
||||
screens show the line:
|
||||
The token's name comes from the same sources. The bundled token list is used
|
||||
only for a token on Ethereum Mainnet. While "Use Blockscout" is off, a token
|
||||
gets a line under it when the bundled list and the tracked tokens lack its name
|
||||
or decimals. The line says "Blockscout's report of your balances is not used to
|
||||
name this token, because "Use Blockscout" is off in Settings." These screens
|
||||
show the line:
|
||||
|
||||
- TxApproval and SignApproval
|
||||
- WaitTx, SuccessTx and ErrorTx, which follow TxApproval
|
||||
@@ -1477,14 +1478,14 @@ tracked.
|
||||
|
||||
A tracked token is shown when its balance is nonzero, and any other ERC-20 when
|
||||
its balance is nonzero and it is in the bundled known-token list or has 1,000 or
|
||||
more holders. The balance list always drops a token that claims a bundled-list
|
||||
symbol from another contract address, whatever the settings. The list also drops
|
||||
every token that claims the native asset's symbol: `"ETH"`, or any network's
|
||||
`nativeCurrency`, such as `"SepoliaETH"`. That filter is unconditional — the
|
||||
"Hide tokens with fewer than 1,000 holders" setting governs the transaction
|
||||
history and the send-screen token selector, not this list. A token's holder
|
||||
count is unknown when the explorer reports none, or reports anything other than
|
||||
a whole number written in digits alone, such as `1,000` or `1e3`
|
||||
more holders. On Ethereum Mainnet, the balance list always drops a token that
|
||||
claims a bundled token's symbol from another contract. On every network, it
|
||||
drops a token that claims a label of the native asset. Those labels are `"ETH"`
|
||||
and each network's `nativeCurrency`, such as `"SepoliaETH"`. The "Hide tokens
|
||||
with fewer than 1,000 holders" setting does not change this list. It governs
|
||||
only the transaction history and the send-screen token selector. A token's
|
||||
holder count is unknown when the explorer reports none, or reports anything
|
||||
other than a whole number written in digits alone, such as `1,000` or `1e3`
|
||||
(`parseHoldersCount()` in `src/shared/holders.js`). This list does not take an
|
||||
unknown count as 1,000 or more, so such a token is shown only when it is on the
|
||||
bundled list or tracked. Every nonzero holding of a token shown is stored
|
||||
@@ -3236,26 +3237,25 @@ indexes it as a real token transfer.
|
||||
Ethereum mainnet ERC-20s taken from the CoinGecko API, with decimals verified
|
||||
on-chain and addresses EIP-55 checksummed; `TOKENS` in
|
||||
`src/shared/tokenList.js` is the authoritative set. It is bundled at build
|
||||
time and only changes when that file is regenerated. Any token transfer
|
||||
claiming a symbol from this list (e.g. "ETH", "USDT", "USDC") but originating
|
||||
from an unrecognized contract address is identified as a spoof and filtered
|
||||
from display. The fake "Ethereum" token in the attack above used symbol "ETH"
|
||||
from contract `0xD05339f9Ea5ab9d9F03B9d57F671d2abD1F55c82`, which does not
|
||||
match the known WETH contract — so it would be caught by this check. Detecting
|
||||
a spoof is also what adds a contract to the fraud contract blocklist below;
|
||||
that is the only thing that populates it. In the transaction history the check
|
||||
is the "Hide fake tokens impersonating a known symbol" setting, on by default;
|
||||
with it off, spoofed transfers are shown and no new blocklist entries are
|
||||
learned from them. The send-screen token selector and the balance list apply
|
||||
the same check unconditionally, because they decide which tokens the user can
|
||||
act on and what the user believes they own rather than what the history
|
||||
displays. All three surfaces read the rule from `src/shared/symbolSpoof.js`,
|
||||
so they cannot answer the question differently. A symbol the list maps to no
|
||||
contract at all — the native asset's labels: `"ETH"` and every network's
|
||||
`nativeCurrency`, such as `"SepoliaETH"`, on every network — may be borne by
|
||||
no contract, so every ERC-20 claiming it is a spoof on all three. The user's
|
||||
real ETH balance is not an ERC-20 and is read over RPC, so the rule never sees
|
||||
it.
|
||||
time and only changes when that file is regenerated. On Ethereum Mainnet, a
|
||||
token that claims a symbol from this list, such as "USDT" or "USDC", is a
|
||||
spoof unless its contract is the listed one. The wallet hides it. The fake
|
||||
"Ethereum" token in the attack above used symbol "ETH" from contract
|
||||
`0xD05339f9Ea5ab9d9F03B9d57F671d2abD1F55c82`. No contract may bear "ETH", so
|
||||
that token is a spoof. Detecting a spoof is also what adds a contract to the
|
||||
fraud contract blocklist below; that is the only thing that populates it. In
|
||||
the transaction history the check is the "Hide fake tokens impersonating a
|
||||
known symbol" setting, on by default; with it off, spoofed transfers are shown
|
||||
and no new blocklist entries are learned from them. The send-screen token
|
||||
selector and the balance list apply the same check unconditionally, because
|
||||
they decide which tokens the user can act on and what the user believes they
|
||||
own rather than what the history displays. All three surfaces read the rule
|
||||
from `src/shared/symbolSpoof.js`, so they cannot answer the question
|
||||
differently. A symbol the list maps to no contract at all — the native asset's
|
||||
labels: `"ETH"` and every network's `nativeCurrency`, such as `"SepoliaETH"`,
|
||||
on every network — may be borne by no contract, so every ERC-20 claiming it is
|
||||
a spoof on all three. The user's real ETH balance is not an ERC-20 and is read
|
||||
over RPC, so the rule never sees it.
|
||||
|
||||
- **Low-holder token filtering**: Token transfers from ERC-20 contracts with
|
||||
fewer than 1,000 holders are hidden from transaction history by default.
|
||||
|
||||
Reference in New Issue
Block a user