Skip to content
Back to skills

Permit2 Signature Transfer

ASecurity

Uses permitWitnessTransferFrom for gasless token transfers with EIP-712 signatures. Use when implementing swap/deposit/withdraw with Permit2 signature-based authorization.

  • 9 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added September 10, 2026
businesstypescript

Security analysis

A100/100

Pro scans all 2 files and shows the line behind each finding

Scanned September 10, 2026

npx -y skills add cyotee/indexedex --skill permit2-signature-transfer --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Permit2 Signature Transfer?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Permit2 Signature Transfer
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/cyotee-permit2-signature-transfer/badge)](https://www.skillsdirectory.com/skills/cyotee-permit2-signature-transfer)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: permit2-signature-transfer
description: Uses permitWitnessTransferFrom for gasless token transfers with EIP-712 signatures. Use when implementing swap/deposit/withdraw with Permit2 signature-based authorization.
---

# Permit2 Signature Transfer

The recommended pattern for IndexedEx operations. Users sign **one EIP-712 message** off-chain - no pre-approval needed.

## Quick Start

```typescript
import { SignatureTransfer, PERMIT2_ADDRESS } from '@uniswap/permit2-sdk'
import { useSignTypedData, useWriteContract } from 'wagmi'
import { parseUnits, keccak256, encodePacked } from 'viem'

// Build permit (what user authorizes)
const permit: SignatureTransfer.PermitTransferFrom = {
  permitted: { token: tokenInAddress, amount: parseUnits('100', 6) },
  nonce: BigInt(Date.now()) << 8n,
  deadline: BigInt(Math.floor(Date.now() / 1000) + 1800n)
}

// Build witness (binds signature to this specific action)
const witness = {
  actionId: keccak256(encodePacked(
    ['address', 'address', 'address', 'uint256'],
    [tokenIn, tokenOut, vaultAddress, amountIn]
  )),
}

// Get EIP-712 data
const { domain, types, values } = SignatureTransfer.getPermitData(
  permit,
  PERMIT2_ADDRESS,
  chainId,
  { witness, witnessTypeName: 'Witness', witnessType: WITNESS_TYPE }
)

// User signs
const signature = await signTypedDataAsync(domain, types, values)
```

## Witness Types

### For exchangeIn (Exact In Swap)

```typescript
const WITNESS_TYPE: Record<string, TypedDataField[]> = {
  Witness: [{ name: 'actionId', type: 'bytes32' }]
}
```

### For exchangeOut (Exact Out Swap)

```typescript
// actionId includes maxAmountIn since that's variable
const witness = {
  actionId: keccak256(encodePacked(
    ['address', 'address', 'address', 'uint256', 'uint256'],
    [tokenIn, tokenOut, vaultAddress, amountOut, maxAmountIn]
  ))
}
```

## Contract Integration

See `permit2-signature-transfer-contract` skill for Solidity implementation.

Files in this skill

  • README.md1 KB
  • SKILL.md1.9 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.