ERC-20 Approve Race Remediation
Overview
Related Detector: ERC-20 Approve Race
approve() overwrites the spender’s allowance rather than adjusting it. When an owner changes an existing non-zero allowance, a spender watching the mempool can front-run the change: they spend the old allowance, then spend the new one, moving more tokens than the owner intended. The remediation is to change allowances by delta, or to reset to zero before setting a new value.
Recommended Fix
Before (Vulnerable)
// Owner intends to lower Bob's allowance from 100 to 10.
// Bob front-runs: spends 100 with the old approval, then 10 with the new one — 110 total.
token.approve(bob, 10);
After (Fixed — adjust by delta)
// OpenZeppelin-style delta helpers change the allowance relative to its current value,
// so there is no window where an old and a new allowance both apply.
token.safeIncreaseAllowance(bob, 5); // raise by 5
token.safeDecreaseAllowance(bob, 90); // lower by 90
If you must use approve directly, set the allowance to zero first, then to the new value in a separate transaction. For new integrations, prefer EIP-2612 permit (signed, single-use approvals) so allowances do not linger.
Common Mistakes
- Assuming the race is only theoretical — it is a documented ERC-20 property, and automated spenders do watch the mempool.
- Calling
decreaseAllowancebelow zero and reverting, when the goal was simply to revoke; use a zero-set orforceApprove. - Leaving large “infinite” approvals in place indefinitely; scope approvals to what a transaction needs.