44 lines
1.9 KiB
JavaScript
44 lines
1.9 KiB
JavaScript
// The known-symbol spoof rule, in one place.
|
|
//
|
|
// A token that borrows a known symbol from a contract that is not the one
|
|
// that symbol belongs to is a spoof, and the wallet hides it. Three surfaces
|
|
// ask that question — the transaction history, the Send token selector and
|
|
// the balance list — and they must answer it identically: a token the history
|
|
// calls fake while the balance list lists it as a holding is worse than
|
|
// either verdict alone, because the balance list is where the user forms
|
|
// their belief about what they own (issue #235).
|
|
//
|
|
// KNOWN_SYMBOLS maps a symbol to the lowercased contract address that may
|
|
// bear it, or to null. Null means the symbol belongs to the native asset,
|
|
// which has no contract at all, so no contract may bear it and every one
|
|
// that does is a spoof. "ETH" is the only such entry today; the rule is
|
|
// written so that a second one needs no change here or at any call site.
|
|
|
|
const { KNOWN_SYMBOLS } = require("./tokenList");
|
|
|
|
// Ethereum addresses are case-insensitive: EIP-55 mixed case is a checksum
|
|
// over the address, not part of its identity.
|
|
function normalizeAddress(addr) {
|
|
return (addr || "").toLowerCase();
|
|
}
|
|
|
|
// True when a token bearing `symbol` from contract `contractAddress` is
|
|
// impersonating a known symbol.
|
|
//
|
|
// An empty contract address is the native asset, which is never a spoof:
|
|
// this is what keeps the user's real ETH out of the rule, and it holds for
|
|
// any symbol that becomes null-mapped later, not just for ETH.
|
|
function isSpoofedSymbol(symbol, contractAddress) {
|
|
const contract = normalizeAddress(contractAddress);
|
|
if (!contract) return false;
|
|
const sym = (symbol || "").toUpperCase();
|
|
if (!KNOWN_SYMBOLS.has(sym)) return false;
|
|
const legit = KNOWN_SYMBOLS.get(sym);
|
|
if (legit === null) return true;
|
|
return contract !== normalizeAddress(legit);
|
|
}
|
|
|
|
module.exports = {
|
|
isSpoofedSymbol,
|
|
};
|