setApprovalForAll is the ERC-721 / ERC-1155 function that grants a contract or address blanket permission to transfer every NFT or token of a particular collection owned by your address — present and future. A single signature, indefinite scope, no per-token limit. The OpenSea pattern of "approve once, trade many times" relies on this; the Inferno Drainer and Pink Drainer kits exploit it. In dollar terms, this is one of the most expensive function calls in Ethereum history.

Why setApprovalForAll exists

NFT marketplaces need to be able to transfer NFTs on behalf of sellers without requiring a separate approval transaction for every listing. OpenSea, LooksRare, X2Y2, Blur — all use setApprovalForAll to grant their marketplace contract permission to move NFTs when sales execute.

This is convenient for legitimate use. It is also a one-signature catastrophe if the contract you approved turns out to be malicious. Unlike ERC-20 approvals (which have a per-token amount limit), setApprovalForAll is binary: yes or no, all or nothing.

The drainer mechanics

Fake mint page → user connects wallet → mint button prompts setApprovalForAll on the most valuable NFT contract in the user's wallet → user signs without reading → attacker now has transfer rights over every NFT in that collection at that address.

The attacker typically delays the drain. Sometimes they wait until the user has added more NFTs to the wallet (a higher take). Sometimes they wait until a market event reduces user vigilance. Sometimes the drain happens immediately if the wallet contains time-sensitive assets like staked NFTs about to be unlocked.

By Chainalysis's accounting, the Inferno Drainer alone exfiltrated roughly $80 million across 2023, primarily via setApprovalForAll signatures on Discord-distributed fake-mint pages.

How a wallet UI presents setApprovalForAll

The transaction reads "setApprovalForAll" in the function field, with two parameters: an "operator" address (the contract receiving the approval) and a boolean (true to grant, false to revoke). Modern wallets like Rabby and the post-2024 MetaMask display this clearly, often with a warning if the operator address is unknown.

Older hardware-wallet firmware shows the raw transaction with hex-encoded data. The Ledger Nano S Plus pre-2024 firmware did not parse setApprovalForAll meaningfully; the Trezor Safe 3 and Safe 5 do. If your hardware wallet displays raw hex for an unfamiliar call, treat that as a red flag — refuse to sign, update firmware, retry.

What defends

Three rules that work in practice:

First, only approve marketplaces you actively use. If you mint exclusively on OpenSea, do not approve LooksRare's contract. Each unused approval is a future attack surface.

Second, revoke after first use of unfamiliar contracts. If you connect to a new dApp once for an airdrop claim, immediately afterward visit revoke.cash and remove the approval.

Third, separate "trading" and "vault" wallets. Keep valuable NFTs at an address that has zero approvals to anything. When you want to list one, transfer to the trading address, do the listing, then transfer leftovers back. This adds friction but eliminates the setApprovalForAll catastrophe class entirely.

The quarterly hygiene step

Every three months, visit revoke.cash, connect each of your wallets, and revoke every approval you cannot identify or cannot remember granting. This is one of those custody habits that pays for itself the one time it stops a drain.

Further reading: EIP-2612 Permit, revoke.cash, Phishing.