A signature, not a transaction: how permit quietly hands over your tokens
The familiar way to give an app access to your tokens is an approve transaction:
the wallet shows it, you pay gas and confirm. But there is a second path that looks completely different —
a plain "sign this message." That is permit, and it is how most modern drainers work.
What permit is
Permit is an extension of the ERC-20 standard (specified in EIP-2612). Instead of sending a
transaction, you sign an off-chain message in EIP-712 format: "I allow address spender
to spend up to value of my tokens until deadline." The signature does not go
on-chain by itself and costs no gas. The app (or an attacker) takes it and later presents it to the token
contract by calling permit(...) — and your allowance is set, exactly as if you had called
approve.
Why it is quiet — and dangerous
An approve transaction is shown by the wallet as a token action: you see the contract, the
amount, the gas. A permit arrives as "Sign this message" — no gas, no transfer, and many wallets render it
plainly. Psychologically, "signing" feels more harmless than "sending a transaction," even though the
consequence is the same allowance over your tokens.
The drainer pattern. A site asks you to "sign in" or "verify your wallet." You sign a
permit with value = maximum and spender = the attacker's contract. There is no
transaction at that moment, so nothing alarms you. A minute later the attacker calls permit(),
then transferFrom, and drains the tokens. You "just signed a message."
How to read what you are signing
EIP-712 shows structured (typed) data — not a meaningless hash, but fields. For a permit, look at them:
spender— who gets access. Is it the app's known contract, or an unknown address?value— how much. Very often this is "unlimited" (2^256-1) — a red flag if the site only needs a one-off operation.deadline— until when it is valid. A far-off date means the approval lives a long time.nonce— replay protection. One permit = one nonce.- the domain (
verifyingContract,chainId) — which token and which chain. A signature asked "to log in" should not be pointing at a token contract.
EIP-2612 vs Permit2
EIP-2612 is permit built into the token itself. It only works if the token implements it — and many ERC-20s do not.
Permit2 is a separate intermediary contract from Uniswap that brings permit logic to any token,
even one without a native permit(). You give Permit2 an ordinary approve once, then
hand out approvals to specific apps through off-chain signatures with an amount and an expiry. Convenient — but
the risk is the same: that first approve to Permit2 is often unlimited, and a Permit2 signature
can be phished just as easily.
How to stay safe
- Don't sign typed data on unfamiliar sites. A "sign-in" signature should never touch a token contract.
- Read the fields: check
spender,value(beware of unlimited) anddeadline. - A hardware wallet shows permit fields on the device screen — use that.
- Regularly review and revoke granted allowances at revoke.cash.
- In MetaMask a permit arrives as a "Signature request" of type
Permit— expand the details, don't sign blindly.
Want to see the trap live? Our trainer has an educational permit drainer on a testnet — you sign it, watch what happens, and learn to say "no."
- Sources: EIP-2612 · Uniswap Permit2 · revoke.cash