Analysing ERC20 activity accurately
The fact that ERC20 is nowadays the most widely used standard for smart contracts is a blessing in disguise. It allows the economy of tokens on the Ethereum blockchain to run fairly smoothly and enables many cross-contract behavior. But in most of the analyses that I have seen, there is a definite overconfidence in the standard.
If you read the definition of the ERC20 standard you will find something well written and quite straight forward. But you will most likely also overlook one small detail that can make the world of difference in analyzing some contracts. It is in the relationship between the transfer() and transferFrom() methods and the Transfer() event. Take a look at this transaction for example.
Tools like Etherscan consider that there were 1000 tokens transferred by this message call. But upon closer inspection the method is called “MassNotify”. It doesn’t sound like a transfer to me. So what happened there? Why does it seem that 1000 tokens were issued when it is not the case?
The answer lies in this little detail that is easily overlooked: Transfer() must be triggered by token transfers, but it could be triggered for other reasons too! The wording of the standard is the following:
MUST trigger when tokens are transferred, including zero value transfers.
In the contract above what is called “virtual tokens” are issued at will and accounts are “notified” about it using the Transfer() event. That means that they are entered in a list of accounts that may transfer up to 10 tokens, provided it does not make the general supply reach the fixed limit. But until they do so, nothing in the contract ensures that they do have a token to spend. Such virtual tokens could be generated ad infinitum and completely throw off analyses of ERC20 tokens. The issue here in the etherscan analysis is that they used the Transfer() event log to get the information, which at the present state of the standard is not reliable.
You could suggest that we only count transfer() and transferFrom() message calls, but that would be a mistake again. Indeed nothing in the ERC20 standard currently suggests that these methods can only be called externally, by a message call. One could be called internally, inside another method. For example one could have an ERC20 contract with a shuffleAccounts(n) method, making n random calls to transferFrom(). That would appear in the Transfer() logs but not be seen by the method described above.
I suggest that any analysis of ERC20 token activity be preceded by a review of the contract’s code generating a list of method calls to be cross referenced with. As for virtual tokens, there is no way to know the individual state of accounts before they make their first use of their virtual tokens. I propose that in this case, counts should be capped by the total supply.