I was wondering How does etherscan fetch the number of token holders from a smart contract?
4 Answers
They keep track of Transfer
events emitted by that smart contract. Most likely they record them in an SQL database and maintain a ledger based on these events. The event is defined in the ERC20 https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md
There is no way to look up this information from the smart contract directly. Even though the balances
variable is public, the mapping
data type in Solidity doesn't support enumerating the keys. Reading the low level database of an Ethereum client wouldn't help either since all storage keys are hashed before they are persisted.
-
1I actually tested Etherscan's token holder records the Transfer event on Ropsten. They indeed seem to rely on this event. Token transfer through changing the mapping only (i.e. without Transfer) doesn't appear to appear on Etherscan. Mar 28, 2018 at 17:51
-
Does this mean that the number that they are showing might be missing a few first events?– HosseinMar 28, 2018 at 19:04
-
Normally the contract would emit the Transfer event for everything that changes token balances. Not sure what you mean by a few first events? Mar 28, 2018 at 19:36
-
1@medvedev1088 Not always, if you transfer tokens using the approve/transferFrom mechanism it doesn't emit a Transfer() event. So in that case, Etherscan will miss the transfer– abedDec 30, 2018 at 23:11
-
1@abed: The ERC20 standard does not state that you should emit a
Transfer
event every time you change thebalanceOf
mapping (and even if it did, there is no practical way to enforce it). Emitting this event is under the responsibility of the programmer. A good programmer would add it in every function which changes the mapping, and a bad programmer could even leave it out out every such function. Jul 21, 2019 at 13:04
I have created a standalone tool which does the same.
Take a token contract address
Iterate over all
Transfer
events for token usingeth_getLogs
JSON-RPC APIBuild a local database of these events
Allow you to use SQL to query any account balance on any point of time (block num)
You can find the command line application how to build the database here
The core Python logic is here.
There are some quirks here and there: for example detecting mint / creation event for some tokens is not straightforward. Thus, you will may negative balance on the account receiving initial total supply if you rely on Transfer
event only.
As ERC20 tokens distribution is stored in balances
variable inside the token smart-contract and as variable is public, by listing the transactions in
and out
you can then know all the holding token addresses. As reading a variable state doesn't cost any gas, you can perform this at almost no cost ( other than the power you need to perform the checkings )
Another solution is to host a synchronized node in which you could then check the state of the balances
inside the EVM.
-
1Although the balances mapping is public as you said, you can't loop through them all and check everyone's balance, this is not supported in the base ERC-20 contract– abedDec 30, 2018 at 23:14
There is a free API provider that contains this info (free api key needed): https://ethplorer.io/ https://github.com/EverexIO/Ethplorer/wiki/Ethplorer-API#get-token-info
-
-
1Hi! You might be wondering why this answer got downvoted. Thanks for taking the time to answer, but if you look at the original question, you'll see that the asker wanted to know how Etherscan does something, not how to find that information elsewhere. Apr 18, 2021 at 10:45