How do I prevent against the double withdrawal attack described in ERC20 API: An Attack Vector on Approve/TransferFrom Methods and initially posted here?

An example of the attack:

  1. Alice allows Bob to transfer N of Alice's tokens (N>0) by calling approve method on Token smart contract passing Bob's address and N as method arguments
  2. After some time, Alice decides to change from N to M (M>0) the number of Alice's tokens Bob is allowed to transfer, so she calls approve method again, this time passing Bob's address and M as method arguments
  3. Bob notices Alice's second transaction before it was mined and quickly sends another transaction that calls transferFrom method to transfer N Alice's tokens somewhere
  4. If Bob's transaction will be executed before Alice's transaction, then Bob will successfully transfer N Alice's tokens and will gain an ability to transfer another M tokens
  5. Before Alice noticed that something went wrong, Bob calls transferFrom method again, this time to transfer M Alice's tokens.

So, Alice's attempt to change Bob's allowance from N to M (N>0 and M>0) made it possible for Bob to transfer N+M of Alice's tokens, while Alice never wanted to allow so many of her tokens to be transferred by Bob.


EIP20 refers readers to the MiniMeToken implementation regarding this issue which works around it by adding the line:

require((_amount == 0) || (allowed[msg.sender][_spender] == 0));

EIP20 refers readers to two example token implementations (I've linked to the relevant line numbers):

  • OpenZeppelin - Brief issue description and link to the original issue comment. Mentions "[o]ne possible solution to mitigate this race condition", but doesn't implement it.
  • ConsenSys - no mention or attempt to work around the issue

The MiniMeToken function comment says:

This is a modified version of the ERC20 approve function to be a little bit safer

Given this is the reference implementation, I would like to be a lot more confident than "a little bit safer".

There is no backward compatible resolution to this problem, and the solution is still being discussed.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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