Home

Token Approvals & Blind Signing

EIP-2612 Permit Signatures and Permit2: How Free Approvals Enable Blind-Signing Attacks

Spot the edge. Swoop in.

A permit signature never shows a gas fee, never triggers your wallet's transaction-warning screen, and never appears in your transaction history at the moment you sign it. Those are exactly the properties that make EIP-2612 permits, and Uniswap's broader Permit2 standard, such a genuine improvement to DeFi's clunky approve-then-execute flow, and exactly the properties a drainer site can exploit to get full spending rights over your tokens without you ever feeling like you approved anything. Here's what a permit actually is, how Permit2 extends it, and how to tell a real request from a fake one before you sign.

By Swoopr Editorial Team

Published · Updated

AI-assisted content · Swoopr is responsible for the final published article.

Key Takeaways

EIP-2612 was built to fix a real, widely felt problem: using a token in DeFi used to require two separate on-chain transactions and two gas payments before you could do anything, and permit signatures collapse that down to one signed message plus one transaction. That's a genuine UX win. It's also, for exactly the same reasons, one of the most effective vectors for wallet-drainer scams, because a signature request looks and feels nothing like a transaction, and most wallets and most users treat it accordingly.

Direct answer: EIP-2612 lets a token holder grant a spending approval by signing an off-chain message instead of sending an on-chain approve transaction; the signature costs no gas and isn't broadcast until someone submits it. Permit2 extends the same idea to any ERC-20 token through a shared contract. Because signing produces none of the friction of a transaction, no gas estimate, no balance-change warning, it is specifically the format attackers target for blind-signing scams, and a signed permit gives an attacker's contract the exact same ability to drain your tokens as a malicious on-chain approve call would.

What EIP-2612 "Permit" Actually Is

EIP-2612 is an Ethereum standard that adds an optional function called permit to an ERC-20 token contract. Ordinarily, granting another address the right to move your tokens means calling the token's approve function yourself, in a transaction you sign, broadcast, and pay gas for, which writes an allowance directly into the token contract's storage. A permit does the same underlying thing, it authorizes a specific spender to move up to a specific amount of your tokens, but it gets there by a different mechanical path.

Instead of calling approve on-chain, you sign a structured off-chain message, formatted according to EIP-712, that specifies the owner, the spender, the value being approved, a nonce that prevents the same signature from being reused, and a deadline after which the signature stops being valid. That signature is created entirely in your wallet and never touches the blockchain by itself. It costs no gas, because gas is only spent when something is actually executed by the network, and a signature, on its own, executes nothing.

The signature becomes useful once someone, typically the spender contract itself or a relayer acting on the dApp's behalf, submits it on-chain by calling the token's permit function and passing in your signature along with the owner, spender, value, and deadline you signed. The contract verifies the signature cryptographically against the address it claims to be from, and if it checks out, it writes the exact same allowance into storage that a direct approve call would have. From that point forward, the approval behaves identically to any other ERC-20 allowance: the spender can call transferFrom against it, up to the approved amount, for as long as the allowance stands or until it's revoked.

The important part to hold onto is that a permit is not a lesser or informal version of an approval. It is the exact same approval, reached by signing a message instead of sending a transaction. Whoever ends up holding your signature, whether that's the legitimate protocol you intended to use or an attacker who tricked you into signing, has the ability to submit it and unlock the identical spending right.

Why This Was Built: Fixing DeFi's Two-Transaction Problem

Before EIP-2612 existed, and for tokens that still don't support it, using a DeFi app for the first time with a given token follows a predictable, annoying pattern. You connect your wallet, choose an action, a swap, a deposit, adding liquidity, and the app first needs your token contract to grant it an allowance before it can move anything on your behalf. That means signing and paying gas for an approve transaction, waiting for it to confirm, and only then signing and paying gas for a second transaction that actually performs the swap or deposit. Two transactions, two gas payments, two confirmation waits, for what feels to the user like a single action.

That friction wasn't just an inconvenience; it was a real driver of the perception that DeFi is clunky and expensive compared to a centralized exchange, where a trade is one click. EIP-2612 was proposed specifically to close that gap. With a permit-supporting token, the first step, granting the allowance, becomes a free, instant signature instead of a transaction. The dApp can then submit that signature together with the actual action, often bundled into a single on-chain transaction that both activates the permit and executes the swap or deposit in one step. From the user's perspective, what used to be sign-wait-pay, sign-wait-pay collapses into sign once, then confirm one transaction, cutting the gas cost and the wait time roughly in half for that first interaction with a new token.

This is a genuine, well-intentioned UX improvement, not a workaround or a shortcut that trades away security for convenience in principle. The cryptographic guarantee behind a permit signature is exactly as strong as the guarantee behind a directly submitted approve transaction; both rely on the same private key, the same signature scheme, and the same on-chain verification. The risk this article covers isn't a weakness in the signature scheme itself, it's a weakness in how wallets present a signature request to a human being, and how that presentation gets exploited.

Permit2: Extending the Same Idea to Every ERC-20 Token

EIP-2612 has one significant limitation: it only works for tokens whose contracts were deployed with the permit function built in. Because it's optional and requires the token's own contract code to include it, a large share of ERC-20 tokens, including many deployed before EIP-2612 existed and some deployed afterward without adopting it, simply don't support it, and a token contract can't be retroactively upgraded to add it after deployment in the vast majority of cases.

Permit2 is Uniswap Labs' answer to that gap. Rather than requiring the token itself to implement gasless approvals, Permit2 is a single, shared contract, deployed at the same address across most EVM-compatible chains, that sits between users and the dApps they interact with. The way it works in practice has two stages. First, you grant a one-time on-chain approval from your token to the Permit2 contract itself, exactly like a normal approve call, which most wallets and dApps now prompt automatically the first time you use a token with a Permit2-integrated app. That one approval effectively delegates approval-granting authority to the Permit2 contract for that token.

After that one-time setup, any dApp built to work with Permit2, Uniswap's own interface among many others, can request a gasless, signature-based permission scoped to itself, specifying its own contract as the spender, a specific amount, and an expiration, all verified through Permit2 rather than through the token's own logic. Because the permit mechanism lives in Permit2 rather than in each individual token contract, this works identically whether or not the underlying token ever implemented EIP-2612 on its own. That's the entire point of Permit2: it generalizes the gasless-approval pattern to the whole ERC-20 ecosystem instead of leaving it available only to tokens whose developers happened to build it in. A growing number of wallets and dApps beyond Uniswap now integrate with Permit2 directly, which means the signature-request pattern described in this article shows up across a meaningfully wide slice of everyday DeFi activity, not just on Uniswap itself.

The Security Risk: Why Permits Are Built for Blind Signing

Wallets treat signature requests and transaction requests very differently in their user interface, and that difference is the entire mechanism behind the risk. A transaction, an on-chain approve or transferFrom call, triggers a wallet screen that estimates gas cost in real currency terms, and increasingly simulates the resulting balance change and surfaces a warning if the transaction looks like it could drain funds. A signature request, including a permit, triggers a different, lighter-weight screen: there's no gas to estimate because none will be spent by the act of signing, and many wallets historically have shown less prominent, more generic warning language, or none at all, on a raw EIP-712 signature request compared to a transaction.

That difference in presentation trains a predictable, understandable habit: transactions feel like real financial events, worth reading carefully, while signatures feel like a lightweight, almost bureaucratic step, a "connect" or "verify" click rather than a "spend money" click. Attackers who understand that gap don't need to break any cryptography to profit from it. They just need to get a permit signature request in front of you that looks like routine wallet activity, formatted exactly like the dozens of legitimate signature requests you've clicked through without a second thought, while the spender field quietly names a drainer contract instead of the protocol you meant to use.

This is the textbook definition of blind signing: authorizing something without actually reading or understanding what you're authorizing, whether because the interface doesn't show it clearly, because you're used to skimming past it, or both. A permit signature is close to the ideal vehicle for a blind-signing attack precisely because it removes every cue, the gas estimate, the balance-change warning, the sense of "this is a real transaction", that might otherwise prompt a closer look. And unlike a scam that tricks you into sending funds directly, a phished permit doesn't take anything from you the moment you sign it. It sits, valid and redeemable, until whoever holds it decides to submit it on-chain, which means the damage can land well after the moment that caused it, at a time when the original scam site is long forgotten.

Worked Example: A Real Permit2 Swap Versus a Fake One

Illustrative walkthrough of the wallet-popup flow — for education only, not a report of any specific incident.

To make the difference concrete, walk through what a Permit2-based token swap looks like on Uniswap's actual interface, then compare it step by step to what a fake site imitating that same flow would show.

Step one, the legitimate flow: you go to Uniswap's interface, connect your wallet, and select a token you haven't swapped there before. If that token has never been approved to Permit2's contract from your wallet, you'll first see a standard transaction request, not a signature, asking you to approve the Permit2 contract itself. This is a one-time, ordinary on-chain approval, and it's worth reading like any other approval: it names Permit2's contract as the spender, not Uniswap's swap router directly.

Step two, the legitimate flow: once that one-time approval is in place, initiating the actual swap produces a signature request rather than a transaction. Your wallet shows a structured EIP-712 message, typically labeled around "Permit2" or "PermitSingle," containing a spender address, a token, an amount, and an expiration timestamp. On a genuine Uniswap swap, the spender named is Uniswap's own Universal Router contract, and the amount matches the specific swap you just configured, not an unlimited figure. You sign it, no gas is spent, and Uniswap's backend submits the swap transaction, redeeming your signature through Permit2 to move exactly the amount you authorized.

Step three, the fake flow: picture a phishing site built to imitate that same experience, reached through a fake ad, a compromised social account, or a cloned link. Visually, the site can be pixel-identical to the real Uniswap interface. You go through what looks like the same swap flow, and your wallet produces what looks like the same kind of popup: a structured EIP-712 message, plausibly still labeled "Permit2" or "Permit," with a spender, a token, an amount, and an expiration. Structurally, it's indistinguishable at a glance from the legitimate request in step two.

Where the fake one actually differs: the spender address in the malicious request is not Uniswap's Universal Router, it's a contract controlled by the attacker, often built to immediately sweep the approved token once redeemed. The requested amount is frequently not scoped to a single swap either; fake requests commonly ask for the maximum possible value, an effectively unlimited approval, rather than a transaction-sized amount. Nothing about the wallet's generic popup chrome flags either difference automatically; reading the spender and amount is the only thing that separates a routine swap from handing over unlimited spending rights to an unknown contract.

How to Verify a Permit Signature Request Before Signing

Because the wallet popup itself won't reliably flag a malicious permit for you, the checks that matter happen in your own reading of the request, supplemented wherever possible by a wallet that does some of that reading for you.

Check the spender address against what you actually intend to use

Every permit or Permit2 request names a spender, the contract that will be allowed to move the approved amount. Before signing, confirm that address matches the protocol you're trying to use, cross-referenced against that protocol's own documentation or a block explorer's verified-contract listing, rather than trusting the label your wallet or the requesting site displays. A drainer contract can be named anything in a website's own interface; the address, not the text next to it, determines who can spend your tokens.

Check the requested amount, not just that a number is present

A permit scoped to the exact amount of the swap or deposit you're making is low-risk even if the spender turns out to be wrong, since exposure is capped at that amount. A request for the maximum possible value, an effectively unlimited approval, is a much larger blast radius for the same signing effort, and legitimate dApps request it far less consistently than phishing sites do. Treat any unlimited-amount request as worth a second look regardless of which site is asking.

Use a wallet with request simulation or plain-language decoding

Several modern wallets simulate the likely outcome of signing, surfacing something closer to "you are granting [address] the ability to spend up to [amount] of [token] until [date]" in plain language, sometimes flagging unusually broad or unlimited requests automatically. This isn't available in every wallet, but where it is, it closes most of the gap that makes permits an attractive blind-signing target in the first place.

Treat the deadline as a real field, not filler

A permit's expiration timestamp genuinely limits how long a signature remains redeemable. A short, reasonable deadline limits your exposure if the signature is misused; an unusually distant deadline extends the window in which a phished signature could still be redeemed long after you've forgotten signing it. It's a smaller signal than the spender and amount, but worth reading rather than skipping past.

Misconceptions Versus Reality

MisconceptionReality
Since it's a signature, not a transaction, there's no real risk in signing itA permit signature grants the exact same spending authority as an on-chain approve call; once the spender submits it, the fund-draining consequences are identical, the only difference is how the authorization was granted
No gas fee shown means it's a minor, low-stakes actionGas cost reflects computational effort, not financial exposure; a free signature can authorize unlimited spending just as effectively as an expensive transaction can authorize a small one
A "Permit2" or "Permit" popup only appears during legitimate dApp useAny site can trigger the same EIP-712 signature request format through your connected wallet; the popup's structure says nothing about whether the requesting site is legitimate
If nothing has visibly happened yet, nothing can be taken from meA signed permit is valid and redeemable from the moment it's signed until its deadline passes or it's used; the spender can choose to submit it immediately or hold it for later
Checking a revoke/approval tool like a block explorer's token approval checker shows all my risk exposureThose tools list on-chain approvals only; a signed-but-not-yet-submitted permit produces no on-chain record at all and won't appear anywhere until the moment it's actually redeemed
Permit2 is inherently riskier than EIP-2612 because it's a third-party contract in the middlePermit2 is a widely used, publicly verifiable shared contract; the actual risk in both systems comes from which spender and amount you sign for, not from which standard is technically in use

Common Mistakes That Make This Work

Risks, Limitations, and Exceptions

Tool Opportunity

A permit and signature-request decoder built for this pattern would translate a raw EIP-712 payload, before signing, into the plain-language terms a wallet transaction warning already uses for on-chain approvals.

Recommended inputs: the raw EIP-712 payload, or the spender address, token, amount, and deadline as displayed in the wallet popup.

Expected outputs: a plain-language summary of what's being authorized, spender identity cross-checked against known protocol contracts, an explicit flag for unlimited or unusually large amounts, and the deadline shown as a readable duration rather than a raw timestamp.

Validation requirements: never request private keys or seed phrases, label spender identification as a best-effort match rather than a guarantee, and make clear the tool evaluates the request's structure, not whether the requesting website is trustworthy.

Sources

Frequently Asked Questions

What is EIP-2612 and how is a permit different from calling approve?

EIP-2612 is a standard that adds a permit function to an ERC-20 token, letting a token holder authorize a spender by signing an off-chain message instead of sending an on-chain approve transaction. The signature itself costs no gas and isn't broadcast to the network; the spender, or whoever is relaying the action, later submits that signature on-chain by calling permit, which activates the approval at that point exactly as if approve had been called directly.

Why was EIP-2612 created in the first place?

Before EIP-2612, using a token in a DeFi app normally required two separate on-chain transactions: one to approve the app's contract to spend the token, and a second to actually execute the swap, deposit, or other action, each paid for separately in gas and each waiting on its own block confirmation. EIP-2612 collapses that into a single off-chain signature plus one on-chain transaction, removing an entire redundant transaction and gas payment from routine DeFi use without changing what the user is ultimately authorizing.

What is Permit2 and how is it different from EIP-2612?

Permit2 is a shared contract, originally built by Uniswap Labs, that extends the same gasless-signature idea to any ERC-20 token, even ones that never implemented EIP-2612 themselves. A user grants a one-time on-chain approval to the Permit2 contract for a given token, and after that, individual dApps can request gasless, signature-based permissions routed through Permit2 rather than needing the token itself to support permit.

Why are permit signature requests a specific target for blind-signing attacks?

A permit signature triggers a wallet's signature-request flow rather than its transaction flow, which means no gas estimate, no simulated balance change, and often less prominent warning language than a wallet shows before a transaction. That makes it easy to treat as routine background activity, which is exactly the blind-signing failure mode: approving something without reading or understanding what it authorizes, and a permit can authorize full spending rights just as effectively as an on-chain approve call.

What does a real Permit2 signature request look like compared to a fake one?

Both a legitimate Uniswap swap and a malicious drainer site produce a wallet popup with the same structural EIP-712 fields: a spender address, a token, an amount, and an expiration. The genuine Uniswap request names its own Universal Router contract as the spender and scopes the amount to the swap being executed, while a fake request substitutes a drainer contract's address as the spender and frequently requests an unlimited or maximum amount instead of a specific one, all inside a popup that looks structurally identical to the real thing.

How can I verify a permit signature request before signing it?

Check that the spender address shown in the signature request actually matches the protocol's known, documented contract rather than an unfamiliar address, check that the requested amount matches the transaction you intend to make rather than an unlimited value, and use a wallet that decodes and simulates the request in plain language if one is available, since raw EIP-712 data alone can be difficult to read correctly under time pressure.

If a permit signature was phished but never submitted on-chain, am I still at risk?

Yes, and this is one of the least understood parts of permit risk: a signed permit produces no on-chain record until the spender chooses to submit it, so it will not show up in a wallet's transaction history or in an approval-revocation tool until that moment, which could be immediate or much later. A signature you no longer remember giving can still be redeemed against your tokens at any point before its deadline passes.

Conclusion

EIP-2612 permits and Permit2 solved a real problem: DeFi's old two-transaction, two-gas-payment approval pattern was genuinely bad UX, and collapsing it into a single free signature plus one transaction was a legitimate improvement, not a corner cut. The security cost of that improvement isn't a flaw in the cryptography, it's a gap in how differently wallets present a signature compared to a transaction, and attackers have built an entire category of scams around living in that gap. A permit request and a phishing request built to imitate one look the same in every way that matters to a fast glance, no gas estimate, no balance warning, the same EIP-712 shape, and the only real differences, the spender address and the requested amount, are exactly the two fields it's easiest to sign past without reading. Read the token approvals hub for the wider set of approval-related risks this fits into, and the blind-signing guide for how the same underlying failure mode shows up beyond permits specifically.

Related Reading