Skip to main content
Sigvex

ERC-20 Approve Race Remediation

How to avoid the ERC-20 approval front-running race by using allowance deltas or a set-to-zero-first pattern.

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.

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 decreaseAllowance below zero and reverting, when the goal was simply to revoke; use a zero-set or forceApprove.
  • Leaving large “infinite” approvals in place indefinitely; scope approvals to what a transaction needs.

References