Token approvals, explained: approve, permit, Permit2 and how to revoke
· 3 min read · by haze
Most wallet drains don't steal a private key. They use a permission the wallet already gave away: an approval from months ago, or a signature that looked harmless. Knowing the four kinds of permission makes it much easier to spot the bad ones.
1. ERC-20 approve
A token contract can't pull your tokens on its own. When a dapp wants to move them (a swap, a deposit), it first asks you to call approve(spender, amount) on the token. From then on, the spender can call transferFrom and move up to that amount from your wallet, whenever it likes.
Two details matter:
- Many dapps ask for an unlimited amount (
2^256 - 1), so you don't have to approve again next time. It's convenient, but it means the spender can move every token of that kind you will ever hold. - Approvals don't expire. If that spender contract is later exploited, or was malicious from the start, the approval is still there.
2. NFT setApprovalForAll
NFTs have per-token approvals too, but most marketplaces ask for setApprovalForAll(operator, true). That hands the operator every NFT you own in that collection, now and later. A fake mint page asking for this is one of the most common NFT drains.
3. EIP-2612 permit (a signature, not a transaction)
Tokens that support permit let you grant an allowance by signing a message instead of sending a transaction. Anyone holding that signature can submit it on-chain and the allowance appears, before your deadline runs out.
That's why "it's just a signature, no gas" is not a safety signal. A permit signature for a big amount to an unknown spender is as dangerous as an approval. Wallets show these as typed data with fields like owner, spender, value, nonce and deadline.
4. Permit2
Permit2 is a shared contract (from Uniswap) that many apps use. You approve the Permit2 contract once per token, then every app gets its own allowance through a signed message, with an amount and an expiration.
This is safer than unlimited approvals to each app, because Permit2 allowances expire. The phishing version is a PermitSingle or PermitBatch signature that names an attacker as the spender. Read the spender before you sign.
How to spot a bad request
- Who is the spender or operator? If it's not the contract of the app you meant to use, stop.
- How much? An unlimited amount for a one-off action is a smell.
- Is it a signature that grants an allowance? Look for
permit,PermitSingle,PermitBatchorsetApprovalForAllin what you sign. - Does the site match? Drainer pages copy real sites pixel for pixel. Check the domain, not the design.
You can paste any signature request into what am i signing? to get it in plain english with the risky fields flagged. And scam or sign? is a daily five-question game built on exactly these patterns, if you want practice.
How to revoke
Revoking sets the permission back to zero:
- ERC-20:
approve(spender, 0) - NFTs:
setApprovalForAll(operator, false) - Permit2: set that app's allowance to zero through the Permit2 contract (it also has a
lockdownfunction for several at once)
Each revoke is a normal transaction, so it costs a little gas. It stops future pulls, but it can't undo a transfer that already happened.
The token approval checker lists every live allowance and NFT approval a wallet has granted on the chain you pick, and revokes any of them in one transaction from your own wallet.
A habit that helps
Use one wallet for holding and a separate one for minting and trying new apps. Approvals on the second wallet can only touch what's in it. Then check its approvals once a month and clear the ones you don't use.
Building a dapp? Ask for the exact amount you need, prefer Permit2 with a short expiration, and show users the spender in plain words. If you want that built right, that's what i do.