Dev.to Security ๐Ÿ” Cybersecurity ๐Ÿ‘ 0 ๐Ÿ“– 2 min read

Your old token approvals are a loaded gun: how ERC-20 approve, Permit2 and setApprovalForAll get you drained

Most people think a wallet gets drained when someone steals the seed phrase. In 2026 the more common story is quieter: an approval you signed months ago gets used against you. January 2026: an aggregator partner (SwapN

Most people think a wallet gets drained when someone steals the seed phrase. In 2026 the more common story is quieter: an approval you signed months ago gets used against you.

  • January 2026: an aggregator partner (SwapNet) was exploited and about $16.8M left users' wallets through approvals they had granted earlier. No new signatures.
  • The same month, a single wallet lost about $13.3M through an approval granted on January 1.
  • October 29, 2026: Binance lost about $6.3B (a different vector โ€” exchange hot wallets), which tells you how active attackers are right now.

Here's how approvals actually work, why they're dangerous, and the free scanner I built to clean them up across 6 EVM chains.

What an approval really is

ERC-20 tokens don't let contracts pull your funds by default. A dApp first asks you to call:

function approve(address spender, uint256 amount) external returns (bool);

After that, spender can call transferFrom(you, anyone, amount) whenever it wants. Two details make this risky:

  1. Amount is almost always type(uint256).max โ€” "unlimited", so the UI doesn't have to ask again.
  2. There is no expiry. The allowance stays until you set it back to 0.

NFTs are worse: setApprovalForAll(operator, true) gives one contract every token in a collection.

Permit and Permit2

permit (EIP-2612) lets you grant an allowance with an off-chain signature โ€” no transaction, no gas, and no scary-looking wallet popup. Drainer sites love it.

Uniswap's Permit2 adds a layer: you approve the Permit2 contract once per token, and apps get spending rights through Permit2 allowances. Cleaning up means checking both the token โ†’ Permit2 approval and the Permit2 โ†’ app allowances.

Why "I stopped using that dApp" doesn't help

The allowance lives in the token contract, not in the dApp. When a router, aggregator or bridge contract gets exploited later, the attacker inherits every allowance users ever gave it. That's exactly what happened in the cases above.

How to clean up

Revoking = sending approve(spender, 0) (or setApprovalForAll(operator, false)). It costs normal gas: cents on BNB Chain, Base, Arbitrum, Optimism and Polygon.

The annoying part is finding the approvals: they're spread across chains and buried in years of logs. That's why I built Revokly:

  • scans Ethereum, BNB Chain, Base, Arbitrum, Optimism and Polygon in one pass;
  • shows each spender, token and amount, with unlimited ones flagged;
  • revokes in one click from MetaMask, Rabby, Trust Wallet or any WalletConnect wallet;
  • runs in the browser โ€” no signup, keys never leave your wallet, and it only ever asks you to sign approve(spender, 0).

It's free. Feedback very welcome in the comments.

A 60-second habit

  • After every new dApp, airdrop claim or mint โ†’ re-scan.
  • When a protocol you used is hacked โ†’ revoke immediately, on every chain you used it on.
  • Savings on a hardware wallet; a small separate hot wallet for experiments.

๐Ÿ‘‰ Check your wallet on Revokly ยท Wallet drained? What to do

๐Ÿ“ฐ Read the original article on Dev.to Security

Originally published by Dev.to Security. Aggregated on AIWithGhost for educational purposes โ€” full credit and traffic to the original publisher.