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:
-
Amount is almost always
type(uint256).maxโ "unlimited", so the UI doesn't have to ask again. - 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
Originally published by Dev.to Security. Aggregated on AIWithGhost for educational purposes โ full credit and traffic to the original publisher.