This bot detects creation of an impersonating token. For example, the bot will detect when an attacker creates a copy of an existing APE token (ApeCoin), which will be used for subsequent scams. The key to determining whether a token is an impersonator is the token symbol, name and its interface. Tokens deployed from the same address are ignored.
- ERC20
- ERC721
- ERC1155
- Ethereum (1)
- BSC (56)
- Polygon (137)
- Arbitrum (42161)
- Optimism (10)
- Fantom (250)
- Avalanche (43114)
Some protocols can create tokens with the same name. To reduce the noise caused by such tokens, you can specify a name and a symbol that will be ignored. You can either combine them, increasing the accuracy of the check, or specify either symbol or name.
By default, the bot ignores the deployment of Uniswap tokens:
{
"exclude": [
{
"symbol": "UNI-V2"
}
]
}
-
IMPERSONATED-TOKEN-DEPLOYMENT
- Fired when someone deployed an impersonating token
- Severity is always "medium"
- Type is always set to "suspicious"
- Metadata:
newTokenSymbol
: symbol of the deployed tokennewTokenName
: name of the deployed tokenoldTokenSymbol
: symbol of the original tokenoldTokenName
: name of the original tokennewTokenDeployer
: address that deployed a contract that impersonates another tokennewTokenContract
: address of the contract that impersonates another tokenoldTokenDeployer
: address that deployed the original tokenoldTokenContract
: address of the original token contract
-
IMPERSONATED-TOKEN-DEPLOYMENT-POPULAR
- Fired when someone deployed a contract that impersonates a popular token
- Severity is always "high"
- Type is always set to "suspicious"
- Metadata:
newTokenSymbol
: symbol of the deployed tokennewTokenName
: name of the deployed tokenoldTokenSymbol
: symbol of the original tokenoldTokenName
: name of the original tokennewTokenDeployer
: address that deployed a contract that impersonates another tokennewTokenContract
: address of the contract that impersonates another tokenoldTokenDeployer
: address that deployed the original tokenoldTokenContract
: address of the original token contract
Alert IMPERSONATED-TOKEN-DEPLOYMENT
for "GOLIATH (Goliath)" token:
$ npm run tx 0xd9eef1565c3e580a207855aa76baab84033c79f1accf449b1d3848d5e9c795a9
The bot uses tokens collected at runtime as well as pre-generated tokens.
Token data is located in the data folder. Each chain uses its own file.
For example, for the Mainnet
, the file will be called chain-1.csv
, since 1 is the id of that network.
Pre-generated token data can be collected in two ways.
All you need to do is run the following command, passing an id of the desired network:
$ npm run fetch:auto 137
For instance, this command starts scanning blocks of the last 28 days on the Polygon network. The script searches for tokens by their traces in transaction events. If a discovered token has a similar hash to a previously discovered one, the script finds the most popular one. If the new token is more popular, it will be written to the end of the data file, so that it will overwrite the previous one. If the previous token is more popular, the new token will be ignored.
All tokens found will be written to the chain-137.csv
file. Also, a state file chain-137.fetcher.json
will be created,
which will contain the scanned range of blocks, and which can be used by the script for optimizations in subsequent runs.
The most accurate way to generate data is to use prepared list of token addresses. It can be obtained from services such as dune.com.
For example, this query allows you to get the most popular erc20 tokens for 3 months:
SELECT contract_address, events
FROM (
SELECT
COALESCE(transfer_table.contract_address, approval_table.contract_address) as contract_address,
COALESCE(transfer_count, 0) + COALESCE(approval_count, 0) as events
FROM (
SELECT contract_address, COUNT(DISTINCT "spender") as approval_count
FROM erc20."ERC20_evt_Approval"
WHERE evt_block_time >= now() - interval '3' month
GROUP BY contract_address
) as approval_table
FULL OUTER JOIN (
SELECT contract_address, COUNT(DISTINCT "to") as transfer_count
FROM erc20."ERC20_evt_Transfer"
WHERE evt_block_time >= now() - interval '3' month
GROUP BY contract_address
) as transfer_table
ON (transfer_table.contract_address = approval_table.contract_address)
) as events_table
WHERE events >= 50
ORDER BY events DESC
The list of token addresses must be placed in the data folder, named chain-{ID}.list.erc{INTERFACE}.csv. Where {ID} is a chain id of the tokens and {INTERFACE} is the tokens standard (20, 721, 1155).
Then you have to run the following command, which will do everything automatically:
$ npm run fetch:list {ID}
Beware, if you change hash function, you should re-generate token data
You can also specify a custom RPC server for each network separately. By default, the project stores the network configurations in the networks.config.json file.
You can find suitable open RPC servers on https://chainlist.org.