A known race condition exists within the present implementation of the ERC20 standard. Due to the nature of this vulnerability being an inherent flaw in the ERC20 standard, considerations must be made for any divergence (as modifications made while no longer be ERC20 compliant).
The scenario for exploitation is as follows:
Alice calls approve(Bob, 1000), allocating 1000 tokens for Bob to spend
Alice opts to change the amount approved for Bob to spend to a lesser amount via approve(Bob, 500). Once mined, this decreases the number of tokens that Bob can spend to 500.
Bob sees the transaction and calls transferFrom(Alice, X, 1000) before approve(Bob, 500) has been mined.
If Bob’s transaction is mined prior to Alice’s, 1000 tokens will be transferred by Bob.
However, once Alice’s transaction is mined, Bob can call transferFrom(Alice, X, 500), transferring a total of 1500 tokens despite Alice attempting to limit the total token allowance to 500.
The particular exploit requires the usage of both the transferFrom and approve functions. As demonstrated above, the race condition occurs when one calls approve a second time on a spender that has already been allowed. If the spender sees the transaction containing the call before it has been mined, then the spender can call transferFrom to transfer the previous value and still receive the authorization to transfer the new value. While a multitude of approaches do exist to prevent this particular behavior from being exploited (one example of such is included below), they unfortunately may cause downstream functionality issues with those who implement such changes.
A potential fix includes preventing a call to approve if all the previous tokens are not spent through adding a check that the allowed balance is 0:
require(allowed[msg.sender][_spender] == 0)
At this point, this is more or less a consideration of whether or not the team determines this to be an acceptable risk.
The text was updated successfully, but these errors were encountered: