Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a72f301fe1 |
@@ -1474,23 +1474,24 @@ tracked.
|
|||||||
|
|
||||||
A tracked token is shown when its balance is nonzero, and any other ERC-20 when
|
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
|
its balance is nonzero and it is in the bundled known-token list or has 1,000 or
|
||||||
more holders. On Ethereum Mainnet, a token claiming a symbol from the bundled
|
more holders. On Ethereum Mainnet, a token that claims a bundled token's symbol
|
||||||
list from any other contract address is always dropped, tracked or not. On every
|
from another contract is always dropped, tracked or not. On every network, a
|
||||||
network, a token claiming a label of the native asset is always dropped. Those
|
token claiming a label of the native asset is always dropped. Those labels are
|
||||||
labels are `"ETH"` and each network's `nativeCurrency`, such as `"SepoliaETH"`.
|
`"ETH"` and each network's `nativeCurrency`, such as `"SepoliaETH"`. The balance
|
||||||
That filter is unconditional — the "Hide tokens with fewer than 1,000 holders"
|
list applies all three rules whatever the settings say. The "Hide tokens with
|
||||||
setting governs the transaction history and the send-screen token selector, not
|
fewer than 1,000 holders" setting governs only the transaction history and the
|
||||||
this list. A token's holder count is unknown when the explorer reports none, or
|
send-screen token selector. A token's holder count is unknown when the explorer
|
||||||
reports anything other than a whole number written in digits alone, such as
|
reports none, or reports anything other than a whole number written in digits
|
||||||
`1,000` or `1e3` (`parseHoldersCount()` in `src/shared/holders.js`). This list
|
alone, such as `1,000` or `1e3` (`parseHoldersCount()` in
|
||||||
does not take an unknown count as 1,000 or more, so such a token is shown only
|
`src/shared/holders.js`). This list does not take an unknown count as 1,000 or
|
||||||
when it is on the bundled list or tracked. Every nonzero holding of a token
|
more, so such a token is shown only when it is on the bundled list or tracked.
|
||||||
shown is stored exactly, however small, but a holding below 0.000001 is left out
|
Every nonzero holding of a token shown is stored exactly, however small, but a
|
||||||
of the balance lists, the send-screen token selector, the address total and the
|
holding below 0.000001 is left out of the balance lists, the send-screen token
|
||||||
remove-address warning (`isBelowOneMillionth()` in
|
selector, the address total and the remove-address warning
|
||||||
`src/shared/amountDisplay.js`). The Send and confirmation screens show it when
|
(`isBelowOneMillionth()` in `src/shared/amountDisplay.js`). The Send and
|
||||||
its token is the one being sent. Tracked tokens with a zero balance are listed
|
confirmation screens show it when its token is the one being sent. Tracked
|
||||||
as well while "Show tracked tokens with zero balance" is on.
|
tokens with a zero balance are listed as well while "Show tracked tokens with
|
||||||
|
zero balance" is on.
|
||||||
|
|
||||||
#### Stored state and its version
|
#### Stored state and its version
|
||||||
|
|
||||||
@@ -3198,27 +3199,25 @@ indexes it as a real token transfer.
|
|||||||
Ethereum mainnet ERC-20s taken from the CoinGecko API, with decimals verified
|
Ethereum mainnet ERC-20s taken from the CoinGecko API, with decimals verified
|
||||||
on-chain and addresses EIP-55 checksummed; `TOKENS` in
|
on-chain and addresses EIP-55 checksummed; `TOKENS` in
|
||||||
`src/shared/tokenList.js` is the authoritative set. It is bundled at build
|
`src/shared/tokenList.js` is the authoritative set. It is bundled at build
|
||||||
time and only changes when that file is regenerated. On Ethereum Mainnet, any
|
time and only changes when that file is regenerated. On Ethereum Mainnet, a
|
||||||
token transfer claiming a symbol from this list (e.g. "ETH", "USDT", "USDC")
|
token that claims a symbol from this list, such as "USDT" or "USDC", is a
|
||||||
but originating from an unrecognized contract address is identified as a spoof
|
spoof unless its contract is the listed one. The wallet hides it. The fake
|
||||||
and filtered from display. On another network, the list's symbols are not
|
"Ethereum" token in the attack above used symbol "ETH" from contract
|
||||||
checked, because the list holds mainnet contracts. The fake "Ethereum" token
|
`0xD05339f9Ea5ab9d9F03B9d57F671d2abD1F55c82`. No contract may bear "ETH", so
|
||||||
in the attack above used symbol "ETH" from contract
|
that token is a spoof. Detecting a spoof is also what adds a contract to the
|
||||||
`0xD05339f9Ea5ab9d9F03B9d57F671d2abD1F55c82`, which does not match the known
|
fraud contract blocklist below; that is the only thing that populates it. In
|
||||||
WETH contract — so it would be caught by this check. Detecting a spoof is also
|
the transaction history the check is the "Hide fake tokens impersonating a
|
||||||
what adds a contract to the fraud contract blocklist below; that is the only
|
known symbol" setting, on by default; with it off, spoofed transfers are shown
|
||||||
thing that populates it. In the transaction history the check is the "Hide
|
and no new blocklist entries are learned from them. The send-screen token
|
||||||
fake tokens impersonating a known symbol" setting, on by default; with it off,
|
selector and the balance list apply the same check unconditionally, because
|
||||||
spoofed transfers are shown and no new blocklist entries are learned from
|
they decide which tokens the user can act on and what the user believes they
|
||||||
them. The send-screen token selector and the balance list apply the same check
|
own rather than what the history displays. All three surfaces read the rule
|
||||||
unconditionally, because they decide which tokens the user can act on and what
|
from `src/shared/symbolSpoof.js`, so they cannot answer the question
|
||||||
the user believes they own rather than what the history displays. All three
|
differently. A symbol the list maps to no contract at all — the native asset's
|
||||||
surfaces read the rule from `src/shared/symbolSpoof.js`, so they cannot answer
|
labels: `"ETH"` and every network's `nativeCurrency`, such as `"SepoliaETH"`,
|
||||||
the question differently. A symbol the list maps to no contract at all — the
|
on every network — may be borne by no contract, so every ERC-20 claiming it is
|
||||||
native asset's labels: `"ETH"` and every network's `nativeCurrency`, such as
|
a spoof on all three. The user's real ETH balance is not an ERC-20 and is read
|
||||||
`"SepoliaETH"`, on every network — may be borne by no contract, so every
|
over RPC, so the rule never sees it.
|
||||||
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
|
- **Low-holder token filtering**: Token transfers from ERC-20 contracts with
|
||||||
fewer than 1,000 holders are hidden from transaction history by default.
|
fewer than 1,000 holders are hidden from transaction history by default.
|
||||||
|
|||||||
@@ -3978,7 +3978,8 @@ function bundledToken(address, chainId) {
|
|||||||
// hides from the balance list, the history and the send selector at its own
|
// hides from the balance list, the history and the send selector at its own
|
||||||
// address, so the user cannot spend it (issue #276). Naming every address
|
// address, so the user cannot spend it (issue #276). Naming every address
|
||||||
// that bears the symbol is the only shape that says what is true; it does not
|
// that bears the symbol is the only shape that says what is true; it does not
|
||||||
// loosen the rule, because a contract outside the set is still a spoof.
|
// loosen the rule. On Ethereum Mainnet, a contract outside the set is still a
|
||||||
|
// spoof.
|
||||||
const KNOWN_SYMBOLS = new Map();
|
const KNOWN_SYMBOLS = new Map();
|
||||||
KNOWN_SYMBOLS.set("ETH", null);
|
KNOWN_SYMBOLS.set("ETH", null);
|
||||||
for (const network of Object.values(NETWORKS)) {
|
for (const network of Object.values(NETWORKS)) {
|
||||||
|
|||||||
Reference in New Issue
Block a user