Tutorial·8 min का पठन·Solingo द्वारा

Permit2 — Uniswap का Token Approval Revolution

हर app के लिए एक approval। Permit2 approvals को एक ही battle-tested contract के पीछे consolidate करता है।

# Permit2 — Uniswap का Token Approval Revolution

Token approvals annoying हैं — हर नए dapp के लिए एक approval tx।

Permit2 इसे solve करता है: एक approval, सभी apps के लिए।

Problem: Approval Hell

Traditional Flow

// User wants to swap USDC on Uniswap
  • approve(uniswap, type(uint).max) // Tx 1
  • swap(...) // Tx 2
  • // Now user wants to use Curve

  • approve(curve, type(uint).max) // Tx 3
  • swap(...) // Tx 4
  • // Now 1inch

  • approve(1inch, type(uint).max) // Tx 5
  • ...

    Problems:

    • Gas waste (approval tx हर app के लिए)
    • Security risk (infinite approvals scattered)
    • UX nightmare (2 tx for every new app)

    Permit2 Solution

    // Once per token
    

    approve(Permit2, type(uint).max) // One-time

    // Then use any app (via signatures, gasless!)

    Uniswap.swap(permit2Signature) // ✅ No approval tx

    Curve.swap(permit2Signature) // ✅ No approval tx

    1inch.swap(permit2Signature) // ✅ No approval tx

    Benefits:

    • One approval per token (lifetime)
    • Apps don't touch token directly
    • Revocable permissions
    • Gasless (signature-based)

    Architecture

    ┌─────────┐
    

    │ User │

    └────┬────┘

    │ 1. Approve Permit2 (once)

    ┌─────────────┐

    │ Token │

    └──────┬──────┘

    │ 2. Permit2 can transfer

    ┌─────────────┐

    │ Permit2 │ ← Shared contract

    └──────┬──────┘

    │ 3. App requests transfer via Permit2

    ┌─────────────┐

    │ Uniswap │

    │ Curve │

    │ 1inch │

    └─────────────┘

    Two Transfer Modes

    1. AllowanceTransfer

    App-specific allowances through Permit2:

    interface IAllowanceTransfer {
    

    function approve(

    address token,

    address spender, // App (Uniswap, etc)

    uint160 amount,

    uint48 expiration // Time-bound!

    ) external;

    function transferFrom(

    address from,

    address to,

    uint160 amount,

    address token

    ) external;

    }

    Example:

    // User approves Uniswap via Permit2 (on-chain tx)
    

    permit2.approve(USDC, uniswapRouter, 1000e6, block.timestamp + 1 days);

    // Uniswap transfers via Permit2

    permit2.transferFrom(user, pool, 1000e6, USDC);

    Benefit: Expiring allowances (no infinite approvals)।

    2. SignatureTransfer (Gasless!)

    Transfer via signature — no approval tx:

    struct PermitTransferFrom {
    

    TokenPermissions permitted; // token + amount

    address spender; // App

    uint256 nonce;

    uint256 deadline;

    }

    struct TokenPermissions {

    address token;

    uint256 amount;

    }

    User signs:

    const permit = {
    

    permitted: {

    token: USDC_ADDRESS,

    amount: 1000e6

    },

    spender: UNISWAP_ROUTER,

    nonce: await permit2.nonces(userAddress),

    deadline: Math.floor(Date.now() / 1000) + 3600

    }

    const signature = await wallet._signTypedData(domain, types, permit)

    App uses:

    function swap(PermitTransferFrom calldata permit, bytes calldata signature) external {
    

    // Permit2 verifies signature + transfers token

    permit2.permitTransferFrom(

    permit,

    SignatureTransferDetails({

    to: address(this),

    requestedAmount: permit.permitted.amount

    }),

    msg.sender,

    signature

    );

    // Now we have tokens, execute swap

    _executeSwap();

    }

    UX:

    User clicks "Swap"
    

    → Wallet shows signature request (free!)

    → App submits tx with signature

    → Done (1 tx total, user pays 0 gas for approval)

    Integration Example

    DEX Router

    import {ISignatureTransfer} from "permit2/interfaces/ISignatureTransfer.sol";
    
    

    contract MyDEX {

    ISignatureTransfer public immutable permit2;

    constructor(address _permit2) {

    permit2 = ISignatureTransfer(_permit2);

    }

    function swapWithPermit(

    ISignatureTransfer.PermitTransferFrom calldata permit,

    bytes calldata signature,

    address tokenOut,

    uint amountOutMin

    ) external returns (uint amountOut) {

    // Transfer tokenIn from user via Permit2

    permit2.permitTransferFrom(

    permit,

    ISignatureTransfer.SignatureTransferDetails({

    to: address(this),

    requestedAmount: permit.permitted.amount

    }),

    msg.sender,

    signature

    );

    // Execute swap

    amountOut = _swap(

    permit.permitted.token,

    tokenOut,

    permit.permitted.amount,

    amountOutMin

    );

    // Send output to user

    IERC20(tokenOut).transfer(msg.sender, amountOut);

    }

    }

    Frontend

    import { SignatureTransfer } from '@uniswap/permit2-sdk'
    
    

    const permit: PermitTransferFrom = {

    permitted: {

    token: USDC.address,

    amount: parseUnits('1000', 6)

    },

    spender: DEX_ROUTER,

    nonce: await permit2.nonces(account),

    deadline: Math.floor(Date.now() / 1000) + 3600

    }

    const { domain, types, values } = SignatureTransfer.getPermitData(

    permit,

    PERMIT2_ADDRESS,

    chainId

    )

    const signature = await signer._signTypedData(domain, types, values)

    // Submit tx

    await dex.swapWithPermit(permit, signature, DAI.address, minAmountOut)

    Security Properties

    1. Expiration

    // Allowance expires after 1 day
    

    permit2.approve(token, spender, amount, block.timestamp + 1 days);

    Traditional approvals = forever। Permit2 = time-bound।

    2. Nonces

    // Each signature uses unique nonce
    

    mapping(address => uint256) public nonces;

    Prevents replay attacks।

    3. Witness Data

    struct PermitWitnessTransferFrom {
    

    PermitTransferFrom permit;

    bytes32 witness; // Additional data user signs

    }

    Example: User signs swap params too (slippage, deadline)।

    bytes32 witness = keccak256(abi.encode(
    

    tokenOut,

    amountOutMin,

    deadline

    ));

    Prevents parameter manipulation।

    4. Permit2 is Immutable

    // Deployed by Uniswap, audited, immutable
    

    // Address: 0x000000000022D473030F116dDEE9F6B43aC78BA3

    No upgrade risk — battle-tested code।

    Gotchas

    User Still Needs Initial Approval

    // User must approve Permit2 once per token
    

    IERC20(token).approve(permit2Address, type(uint256).max);

    UX: First tx per token still needed।

    Mitigation: Batch approvals (approve multiple tokens in one tx)।

    Not All Apps Support

    2026 में adoption growing लेकिन universal नहीं:

    • ✅ Uniswap, 1inch, Cowswap
    • ✅ Most new DEXs
    • ❌ Many old contracts (pre-2023)

    Gas Overhead

    Signature verification ~3-5k gas extra:

    Traditional: approve() + transferFrom() = 50k gas
    

    Permit2: permitTransferFrom() = 55k gas (first time)

    permitTransferFrom() = 35k gas (subsequent, cached)

    Net: Saves gas after first use।

    Adoption (2026)

    Protocols Using Permit2

    • Uniswap V3/V4: Default
    • 1inch: Full support
    • Cowswap: Intent-based (Permit2 perfect fit)
    • Across: Cross-chain bridging
    • Most ERC-7683 implementations

    How to Check

    // Check if contract supports Permit2
    

    try IPermit2User(contract).permit2() returns (address p2) {

    // Supports Permit2 ✅

    } catch {

    // Fallback to traditional approve

    }

    Comparison

    | Method | Approval Cost | Transfer Cost | Expiry | Revocable |

    |--------|---------------|---------------|--------|-----------|

    | Traditional | 45k gas | 30k gas | Never | Manual |

    | Permit2 Allowance | 0 (signature) | 35k gas | Yes | Yes |

    | Permit2 Signature | 0 (signature) | 40k gas | Per-tx | N/A |

    Conclusion

    Permit2 new standard बन रहा है — खासकर intents और gasless UX के लिए।

    When to use:

    • New dapp building? Integrate Permit2 from day 1
    • Existing app? Add Permit2 as optional flow
    • User-facing product? Gasless approvals = better UX

    Adoption tips:

    • Use @uniswap/permit2-sdk (official SDK)
    • Support fallback to traditional approvals
    • Educate users (one-time approval per token)

    2026 में Permit2 = best practice for token transfers। Ignore at your own UX peril। ✅

    Practice में लगाने के लिए तैयार हैं?

    Solingo पर interactive exercises के साथ इन concepts को apply करें।

    मुफ्त में शुरू करें