The ERC20 Token Standard dictates that functions transfer and transferFrom should return true for success and false for failure.

However, various ERC20 tokens deployed on the network have not implemented this requirement.

Subsequently, how would you go about asserting success or failure?

The only way that comes to mind is this:

uint256 prevSourceBalance = token.balanceOf(address(this));
uint256 prevTargetBalance = token.balanceOf(to);
token.transfer(to, amount);
uint256 currSourceBalance = token.balanceOf(address(this));
uint256 currTargetBalance = token.balanceOf(to);
assert(currSourceBalance == prevSourceBalance - amount);
assert(currTargetBalance == prevTargetBalance + amount);

But this verification method effectively adds a restriction which is not a part of the standard:

Function transfer can theoretically:

  • Return true without setting these balances correctly
  • Return false after setting these balances correctly

Is this restriction considered "legitimate enough" for me to impose it?

Otherwise, would you have any idea how else could I assert success or failure?

Thank you!!!

1 Answer 1


The problem with ERC20 (and any token standard) validation is that it's near impossible to determine whether a contract is truly ERC20 compatible or not (and what does it even require for a contract to be fully compatible). Here's some more reading about it (and in its links): Confusion regarding total number of ERC-721 Tokens . That answer is about ERC721 but the same applies also to ERC20.

For example does the transfer function really need to perform the actual transfer? Everyone assumes it does but it might not. But the token contract is rather pointless if it does not perform a token transfer so I'd say you are safe to assume that a standard-compatible token has to actually perform the transfer - so it deducts tokens from one balance and adds to another. Therefore I don't really see any other alternative than to compare balances before and after.

Even if you do such checks there's no way to know whether it performs the transfer the same way every time (unless you analyze the actual bytecode). Maybe there's functionality which does something else every 100th time?

  • I actually mean to check it every time (the call is made from a contract under my control). Thanks! Dec 7, 2019 at 18:50

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.