> ## Documentation Index
> Fetch the complete documentation index at: https://voltaire.tevm.sh/llms.txt
> Use this file to discover all available pages before exploring further.

# Permit

> EIP-2612 Permit signatures for gasless token approvals

# Permit

EIP-2612 Permit signatures enable gasless token approvals through meta-transactions. Users sign an off-chain message granting approval, which can be submitted by a relayer paying the gas.

## Overview

EIP-2612 extends ERC-20 tokens with a `permit` function that accepts EIP-712 signed messages. This enables:

* **Gasless approvals**: Users don't need ETH to approve tokens
* **Single-transaction flows**: Approve + transfer in one transaction
* **Meta-transactions**: Relayers can pay gas on behalf of users
* **Better UX**: No separate approval transaction needed

## Types

### PermitType

```typescript theme={null}
interface PermitType {
  readonly owner: AddressType;
  readonly spender: AddressType;
  readonly value: Uint256Type;
  readonly nonce: Uint256Type;
  readonly deadline: Uint256Type;
}
```

### PermitDomainType

```typescript theme={null}
interface PermitDomainType {
  readonly name: string;
  readonly version: string;
  readonly chainId: ChainIdType;
  readonly verifyingContract: AddressType;
}
```

## Methods

### createPermitSignature

Creates an EIP-712 signature for a permit message.

```typescript theme={null}
import * as Permit from '@tevm/primitives/Permit';
import * as Address from '@tevm/primitives/Address';
import * as Uint256 from '@tevm/primitives/Uint256';

const permit: Permit.PermitType = {
  owner: Address.fromHex('0x...'),
  spender: Address.fromHex('0x...'),
  value: Uint256.fromBigInt(1000000n),
  nonce: Uint256.fromBigInt(0n),
  deadline: Uint256.fromBigInt(BigInt(Math.floor(Date.now() / 1000) + 3600)),
};

const domain: Permit.PermitDomainType = {
  name: 'USD Coin',
  version: '2',
  chainId: 1,
  verifyingContract: Address.fromHex('0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48'),
};

const signature = Permit.createPermitSignature(permit, domain, privateKey);
```

### verifyPermit

Verifies a permit signature matches the permit data and domain.

```typescript theme={null}
const isValid = Permit.verifyPermit(permit, signature, domain);
```

## Known Tokens

Pre-configured domain data for popular ERC-2612 tokens:

```typescript theme={null}
import * as Permit from '@tevm/primitives/Permit';

// USDC Mainnet
const domain = Permit.KnownTokens.USDC_MAINNET;

// DAI Mainnet
const domain = Permit.KnownTokens.DAI_MAINNET;

// Other tokens
Permit.KnownTokens.USDC_POLYGON
Permit.KnownTokens.USDC_ARBITRUM
Permit.KnownTokens.USDT_MAINNET
Permit.KnownTokens.UNI_MAINNET
Permit.KnownTokens.WETH_MAINNET
```

## Complete Example

```typescript theme={null}
import * as Permit from '@tevm/primitives/Permit';
import * as Address from '@tevm/primitives/Address';
import * as Uint256 from '@tevm/primitives/Uint256';

// Setup
const owner = Address.fromHex('0x...');
const spender = Address.fromHex('0x...');
const amount = Uint256.fromBigInt(1000000n); // 1 USDC

// Create permit
const permit: Permit.PermitType = {
  owner,
  spender,
  value: amount,
  nonce: Uint256.fromBigInt(0n),
  deadline: Uint256.fromBigInt(BigInt(Math.floor(Date.now() / 1000) + 3600)),
};

// Sign with known token domain
const domain = Permit.KnownTokens.USDC_MAINNET;
const signature = Permit.createPermitSignature(permit, domain, privateKey);

// Verify
const isValid = Permit.verifyPermit(permit, signature, domain);

// Submit to contract
const { r, s, v } = parseSignature(signature);
await contract.permit(
  permit.owner,
  permit.spender,
  permit.value,
  permit.deadline,
  v,
  r,
  s
);
```

## Security Considerations

### Deadline

Always set a reasonable deadline. Expired permits can't be used:

```typescript theme={null}
// 1 hour from now
const deadline = Uint256.fromBigInt(BigInt(Math.floor(Date.now() / 1000) + 3600));
```

### Nonce Management

Each permit must use the owner's current nonce. Replay protection:

```typescript theme={null}
// Query on-chain nonce
const nonce = await contract.nonces(owner);
```

### Domain Verification

Ensure the domain matches the token contract:

```typescript theme={null}
// Verify domain separator
const onChainSeparator = await contract.DOMAIN_SEPARATOR();
```

### Amount Limits

Be careful with unlimited approvals:

```typescript theme={null}
// Limited approval
const amount = Uint256.fromBigInt(1000000n);

// Unlimited (use with caution)
const unlimited = Uint256.MAX;
```

## See Also

* [Permit (Effect)](https://voltaire-effect.tevm.sh/primitives/permit) - Effect.ts integration with Schema validation

## References

* [EIP-2612: Permit Extension for EIP-20](https://eips.ethereum.org/EIPS/eip-2612)
* [EIP-712: Typed Structured Data Hashing and Signing](/crypto/eip712)
