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

# What is Permit3?

> Multi-chain token permissions protocol extending Permit2

[Permit3](https://github.com/eco/permit3) is an open-source token approval protocol that enables multichain token permission with a single signature and full gas abstraction. It eliminates the need for redundant approvals and native gas tokens, letting developers simplify cross-chain token operations with a single user signature. Permit3 extends the concepts introduced by Permit2 to support multi-chain operations through Unbalanced Merkle Trees, while maintaining full backward compatibility with it.

## The Problem

When protocols need to coordinate token operations across multiple chains, users face compounding issues:

* Multiple approval transactions per chain
* Separate signatures for each blockchain
* Complex coordination between different chain states
* Race conditions when executing cross-chain operations

## Standard Cross-Chain Flow

The traditional multi-chain approach requires:

* User approves Protocol A on Chain 1
* User approves Protocol A on Chain 2
* User signs/submits transaction on Chain 1
* User signs/submits transaction on Chain 2
* Protocol coordinates between chains (often through bridges or relayers)

This results in 4+ transactions and multiple signatures for a single logical operation.

## Permit3 Model

<img src="https://mintcdn.com/ecoinc/zqqCfNkjhHFRZzqI/images/routes/permit3.jpg?fit=max&auto=format&n=zqqCfNkjhHFRZzqI&q=85&s=2e2f6e029462eb2ad35d99a628707ade" alt="Permi3 Architecture" width="3200" height="1800" data-path="images/routes/permit3.jpg" />

Permit3 introduces a unified approach:

* User calls approve() on each chain's ERC20 tokens to grant infinite allowance to the canonical Permit3 contract (one-time setup per token per chain)
* User signs a single offchain permit message containing a merkle root of all intended operations across chains
* The signed message and merkle proofs are distributed to relevant chains by app
* Each chain's protocol contract calls Permit3 contract with the appropriate merkle proof
* Permit3 verifies the proof against the signed root and executes the permitted operations

## Core Components

The Permit3 system consists of three main components:

### Permit3 Contract

The main contract that inherits from PermitBase and NonceManager, implementing the core functionality:

* Processes permit signatures for approvals and transfers
* Verifies EIP-712 signatures with standard and witness data
* Handles cross-chain operations through hash chaining
* Implements witness functionality for custom data verification

### PermitBase Contract

Manages token approvals and transfers:

* Tracks allowances with amounts and expiration times
* Handles token transfers through approvals
* Implements allowance modes (increase, decrease, lock, unlock)
* Provides emergency account locking functionality

### NonceManager Contract

Handles nonce management for replay protection:

* Uses non-sequential nonces for gas efficiency
* Supports cross-chain nonce invalidation
* Implements salt-based signature replay protection
* Provides domain separation for EIP-712 signatures

## Contract Inheritance Structure

```
                 ┌───────────────┐
                 │   EIP-712     │
                 └───────┬───────┘
                         │
                 ┌───────┴───────┐
                 │ NonceManager  │
                 └───────┬───────┘
                         │
                 ┌───────┴───────┐
                 │  PermitBase   │
                 └───────┬───────┘
                         │
                 ┌───────┴───────┐
                 │    Permit3    │
                 └───────────────┘
```

## Key Data Structures

### Allowance Structure

```solidity theme={null}
struct Allowance {
    uint160 amount;        // Approved amount
    uint48 expiration;     // Timestamp when approval expires
    uint48 timestamp;      // Timestamp when approval was set
}
```

### AllowanceOrTransfer Structure

```solidity theme={null}
struct AllowanceOrTransfer {
    uint48 modeOrExpiration;  // Operation mode or expiration time
    address token;            // Token address
    address account;          // Spender or recipient
    uint160 amountDelta;      // Amount change
}
```

### ChainPermits Structure

```solidity theme={null}
struct ChainPermits {
    uint64 chainId;              // Target chain ID (uint64 for gas optimization)
    AllowanceOrTransfer[] permits; // Operations for this chain
}
```

### Cross-Chain Permit Parameters

In the implementation, cross-chain operations use separate parameters:

```solidity theme={null}
function permit(
    address owner,
    bytes32 salt,
    uint48 deadline,
    uint48 timestamp,
    ChainPermits calldata permits,    // Permit operations for the current chain
    bytes32[] calldata proof,         // Standard merkle proof using OpenZeppelin's MerkleProof
    bytes calldata signature
) external;

// Uses OpenZeppelin's MerkleProof.processProof() with bytes32[] arrays
// Each element represents a sibling hash needed for proof verification
```

## Core Operations

### 1. Permit Processing

Permit3 supports two main permit functions:

1. **Single Chain Permits**:
   * Process token approvals for a specific chain
   * Verify signature against chain permits
   * Update allowances or execute transfers

2. **Cross-Chain Permits**:
   * Process token approvals across multiple chains
   * Chain permit hashes together for verification
   * Execute operations on current chain only

Both functions can be extended with witness functionality to include custom data in signature verification.

### 2. Allowance Management

Permit3 supports five operation modes controlled by the `modeOrExpiration` parameter:

1. **Transfer Mode** (`modeOrExpiration = 0`):
   * Executes immediate token transfer
   * `account` field represents recipient
   * `amountDelta` represents transfer amount

2. **Decrease Mode** (`modeOrExpiration = 1`):
   * Reduces existing allowance
   * `amountDelta` represents decrease amount
   * Special case: `type(uint160).max` resets to 0

3. **Lock Mode** (`modeOrExpiration = 2`):
   * Locks allowance for security
   * Blocks any increases or transfers
   * Requires newer timestamp to unlock

4. **Unlock Mode** (`modeOrExpiration = 3`):
   * Cancels locked state
   * Sets new allowance amount
   * Requires newer timestamp than lock

5. **Increase Mode** (`modeOrExpiration > 3`):
   * Value represents expiration timestamp
   * Increases allowance by `amountDelta`
   * Updates expiration if timestamp is newer

### 3. Nonce Management

Permit3 uses non-sequential nonces with salt parameters:

```solidity theme={null}
function _useNonce(address owner, bytes32 salt) internal {
    if (usedNonces[owner][salt] != NONCE_NOT_USED) {
        revert NonceAlreadyUsed(owner, salt);
    }
    usedNonces[owner][salt] = NONCE_USED;
}
```

This approach:

* Enables concurrent operations with different salts
* Optimizes gas usage compared to sequential nonces
* Supports cross-chain nonce management
* Prevents signature replay attacks

### 4. Witness Functionality

Witness functionality extends the standard permit flow:

1. **Type String Construction**:
   ```solidity theme={null}
   bytes32 typeHash = keccak256(
       abi.encodePacked(PERMIT_WITNESS_TYPEHASH_STUB, witnessTypeString)
   );
   ```

2. **Signature Verification**:
   ```solidity theme={null}
   bytes32 signedHash = keccak256(
       abi.encode(
           typeHash,
           permitDataHash,
           owner,
           salt,
           deadline,
           timestamp,
           witness
       )
   );
   ```

3. **Processing**:
   After verification, the permit is processed using the standard flow while the application can verify the witness data.

## Cross-Chain Mechanism

Permit3 enables cross-chain operations through Unbalanced Merkle Trees:

1. Hash permits for each chain individually
2. Build an Unbalanced Merkle Tree from all chain hashes (two-part structure)
3. Sign the Unbalanced root
4. Generate Unbalanced proofs for each chain
5. Process the portion relevant to the current chain

This approach leverages the two-part design:

* **Bottom Part**: Efficient membership proofs within individual chains
* **Top Part**: Unbalanced upper structure that minimizes calldata for chains with high gas costs
* **Verification**: Merkle tree verification for security and compatibility
* **Benefits**: One signature for multiple chains with gas optimization potential
* **Security**: Chain ID validation prevents cross-chain replay attacks
* **Extensibility**: Supports witness data across chains with future optimization opportunities

### Unbalanced Merkle tree Example

```solidity theme={null}
// Calculate the leaf hash for this chain's permits  
bytes32 leaf = permit3.hashChainPermits(proof.permits);

// Verify the Unbalanced Merkle Tree proof using OpenZeppelin's MerkleProof
// (traverses both balanced subtrees and unbalanced upper structure)
bool valid = MerkleProof.processProof(
    proof.proof,
    leaf
) == merkleRoot;

// Verify signature against Unbalanced root
bytes32 signedHash = keccak256(abi.encode(
    SIGNED_PERMIT3_TYPEHASH, 
    owner, 
    salt, 
    deadline, 
    timestamp, 
    merkleRoot  // The hybrid structure root
));
```

## Security Features

Permit3 implements several security features:

1. **Signature Validation**:
   * EIP-712 typed signatures for structured data
   * Signature replay protection through nonces
   * Deadline validation to prevent expired signatures

2. **Access Control**:
   * Allowance-based access for token operations
   * Time-bound permissions with expiration timestamps
   * Owner validation for all operations

3. **Account Locking**:
   * Special locked state for emergency security
   * Operations blocked until explicit unlock
   * Timestamp validation for unlock operations

4. **Chain ID Validation**:
   * Explicit chain ID verification
   * Prevents cross-chain replay attacks
   * Works with witness functionality

5. **Timestamp Ordering**:
   * Operations ordered by timestamp across chains
   * Prevents race conditions in cross-chain operations
   * Critical for asynchronous allowance updates

## Gas Optimization

Permit3 implements several gas optimization strategies:

1. **Non-Sequential Nonces**:
   * Bitmap-based nonce tracking
   * Constant gas cost regardless of nonce value
   * Efficient for concurrent operations

2. **Batched Operations**:
   * Process multiple permits in one transaction
   * Amortize fixed costs across operations
   * Reduce total transaction count

3. **Efficient Storage**:
   * Packed storage slots for allowances
   * Minimal state updates
   * Optimized data types

4. **Cross-Chain Efficiency**:
   * Execute only relevant operations on each chain
   * Single signature for multiple chains leveraging two-part structure
   * Optimized Unbalanced tree structure with gas optimization potential

## Integration with External Systems

Permit3 is designed for seamless integration:

1. **Permit2 Compatibility**:
   * Implements IPermit interface for compatibility with contracts that are already using Permit2 for transfers
   * Existing contracts integrated with Permit2 can work with Permit3 without any changes
   * Maintains backward compatibility while offering enhanced functionality

2. **ERC20 Token Interaction**:
   * Works with any ERC20 token
   * No special token requirements
   * Compatible with standard token interfaces

3. **Cross-Contract Integration**:
   * Clear interfaces for external contracts
   * Witness functionality for custom verification
   * Support for complex integration patterns

## Deployments

Permit3 contracts are deployed at `0xEc00030C0000245E27d1521Cc2EE88F071c2Ae34` on all supported chains.
