XDRIPACADEMY
Sign in

Curriculum·F105 Transactions: What You Are Actually Signing·50 min

The signature taxonomy

By the end of this lesson you can

  • Classify any signature request into one of eight types and state what authority each one grants
  • Explain why an off-chain Permit2 signature is more dangerous than an on-chain approval despite costing nothing and appearing nowhere in your history
  • Identify which request types grant standing authority that outlives the session and which are one-time actions
  • State the correct response when a request cannot be classified
AutopsyBadgerDAO front-end injectionapproximately $120M

The attacker never touched the contracts. Using an unauthorised API key they injected a script into BadgerDAO's own website, which quietly added unlimited spend approvals for their address to transactions users believed were routine. Every user who lost money was on the correct domain, using a real wallet, clicking a button the site put there.

Then they waited. The script ran for about three weeks, harvesting approvals from close to 200 accounts. On 2 December 2021 they drained all of them in under ten hours.

Two decision points, and the second is the one people miss. Users verified where the request came from and never verified what it asked for. And nobody lost money on the day they made the mistake, so nobody had any reason to look.

Primary source

This is the material that does not exist in beginner education anywhere else, and it is the reason personal wallet compromises went from a minor share of stolen value to a dominant one.

The shift is simple to state. Attackers stopped trying to steal keys. Stealing a key is hard. Getting you to sign something is easy, and the result is identical: the chain executes the theft as an authorised action, and it is irreversible because it was never unauthorised.

The eight types

RequestWhat it doesDanger
transferMoves a specific amount, onceLow, but check the destination
approveLets a contract move your tokens up to a limitHigh if the limit is unlimited
increaseAllowanceRaises a permission that already existsHigh
setApprovalForAllGrants control of an entire token collectionCritical
permit and Permit2Off-chain signature granting an allowance. No gas, no transaction, invisible in your historyCritical
eth_sign and raw hexSigning data you cannot readNever
EIP-7702 delegationPoints your account at contract code, and persists until replacedCritical
Plain message, SIWEProves you control an addressLow, if it really is a login

Read the table as two groups rather than eight rows.

One-time actions move a known amount once. transfer is the whole group.

Standing authority is everything else. It grants a capability that persists after you close the tab, and it is redeemable at a time the attacker chooses. This is the distinction that matters. A drainer does not need to empty your wallet while you are watching.

Why the free one is the worst one

Approvals used to cost gas. That was accidentally protective: a transaction appeared in your history, you paid for it, and it was visible afterwards.

EIP-2612 permit and Permit2 removed the cost. You sign a structured message off-chain. No gas. No transaction. Nothing in your history to review later. The attacker holds a valid signed authorisation and submits it whenever they like.

Free is not safe

Users read "no gas fee required" as reassurance. It is the opposite. The absence of a transaction means the absence of a record, and the absence of a record means you will not find it in an audit of your own history. Cost is not a proxy for risk, and here it is inverted.

EIP-712 is the standard that makes these messages structured rather than opaque, which is what lets a good wallet render "Approve USDC spending by 0x..., limit 500" instead of a wall of hex. That is a real improvement. It is also why the next lesson exists: when the rendering fails, the protection fails with it, and the request still looks signable.

Unlimited by default

Most interfaces request an unlimited allowance. The reason given is convenience: approve once, trade many times, pay gas once.

The trade is that you have granted a contract permission to move every unit of that token you will ever hold in that address, for as long as the approval stands. If the contract is upgradeable, if its admin key is compromised, or if it was never what it claimed, the exposure is not the amount you traded. It is the balance.

Approving the amount you actually intend to spend costs more gas across many trades. It is usually the right call anyway, and lesson 5 covers how to audit and revoke what you already granted.

Common misconception

My hardware wallet protects me from this.

It does not. A hardware wallet protects the key. Every request in this table is a legitimate operation performed with your key, correctly, at your instruction. The device will sign it because you told it to. Hardware protects you from key extraction and from nothing in this lesson.

setApprovalForAll, specifically

This one deserves separate attention because the name understates it and the interface rarely clarifies.

It does not approve a token. It approves an operator for a collection. Listing an item for sale legitimately requires it, which is exactly why the request looks routine, and why fake listing flows are built around it. If you grant it to a hostile contract, every item in that collection is transferable at the attacker's discretion, including items you acquire afterwards.

When you cannot classify it

There is one correct answer and it is short.

Stop

If you cannot say which row of the table a request belongs to, do not sign it. Not "sign carefully." Not "sign a small amount first." An unclassifiable request is an unverifiable request, and no legitimate process is destroyed by a five minute delay while you work out what it is.

Key takeaway

Signature requests divide into things that move a known amount once, and things that grant standing authority redeemable later. Almost every large individual loss in the last three years came from the second group, signed by someone who thought they were doing the first. The free ones are the dangerous ones, unlimited is the default and rarely necessary, and hardware does not save you. The Signature Range at the end of this course tests exactly this, and it requires zero false negatives on the hostile requests.

These come back later

What does setApprovalForAll grant?
Control of an entire token collection held by that contract, not one item. It is standing authority with no amount limit and no expiry.
A site asks you to sign with no gas fee and no transaction. Is that safer?
No. It is the most dangerous category. An off-chain Permit or Permit2 signature grants an allowance, costs nothing, creates no on-chain record, and can be redeemed by the attacker days later.
Your wallet shows a signature request as raw hex. What do you do?
Do not sign. Unreadable means unverifiable. There is no version of this where signing is the correct action.

Track your progress

Create a free account to mark lessons complete and pick up where you left off.