Skip to content

Connection security

Token permit vs approval: nonces and deadlines

Track two signed permits through one nonce, a zero approval and deadline expiry. Then inspect Permit2 as a separate permission system.

Ivory paper ticket with a key-shaped cutout hovering above a ceramic latch with a lime peg.
Illustration for connection security; examples in this article are educational.

A token approval sets an on-chain spending allowance through a call authorized by the owner. An ERC-2612 permit uses a signed message that anyone can submit to make that change. Signing alone changes no allowance. Successful execution advances that owner's permit nonce on that token, and its deadline limits when the permit can execute, not how long the resulting ordinary allowance lasts.

Compare how the permission reaches the token

With a conventional ERC-20 approval, the owner authorizes an on-chain call to the token's approve function. That call identifies a spender and an amount. A successful replacement approval overwrites the previous allowance; it does not add another spending budget. The spender later uses the allowance through a separate transfer operation. These are the base ERC-20 approval semantics.

ERC-2612 adds a signature route to that allowance change. The owner signs typed data, and a submitter presents the signature to the token's permit function. This can let an application combine permission and execution in one transaction, but the permit itself does not perform a swap.

QuestionDirect ERC-20 approvalToken-native ERC-2612 permit
What authorizes the change?An owner-authorized contract callA valid owner signature
Does signing an off-chain message change state?Not the ordinary approval routeNo; someone must execute the permit
Who submits the state change?Owner or its authorized account executionAny submitter holding the valid permit
Where does the allowance live?Token contractThe same token contract
Is there a built-in deadline?None in the base approval interfaceDeadline for executing the permit
Does permission alone specify a swap result?NoNo

“Gasless approval” describes the owner's signing experience. The on-chain execution still requires gas; another account may pay it, and the surrounding service may charge separately. Compare the actual transaction flow and costs instead of assuming the signature makes the entire trade free.

For balance changes, finite limits and successful revocation, the token allowance ledger covers the broader accounting. Here the extra concern is authority that has been signed but has not yet appeared on-chain.

Read the signed fields before accepting the convenience

An ERC-2612 message binds an owner, spender, value, nonce and deadline to a signing domain. Review the full addresses and raw amount, then convert the amount using verified token decimals. A familiar app name does not establish that the spender is its intended contract.

The domain also matters. EIP-712 provides structured signing and domain separation; fields such as chain identifier and verifying contract distinguish the intended context. Readable fields help inspection, but the format itself supplies no replay protection. The permit's nonce supplies that additional condition. The typed-data signature guide explains how to inspect the domain and message together.

Do not infer more intent than the message contains. OpenZeppelin's permit security guidance warns that a permit expresses an allowance, not instructions to spend it in a particular way. ERC-2612 does not itself bind minimum swap output, output recipient or a trading plan. Those checks belong to the surrounding execution mechanism.

Check compatibility at the token's actual contract. A token symbol, wallet button or function named permit is insufficient: ERC-2612's specification documents older variants with different fields. Contract-wallet support also depends on the signature mechanism and integration. Keep an appropriate direct-approval path when a supported account cannot use the particular permit implementation.

Follow two signatures through one owner's nonce

Consider a hypothetical token Q with six decimals and ordinary finite allowances. One owner holds 1,000 Q. Its current permit nonce on this token is 7; spender R already has a 40 Q allowance and spender S has zero. Assume valid signatures, no transfer fees, no custom allowance expiry and no reorganization. Each on-chain step below is a separate transaction. Times are illustrative UTC block times on one day.

Permit A authorizes R for 300 Q. Permit B authorizes S for 80 Q. Both use nonce 7 and a deadline of 12:10. These are competing authorizations for the same owner's nonce on the same token, despite naming different spenders.

Time and actionPermit nonceR allowance, QS allowance, QOwner balance, Q
12:00: starting state74001,000
12:01: owner signs A74001,000
12:02: owner signs B74001,000
12:03: direct approval sets R to zero7001,000
12:04: A executes successfully830001,000
12:05: R transfers 120 Q81800880
12:06: B is submitted and rejected81800880
12:11: permit deadline has passed81800880

The 300 Q signature value is 300 × 10⁶ = 300,000,000 base units. After the transfer, the owner's balance is 1,000 − 120 = 880 Q, and R's remaining allowance is 300 − 120 = 180 Q. S never receives an allowance because B's signed nonce no longer matches 8.

Signing B did not supersede A. Whichever valid nonce-7 permit executes first consumes that slot. In an alternative ordering, B could execute first, advance the nonce to 8 and make A unusable, while leaving S with 80 Q of authority. The intended order in an application is not an execution guarantee.

This is also a different counter from the owner's transaction nonce. An owner-sent approval transaction can advance the account's transaction sequence without consuming the token's permit nonce. A relayer can execute the permit using the relayer's transaction nonce. Use the EVM transaction nonce guide for that separate sequence; never substitute its RPC value for the token's nonces(owner) read.

A deadline stops activation, not the resulting allowance

The table ends with a live 180 Q allowance after 12:10. There is no contradiction: the signature's activation window ended, while the permission created at 12:04 remains.

The boundary is inclusive. ERC-2612 checks whether the execution block timestamp is at most the signed deadline. In a separate branch where A has never executed and the nonce is still 7, execution exactly at 12:10 can pass that time check; at 12:10:01 it fails. Other validity checks still apply. Broadcasting before 12:10 does not reserve timely execution.

OpenZeppelin's versioned ERC20Permit implementation makes the distinction visible: it checks the deadline, uses the nonce and sets the allowance. Its ordinary allowance storage does not acquire a deadline from that call. A token with an additional expiry extension needs a separate inspection; do not generalize its behavior to plain ERC-2612.

Choose a signature window that fits the intended operation, then track the remaining allowance after execution. A short window cannot repair an excessive amount or an incorrect spender.

Zero allowance does not prove every signature is unusable

At 12:03, R's allowance is zero, yet A can restore it. This follows from the reference implementation: ordinary ERC20 approval updates allowance without consuming the permit nonce. An allowance scanner therefore cannot, by itself, establish that an unsubmitted signature held elsewhere is harmless.

Maintain two records: current on-chain allowance and outstanding signed authority. Record the latter's non-secret fields and status while keeping usable signature bytes out of ordinary logs, analytics and support messages.

ERC-2612 does not define a general cancellation function. A particular token may offer a documented invalidation mechanism. Another valid permit using the current nonce can also consume that nonce, but it competes with any existing candidate and sets its own allowance. A newly signed zero-value permit does not cancel anything merely by being signed. If A executes first, the competing zero-value permit at nonce 7 fails instead.

Resolve retirement from observed state: which permit executed, what nonce is current, what allowance remains, and whether any unused signature can still pass its checks. Disconnecting a site or deleting a local signature copy cannot alter a signature already held by someone else.

Permit2 has another permission layer

Uniswap Permit2 is a separate contract system. It can provide signature-based spending for ERC-20 tokens without token-native ERC-2612 support, but the underlying token must first authorize Permit2. That base approval remains a separate permission to inspect.

Its two modules then apply different rules:

Permit2 moduleDownstream authorityNonce and time distinction
AllowanceTransferReusable allowance inside Permit2Nonce per owner, token and spender; signature deadline separate from allowance expiration
SignatureTransferOne-time transfer authorizationUnordered nonce bitmap; one-use signature permission

Uniswap's AllowanceTransfer documentation explains why signatures with the same nonce can coexist when their token or spender differs. That differs from the same-token ERC-2612 example above. Its SignatureTransfer documentation describes one-time transfers and the need for integrations to enforce intended caller context.

Identify the actual module before interpreting a wallet's expiry or nonce display. A one-time downstream signature does not imply the underlying token approval to Permit2 has disappeared.

Use a permission receipt before retrying or retiring access

Keep a small worksheet for the actual flow:

EvidenceCheck it supports
Chain, owner, token and verified implementationWhich permission system applies
Spender and signed domainWhich contract receives authority and which verifies it
Raw amount, decimals and displayed budgetWhether the authorized quantity matches the task
Permit nonce and execution deadlineWhether an unused signature could still activate
Existing allowance and read blockWhat authority is already stored
Receipt, resulting nonce and allowanceWhether execution changed permission as intended
Outstanding signatures and invalidation evidenceWhether closing the workflow actually retires authority

If submission fails or times out, refresh nonce and allowance before requesting another signature. A permit may already have executed through another submitter. OpenZeppelin's integration guidance allows for this ordering case, but the surrounding contract must still enforce the intended action; ignoring a permit error is not a substitute for those checks.

A hardware wallet and an exchange API key protect different kinds of authority. Signing on a device still requires reviewing the permission being granted.

Record whether the permit is still usable, executed, expired or demonstrably invalidated, alongside the remaining allowance at an identified block. Treat a still-usable permit as open authority even when the allowance reads zero. Resolve both records before marking access retired.

Keep the context with the example.

Each worked example is illustrative, with its sources and assumptions in the article. Read our editorial standards for authorship, verification and corrections.