ERC-2612 lets a token accept a signed instruction that changes its own spending allowance. Permit2 adds a separate permission system: the token must authorize Permit2, which then checks either a reusable spender allowance or a one-time transfer signature. Compare the actual module, both permission layers, the nonce scope and the time limits. A short-lived signature does not automatically remove the token's underlying approval to Permit2.
Start with the contract that holds each permission
With a native ERC-2612 permit, the token verifies a signature and sets its ordinary allowance for the named spender. Signing alone changes nothing; a successful on-chain call activates the permission and advances the owner's nonce on that token. The deadline limits when that call can execute. The resulting allowance has no expiry supplied by ERC-2612.
Permit2 is an intermediary. The owner first authorizes the Permit2 contract at the token. Permit2 then applies its own rules before calling the token's transfer mechanism. This prerequisite remains true for both of its modules, including SignatureTransfer. Uniswap's Permit2 overview documents the initial approval separately from downstream permissions.
The distinction matters when a wallet displays only a friendly application name. Inspect both spender addresses: Permit2 at the token layer, then the integrating router or other contract at the Permit2 layer.
| Permission model | Where authority is recorded | What remains after activation or use? |
|---|---|---|
| Native ERC-2612 | Allowance in the token | An ordinary token allowance |
| Permit2 AllowanceTransfer | Token approval plus a Permit2 grant | A reusable grant until exhausted, expired or revoked |
| Permit2 SignatureTransfer | Token approval plus an unused signed transfer | No reusable downstream grant after successful use |
A token need not implement ERC-2612 for an integration to use Permit2. That does not make every token, wallet or router compatible with every flow. Verify the actual contracts and supported signature mechanism. The broader permit-versus-approval guide covers token-native activation; this comparison follows the additional Permit2 state.
A reusable grant has two clocks and its own nonce
Permit2's AllowanceTransfer module stores an amount, expiration and nonce for each owner, token and spender combination. A signed grant also has a separate sigDeadline.
The signature deadline answers whether an unused grant may still be installed. The allowance expiration answers whether the installed grant may still be spent. Passing the first deadline does not remove a grant already installed with a later expiration.
Nonce scope also changes. Two AllowanceTransfer permits for the same owner and token can both use nonce 0 when they name different spenders with current nonce 0. Each advances its own record. Two native ERC-2612 permits for that owner on the same token instead compete for the token's single current owner nonce, even when their spenders differ.
Here, detailed Permit2 behavior refers to Uniswap's upstream implementation at commit cc56ad0. Its allowance storage library advances the nonce when installing a signed allowance. Spending against an existing grant does not require another permit signature. Inspect the deployed implementation before applying these details to a particular chain.
Two spenders share one upstream allowance
Consider this hypothetical educational example. Owner O holds 1,000 Q, a token with six decimals and conventional finite allowance accounting as in OpenZeppelin Contracts v5.4.0 ERC20. There are no transfer fees, rebases, other transfers or reorganizations. Each action after the starting row is a separate transaction; the rejected attempt reverts completely.
At 12:00 UTC, O has approved Permit2 for 400 Q at the token. Two signed AllowanceTransfer grants have also activated: router R receives 300 Q of authority and router S receives 200 Q. Both signatures had an execution deadline of 12:00:30; both installed grants expire at 13:00. Their independent permit nonces have each advanced from 0 to 1.
R and S receive permission limits without reserved token balances. They share O's balance and the token's allowance to Permit2.
| Time and completed action | O balance, Q | Token → Permit2, Q | R grant, Q | S grant, Q |
|---|---|---|---|---|
| 12:00: grants active | 1,000 | 400 | 300 | 200 |
| 12:01: R transfers 100 | 900 | 300 | 200 | 200 |
| 12:02: S transfers 160 | 740 | 140 | 200 | 40 |
| 12:03: R requests 150; rejected | 740 | 140 | 200 | 40 |
| 12:04: O revokes token approval | 740 | 0 | 200 | 40 |
| 12:05: O approves Permit2 for 120 | 740 | 120 | 200 | 40 |
| 12:06: R transfers 60 | 680 | 60 | 140 | 40 |
At 12:03, R's 200 Q grant is sufficient for its 150 Q request, but the shared upstream allowance is only 140 Q. The token transfer fails. The pinned AllowanceTransfer implementation checks its internal grant and then calls the token. The downstream limit is only one condition for success.
Although that implementation reduces a finite internal grant before calling the token, the failed transfer does not leave R with a 50 Q grant. EVM revert semantics roll back state changes in the reverted execution. R remains at 200 Q. Earlier successful transactions remain effective.
The arithmetic reconciles: the first two transfers total 260 Q, leaving a 740 Q balance and 140 Q upstream allowance. The later 60 Q transfer leaves a 680 Q balance, a 60 Q upstream allowance and a 140 Q R grant. The original 400 Q approval was 400,000,000 base units.
At 12:05, restoring the upstream approval allows R to use its existing unexpired grant without a fresh signature. The earlier revocation did not delete either grant inside Permit2. Both grants' nonces remain 1 throughout the spending and token-approval changes.
At 13:00:01, the expired grants cannot authorize another transfer, even though their stored amounts may still be positive. The pinned implementation rejects spending when the block timestamp is greater than the expiration; equality passes that particular time check. Sufficient balances and permissions still matter.
A one-time transfer has no reusable remainder
SignatureTransfer uses a different model. In a separate hypothetical example, O again has 1,000 Q and a finite 400 Q token allowance to Permit2. O signs a single transfer permission with a 100 Q ceiling and nonce 517. The authorized spender successfully requests only 65 Q before the deadline.
The resulting balance is 935 Q and the upstream allowance is 335 Q. The unused 35 Q of the signed ceiling is not a remaining AllowanceTransfer grant. The successful call consumes the one-time nonce, so that signature cannot later authorize the other 35 Q. This follows from the pinned SignatureTransfer implementation, which checks the requested amount against the ceiling and spends the nonce for the call.
Its nonce is a bitmap location, not the next sequential number required for every transfer. For nonce 517, the word index is 2 and bit index is 5: 517 = 2 × 256 + 5. Starting from an empty word, successful use sets mask 32, because 2⁵ = 32. Other unused bits remain independently available. Allocating the same owner nonce to two signatures creates a conflict even if their tokens or spenders differ.
Do not mark a nonce consumed merely because a transaction was submitted. If the entire execution reverts, the nonce update reverts too. Resolve an uncertain outcome from the receipt and current bitmap before signing a replacement.
Spending permission does not establish acceptable swap terms
For SignatureTransfer, the signed hash binds the spender to the contract calling Permit2. The ordinary signed payload includes the token, maximum amount, nonce and deadline. The recipient and requested transfer amount are supplied separately by that spender. A valid base permit therefore does not, by itself, establish the intended recipient, minimum output or exact trading instruction.
An integrating router must enforce caller and execution context. Uniswap's SignatureTransfer security guidance describes the failure case where a router accepts someone else's valid signature without checking the intended caller. Its witness variant can bind extra signed trade context; the integration must also enforce the meaning of those fields.
Review the swap's minimum output and price limit alongside the spending permission. They constrain different parts of execution. Likewise, Uniswap v4 hook permissions concern pool callbacks; a hook permission is not evidence that a wallet authorized token spending.
Close access at the layer you intend to retire
Permit2 has separate tools for stored grants and unused signatures. Its AllowanceTransfer interface exposes lockdown to clear selected grant amounts and invalidateNonces to advance a selected owner-token-spender nonce. Clearing an amount does not invalidate a still-usable signed permit; advancing the nonce does not clear an already active amount. SignatureTransfer instead offers bitmap invalidation for selected unordered nonces. Check the relevant state after the operation executes.
Use this worksheet when reviewing a flow or investigating a failed transfer:
| Record | Evidence to capture |
|---|---|
| Identity | Chain, owner, token, Permit2 deployment and downstream spender |
| Upstream permission | Token allowance to Permit2 and read block |
| Reusable grant | Amount, expiration and owner-token-spender nonce |
| One-time permission | Ceiling, deadline, nonce word and bit status |
| Execution intent | Recipient, requested amount and enforced trade constraints |
| Retirement | Successful receipt, resulting permission state and unused signatures addressed |
The token-allowance guide explains the base permission inventory. Add the Permit2 records to it instead of replacing it with a signature history. Keep usable signature bytes out of routine logs and support messages.
Before restoring an upstream token approval, inspect every existing Permit2 grant that the change could make usable again. For an ordinary finite AllowanceTransfer path, compare the requested amount with the owner's balance, the token's allowance to Permit2 and the spender's unexpired internal grant. Record all three at the same block before planning another transfer.
