EIP-2612 Permit: The Approval That Never Sends a Transaction

The standard ERC-20 approval requires a transaction: the owner calls approve, pays gas, and only then can a contract pull the tokens. EIP-2612 replaces that transaction with a signed message. The allowance still changes, the Approval event still fires, and the owner still has to understand what they are authorising — but the party who pays the gas can now be someone else.

CoinSoso EditorialPublished Article #00154Updated

Cover artwork: CoinSoso · AI-generated, not a photograph of a real venue, product or market capture.

Key takeaways

  • EIP-2612 adds permit, nonces and DOMAIN_SEPARATOR to an ERC-20 token; a valid permit sets allowance[owner][spender], increments the owner's nonce and emits Approval without the owner sending a transaction.
  • The signature covers owner, spender, value, nonce and deadline under an EIP-712 domain, so a permit is bound to one token contract on one chain and cannot be replayed after the nonce advances.
  • A permit reverts if the deadline has passed, the owner is the zero address, the nonce does not match, or the signature is not a valid secp256k1 signature from the owner.
  • Because ecrecover returns the zero address on malformed input, the owner != address(0) check is what stops a permit from creating an allowance over funds attributed to the zero address.
  • Permit changes who submits the approval, not whether an approval is risky: a signed permit can be relayed by anyone, is censorable by the relayer, and remains subject to the ERC-20 approval race condition.

The two transactions that became one signature

ERC-20’s approval model is a two-step dance. The owner calls approve(spender, value), which is a transaction and costs gas. Then the spender calls transferFrom(owner, recipient, value), which is another transaction. The allowance is the bridge between them, and the owner has to hold ETH to build it.

EIP-2612’s abstract describes the problem in exactly those terms: the approve function is defined in terms of msg.sender, so a user who needs to interact with a contract needs two transactions — the approve and the contract call that will internally call transferFrom — and, in the simple case of paying another person, still needs ETH for gas.

The extension adds three functions to ERC-20:

function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external
function nonces(address owner) external view returns (uint)
function DOMAIN_SEPARATOR() external view returns (bytes32)

A valid permit call sets allowance[owner][spender] to value, increments nonces[owner] by one, and emits the corresponding Approval event. No transaction from the owner is required. The owner signs; someone else submits.

What the signature actually covers

The permit is not a signature over “approve this token”. It is a signature over a structured message defined by EIP-712, and the fields are the whole of what the owner is agreeing to:

  • owner — whose tokens the allowance applies to
  • spender — who may move them
  • value — how many
  • nonce — the owner’s current permit nonce
  • deadline — the last block time at which the permit is valid

The digest is constructed so that the domain separator, which binds the signature to a contract and a chain, is hashed together with the typed message. The EIP’s formula is:

keccak256(abi.encodePacked(
  hex"1901",
  DOMAIN_SEPARATOR,
  keccak256(abi.encode(
    keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"),
    owner, spender, value, nonce, deadline
  ))
))

The DOMAIN_SEPARATOR is defined according to EIP-712, and the EIP says it should be unique to the contract and chain to prevent replay attacks from other domains. That is the property that stops a signature collected on a testnet contract from being replayed on mainnet, or on a fork.

A permit reverts unless four conditions hold: the current block time is less than or equal to the deadline, owner is not the zero address, the nonce supplied in the message equals nonces[owner] before the state update, and v, r and s form a valid secp256k1 signature from owner. Any failure is a revert, not a silent no-op.

A signed permit replacing the approve transaction, with the relayer in between owner signs typed data no gas signature owner, spender, value, nonce, deadline relayer pays gas calls permit token contract: allowance set, nonce +1, Approval emitted The owner never sends a transaction. Moving the gas out of the approval also moves the confirmation out of the transaction screen.
The relayer can submit or withhold the signature and cannot alter it. The owner's confirmation happens in a message-signing screen, which is a different habit from confirming a transaction.

The risks the EIP itself lists

EIP-2612’s security section is short and unusually candid. Read it as the specification’s own threat model.

Front-running is not a theft. The signer may have a particular party in mind, but another party can always call permit first. The end result is the same for the signer: the allowance is set to the signed value. The front-runner pays the gas and gets an allowance that was already going to exist. This is why “someone else submitted my permit” is not, by itself, an incident.

ecrecover fails silently. The precompile returns the zero address for malformed messages, so the owner != address(0) check is what prevents a permit from creating an approval over “zombie funds” attributed to the zero address. The check is in the specification, and a token implementation that omits it has a bug.

Permits are censorable. A relayer that receives a signed permit can choose not to submit it, withholding the option to submit it later. The deadline is the mitigation: a permit that is not submitted before its deadline becomes unusable. If the owner holds ETH, they can submit it themselves.

The ERC-20 race condition still applies. The EIP says the standard approval race condition (SWC-114) applies to permit as well. Changing an allowance from one non-zero value to another can be front-run by a spender who uses the old allowance before the new one lands. Permit does not fix that; it changes only the mechanism by which the allowance is set.

A static domain separator can replay across a chain split. If DOMAIN_SEPARATOR contains the chainId but is defined at deployment instead of reconstructed for every signature, the EIP warns of possible replay attacks between chains in the event of a future chain split. This is a contract-implementation issue, not a user-facing one, but it explains why some tokens recompute the separator on every call.

What a permit does not do

Three limits are worth stating plainly, because they are the source of most of the confusion around the standard.

It does not make the approval safe. A permit for an unlimited value to an unknown spender is the same grant as an approve transaction for the same values. The difference is that the user signs a typed message instead of sending a transaction, and a message-signing screen is easier to click through than a transaction confirmation. The review habits in token allowances: how to review and revoke approvals apply unchanged.

It does not work for every token. EIP-2612 is an extension. A token that does not implement permit will not accept one, and a front end that assumes support will fail at the call. Checking the contract for the three functions, or for a published interface, is part of using the feature.

It does not cover contract accounts by itself. The signature check is secp256k1 and ecrecover, which is an externally owned account operation. A smart contract wallet needs a different validation path, which is outside this EIP. The distinction is the same one that makes passkeys and account abstraction a separate design space rather than a feature of the token standard.

Reading a permit before signing

A permit request that a wallet displays should answer five questions, and the EIP’s fields map to them directly:

Question Field What to check
Which token? Domain separator / verifying contract The contract address matches the token you think you are approving
Which chain? Domain chainId The network matches the one you intend to use
Who can spend? spender A contract you recognise, not an address copied from a chat
How much? value A bounded amount, not the maximum, unless the use case requires it
Until when? deadline A near date, not a timestamp years away

The nonce is the field users rarely see and wallets should show. A permit signed for a nonce higher than the current one cannot execute until the intervening nonces are used; a permit signed for the current nonce is a one-shot authorisation. If a wallet presents a permit without the nonce, it is hiding the one field that explains why the signature may or may not still be usable.

Why the standard exists at all

The EIP’s motivation is narrower than “better UX”. It is about removing the requirement that a user hold ETH to interact with a token, and about doing so with the smallest possible change to ERC-20. The authors explicitly reject adding *_by_signature counterparts for every ERC-20 function, on the grounds that the specifics vary by use case and can be built from permit plus helper contracts.

That minimalism is why permit is now a building block rather than a complete approvals system. It gives a contract a way to verify that an owner authorised a spender at a particular time, and it leaves the policy — how much, for how long, to whom — to the application. The security of the result depends on the application using that policy well, and on the wallet showing the user enough of the message to make the policy visible.

For the transaction-level view of what a signature can hide, see transaction simulation before signing. For the difference between a wallet that shows structured data and one that shows a hash, see clear signing versus blind signing. And for the account model that decides whether a signature is even the right primitive, see passkeys and account abstraction.

Risk note. The function signatures, digest construction, revert conditions and security considerations in this article were read from EIP-2612 on 2026-11-02, with EIP-712 and EIP-20 for the domain and approval context. Token implementations vary; the specification defines the minimum a compliant contract must do. Nothing here is investment advice.

Sources

How this was researched. Wallet guides describe how key management works in general. Where an article describes a specific product's behaviour, its sources are listed below.

Primary sources for the factual claims on this page. A date appears only where a human has actually read the source; where it is missing, the check is still outstanding.

  1. EIP-2612 — Permit Extension for EIP-20 Signed Approvals (specification, signature digest, security considerations)(read 2026-11-02)
  2. EIP-712 — Typed structured data hashing and signing (domain separator and typed data)(read 2026-11-02)
  3. EIP-20 — Token Standard (approve, transferFrom and the approval race condition)(read 2026-11-02)

Frequently asked questions

Does EIP-2612 remove the need for approvals entirely?

No. It removes the need for the owner to send a separate approve transaction. The allowance still has to be set, and permit sets it from a signature instead of from msg.sender. The token must also implement EIP-2612; it is an optional extension, not part of ERC-20.

Can someone else submit my permit?

Yes. The EIP's security section says that although the signer may have a particular party in mind, another party can always front-run the transaction and call permit first. The end result is the same for the signer: the allowance is set to the signed value. The relayer pays the gas and cannot change the contents.

What happens if a permit expires?

The permit reverts. The specification requires the current block time to be less than or equal to the deadline. A signature with a deadline in the past cannot be used, which is why the deadline is the main mitigation for a relayer that chooses not to submit a permit it has received.

Can I cancel a permit I signed but did not send?

There is no cancel call, but you can invalidate the signature by using the nonce yourself. The EIP notes that if the signing party holds ETH they can submit the permit themselves, which renders previously signed permits invalid because the nonce has advanced. A permit signed for a future nonce cannot be used until that nonce arrives.

Does permit work with smart contract wallets?

Not through the EIP-2612 signature check as written. The specification validates a secp256k1 signature recovered with ecrecover, which is an externally owned account operation. Contract accounts use different signature-validation standards, and a token that supports them needs additional logic beyond EIP-2612.

Is a permit signature as dangerous as an approve transaction?

It authorises the same thing: a spender's allowance over the owner's tokens. The difference is where the confirmation happens. An approve transaction is confirmed in a wallet as a transaction; a permit is confirmed as a typed message, and a user who does not read the message can sign an allowance without noticing the spender or the amount.

Where to go next

Independent research. Each card shows the platform’s invite code, and its Create Account button is a referral link that may earn us a commission at no extra cost to you. Whether an account can be opened is decided by the platform at sign-up.

Binance

One of the largest global exchanges by traded volume, with a very broad product range.

20% Trading Fee Rebate

Use invite code con888 when signing up to enjoy trading fee benefits.

Download Android App

Download from the exchange's official download service. Verify the source and follow the on-screen installation instructions.

Do not install an APK from an unknown source, or one that has been modified or cannot be checked.

Read review →

OKX

A large global exchange offering spot, derivatives and a self-custody wallet.

20% Trading Fee Rebate

Enter invite code con888 when signing up to check available trading fee benefits.

Download Android App

Download from the exchange's official download service. Verify the source and follow the on-screen installation instructions.

Do not install an APK from an unknown source, or one that has been modified or cannot be checked.

Read review →