5

There are plenty of examples of reading the balance of an ERC20 token from an address via a balanceOf.call when knowing the token contract address beforehand. However, how would one go about reading the balance of an address without knowing which tokens the address might hold?

For example, a user wishes to know the total balance (ETH + tokens) of his address. What would be the most efficient way of retrieving this information without doing any unnecessary calculations?

Should I just loop through an array of the most popular token contract addresses? Look at the incoming token transfer events? or are there more efficient ways?

Just to specify, I am looking for a solution with a private node not an API.

Examples of pages that have achieved this:

Any help would be greatly appreciated!

3 Answers 3

4

If you're interested in just a relatively small subset of popular ERC20 tokens, then looping over them might be okay.

But if you want everything, I think your best bet is to process the logs as you go and look for Transfer(address,address,uint256) events. For each event, if the source looks like an ERC20 token (e.g. has name/symbol/decimals), do some accounting in your database where you're keeping track of these things.

5
  • Thank you for your help! Just to clarify, what would you say would constitute as a “relatively small subset”? Would you see it being less than 50, 100 or a 1000 tokens? In terms of the log processing, if I understand correctly, this would require keeping track of all the token transfers events occurring at every new block as well as all the transfers that have occurred since block 0 for every Ethereum address currently in use? Or is it somehow possible to access the transfer event logs per account?
    – smirzo
    Commented Jan 13, 2018 at 7:49
  • I was thinking of watching all the Transfer events since block 0. But you probably want to check balanceOf(<address>) for the definitive answer rather than sum up the Transfers, because some token contracts may, e.g., pay interest or deduct transfer fees or other things like that. So i'd use Transfer events to identify the ERC20 contracts, and then I'd call balanceOf(<address>) for each address I saw appear in those Transfer events.
    – user19510
    Commented Jan 13, 2018 at 8:15
  • In terms of what subset is "small," I'd recommend testing balanceOf calls for tokens to see how quickly you can do them. Presumably you're thinking about doing this on the fly when a user wants to see balances, so it's really a performance question of what seems fast enough.
    – user19510
    Commented Jan 13, 2018 at 8:16
  • That makes perfect sense. I’ll try and run some test later and post back with the results.
    – smirzo
    Commented Jan 13, 2018 at 8:35
  • Also, for anyone wondering how to get the Transfer event logs since block 0 I found this related post ethereum.stackexchange.com/q/26621/28839
    – smirzo
    Commented Jan 13, 2018 at 8:38
3

As suggested by @smarx, I went ahead and tested the efficiency of simply looping over a subset of ERC20 contracts with a balanceOf method and here are the results:

Median response time for number of token contracts using the Infura RPC (this includes getting the token symbol, balance and decimals)

  • 1 = 0.6s
  • 10 = 0.8s
  • 50 = 1.2s
  • 100 = 1.5s
  • 200 = 2s
  • 300 = 2.5s
  • 400 = 3s
  • 500 = 3.5s
  • 1000 = 6s

Judging by the fact that there are a total of 410 Ethereum tokens listed on Coinmarketcap, simply looping through 400 token contracts would take about 3s, which might be adequate depending on the use case.

Knowing the tokens which the address holds, would thereby increase the efficiency by about 2.3s (assuming that an average address hold about 5 tokens). This would certainly lead to a better UX, but would also entail extra maintenance overhead in observing the Transfer events.

3

I wrote about this issue here: https://medium.com/@tjayrush/how-many-tokens-do-you-have-eae7233676f1. Summary it’s as difficult as you think it might be.

If you really want every token that your address holds, you have to spin through every transaction.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.