Say I have a contract called MyContract, and I require to send 100000 DAI to it. Ideally, I'd firstly call approve(<address of A>, 100000e18) in DAI's contract itself. Secondly, I'd execute, for instance, the function collectDAI(100000e18) from MyContract. This function will internally call transferFrom(msg.sender, address(this), 100000e18) in DAI's contract and update MyContract's state accordingly.

Well, in this scenario an attacker could detect my call to "approve" and immediately execute by himself the transferFrom function (with very high fee if needed) and this transaction could potentially arrive before mine. Whenever I would try to call the collectDAI function in MyContract, I wouldn't be able, since the allowance has decreased to zero. Furthermore, MyContract might not be prepared to handle undesired DAI, so those tokens might be lost forever.

So, is it just my imagination, or we are facing a HUGE vulnerability in ERC20 that could potentially disallow its usage in smart contracts?

Please note that I'm using DAI in this example for simplicity, but it's perfectly applicable to any ERC20.

  • Not your imagination, but has already been posted publicly some two years ago. One workaround is to allow approve only when the current approved amount is zero. Another workaround is to implement a couple of additional functions - increaseApproval and decreaseApproval. Commented Nov 15, 2019 at 0:34
  • Here is the post (possibly one out of several): blog.smartdec.net/…. Commented Nov 15, 2019 at 0:36
  • This is a different issue triggered in a very similar way. Your issue is about calling approve twice, the attacker listening for the second one and triggering transferFrom before the second approve arrives. This attack vector is very limited to a sole attacker and a second call to approve, which makes it not so relevant. However the attack I'm describing can be executed by ANY attacker that pretends to destroy the business model of a DApp. Commented Nov 15, 2019 at 8:45

1 Answer 1


Certainly once you have approved MyContract's address anyone is able to call any function from it. And those functions can execute transferFrom and remove tokens from you address for a different purpose. You cannot limit it to only be called from collectDAI.

In any case you should not approve a contract address if you don't trust all of its functions.

As an alternative to ERC20 you have EIP-777 that proposed a new standard backward compatible with ERC20 with fixes for some of the problems.

  • So does this imply that you can not safely use the plain ERC20 standard with smart contracts? That'd basically invalidate most the so-called DeFi, since any attacker could easily track all relevant contracts with a decent volume of funds in ERC20 and execute transferFrom before the user... Commented Nov 15, 2019 at 8:41
  • Concerning ERC777, it's indeed a solution, but nowadays I haven't seen any token following that standard, so de-facto for now it's not usable. Commented Nov 15, 2019 at 8:42
  • @Molina Well known contracts have been audited and they are safe to use. They have measures that prevent an attacker from exploiting that, for example using msg.sender with transferFrom. But you should not blindly trust a contract.
    – Ismael
    Commented Nov 15, 2019 at 14:34
  • The problem is not that the attacker gets the funds. The problem is that the attacker manages to send funds to the contract without the contract being aware of it. This way contracts would end up with tokens and they wouldn't know who sent them. Furthermore, contracts might not be prepared to have a recover mechanism to return or assign those tokens to a proprietary, so the funds would be lost forever. In the best case it could be prepared so that an "administrator" gets all the tokens, but you'd have to trust them then... How exactly do those "well known contracts" handle this situation? Commented Nov 15, 2019 at 14:37
  • @Molina There are two issues you mention: 1/ calling an arbitrary function from an approved contract, 2/ sending arbitrary tokens to a contract. Both issues are well known, some contract have protections other don't. In any case you shouldn't transfer or approve a contract that hasn't been audited or is not widely trusted. It is not an ideal situation but it is the norm in a trustless blockchains.
    – Ismael
    Commented Nov 15, 2019 at 14:58

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.