> ## 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.

# Gas Calculations

> Gas Calculations

<Card title="Try it Live" icon="play" href="https://playground.tevm.sh?example=primitives/authorization.ts">
  Run Authorization examples in the interactive playground
</Card>

# Gas Calculations

Calculate gas costs for EIP-7702 authorizations.

## Overview

EIP-7702 authorization processing has two gas cost components:

1. **Base cost per authorization:** 12,500 gas
2. **Empty account cost:** 25,000 gas (if delegated address is empty)

Total cost: `(authCount * 12500) + (emptyCount * 25000)`

## Constants

```typescript theme={null}
Authorization.PER_AUTH_BASE_COST = 12500n;      // Base gas per authorization
Authorization.PER_EMPTY_ACCOUNT_COST = 25000n;  // Gas for empty account
```

## calculateGasCost

Calculate total gas cost for authorization list.

```typescript theme={null}
Authorization.calculateGasCost.call(
  authList: Authorization.Item[],
  emptyAccounts: number
): bigint
```

**Parameters:**

* `authList`: Array of authorizations
* `emptyAccounts`: Number of empty accounts being delegated to

**Returns:** Total gas cost as bigint

**Formula:** `(authList.length * 12500) + (emptyAccounts * 25000)`

### Usage

```typescript theme={null}
import { Authorization } from 'tevm';

const authList: Authorization.Item[] = [auth1, auth2, auth3];
const emptyAccountCount = 2;

const gas = Authorization.calculateGasCost.call(authList, emptyAccountCount);
console.log(`Total gas: ${gas}`);
// gas = (3 * 12500) + (2 * 25000) = 87500
```

### Examples

**All empty accounts:**

```typescript theme={null}
const gas = Authorization.calculateGasCost.call([auth1, auth2], 2);
// (2 * 12500) + (2 * 25000) = 75000
```

**No empty accounts:**

```typescript theme={null}
const gas = Authorization.calculateGasCost.call([auth1, auth2], 0);
// (2 * 12500) + (0 * 25000) = 25000
```

**Empty list:**

```typescript theme={null}
const gas = Authorization.calculateGasCost.call([], 0);
// (0 * 12500) + (0 * 25000) = 0
```

**Mixed:**

```typescript theme={null}
const gas = Authorization.calculateGasCost.call([auth1, auth2, auth3, auth4], 1);
// (4 * 12500) + (1 * 25000) = 75000
```

## getGasCost

Calculate gas cost for single authorization.

```typescript theme={null}
Authorization.getGasCost.call(
  auth: Authorization.Item,
  isEmpty: boolean
): bigint
```

**Parameters:**

* `auth`: Authorization to calculate cost for
* `isEmpty`: Whether delegated address is empty

**Returns:** Gas cost as bigint

**Formula:**

* If empty: `12500 + 25000 = 37500`
* If not empty: `12500`

### Usage

```typescript theme={null}
import { Authorization } from 'tevm';

const auth: Authorization.Item = {...};

// Empty account
const gasIfEmpty = Authorization.getGasCost.call(auth, true);
console.log(`Gas (empty): ${gasIfEmpty}`);
// 37500

// Non-empty account
const gasIfNotEmpty = Authorization.getGasCost.call(auth, false);
console.log(`Gas (not empty): ${gasIfNotEmpty}`);
// 12500
```

## Empty Account Detection

### What is an Empty Account?

An account is considered empty if:

* Balance = 0
* Nonce = 0
* Code length = 0
* Storage is empty

### Checking if Account is Empty

```typescript theme={null}
import { Authorization } from 'tevm';

async function isAccountEmpty(address: Address): Promise<boolean> {
  const balance = await getBalance(address);
  const nonce = await getNonce(address);
  const code = await getCode(address);

  return balance === 0n && nonce === 0n && code.length === 0;
}

// Use in gas calculation
const isEmpty = await isAccountEmpty(auth.address);
const gas = Authorization.getGasCost.call(auth, isEmpty);
```

### Counting Empty Accounts

```typescript theme={null}
import { Authorization } from 'tevm';

async function countEmptyAccounts(
  authList: Authorization.Item[]
): Promise<number> {
  let count = 0;

  for (const auth of authList) {
    const isEmpty = await isAccountEmpty(auth.address);
    if (isEmpty) count++;
  }

  return count;
}

// Use in gas calculation
const emptyCount = await countEmptyAccounts(authList);
const gas = Authorization.calculateGasCost.call(authList, emptyCount);
```

## Gas Estimation Patterns

### Pre-transaction Estimation

Estimate gas before sending transaction:

```typescript theme={null}
import { Authorization } from 'tevm';

async function estimateAuthGas(
  authList: Authorization.Item[]
): Promise<bigint> {
  // Count empty accounts
  const emptyCount = await countEmptyAccounts(authList);

  // Calculate authorization gas
  const authGas = Authorization.calculateGasCost.call(authList, emptyCount);

  // Add execution gas (estimated separately)
  const executionGas = 21000n; // Base transaction cost
  const totalGas = authGas + executionGas;

  return totalGas;
}

const gasEstimate = await estimateAuthGas(authList);
console.log(`Estimated gas: ${gasEstimate}`);
```

### With Gas Limit

Check if within gas limit:

```typescript theme={null}
import { Authorization } from 'tevm';

async function validateGasLimit(
  authList: Authorization.Item[],
  gasLimit: bigint
): Promise<void> {
  const emptyCount = await countEmptyAccounts(authList);
  const authGas = Authorization.calculateGasCost.call(authList, emptyCount);

  if (authGas > gasLimit) {
    throw new Error(
      `Authorization gas (${authGas}) exceeds limit (${gasLimit})`
    );
  }
}

await validateGasLimit(authList, 100000n);
```

### Per-Authorization Cost Breakdown

Calculate cost for each authorization:

```typescript theme={null}
import { Authorization } from 'tevm';

interface AuthGasCost {
  auth: Authorization.Item;
  isEmpty: boolean;
  gas: bigint;
}

async function calculateIndividualCosts(
  authList: Authorization.Item[]
): Promise<AuthGasCost[]> {
  const costs: AuthGasCost[] = [];

  for (const auth of authList) {
    const isEmpty = await isAccountEmpty(auth.address);
    const gas = Authorization.getGasCost.call(auth, isEmpty);

    costs.push({ auth, isEmpty, gas });
  }

  return costs;
}

const costs = await calculateIndividualCosts(authList);
costs.forEach((c, i) => {
  console.log(`Auth ${i}: ${c.gas} gas (${c.isEmpty ? 'empty' : 'not empty'})`);
});
```

## Optimization Strategies

### Minimize Empty Account Delegations

Empty accounts cost more gas. Prefer delegating to deployed contracts:

```typescript theme={null}
// More expensive: delegate to empty address
const expensiveAuth = {
  chainId: 1n,
  address: emptyAddress,  // 37,500 gas
  nonce: 0n
};

// Cheaper: delegate to deployed contract
const cheaperAuth = {
  chainId: 1n,
  address: deployedContract,  // 12,500 gas
  nonce: 0n
};
```

### Batch Size Optimization

Larger batches have better gas efficiency per authorization:

```typescript theme={null}
import { Authorization } from 'tevm';

function calculateEfficiency(
  authCount: number,
  emptyCount: number
): number {
  const totalGas = Authorization.calculateGasCost.call(
    new Array(authCount).fill(null),
    emptyCount
  );

  const gasPerAuth = Number(totalGas) / authCount;
  return gasPerAuth;
}

// Examples
calculateEfficiency(1, 0);   // 12,500 gas/auth
calculateEfficiency(10, 0);  // 12,500 gas/auth (same)
calculateEfficiency(1, 1);   // 37,500 gas/auth
calculateEfficiency(10, 5);  // 25,000 gas/auth (better due to batching)
```

### Deduplication

Remove duplicate delegations to save gas:

```typescript theme={null}
import { Authorization, Address } from 'tevm';

function deduplicateByAddress(
  authList: Authorization.Item[]
): Authorization.Item[] {
  const seen = new Set<string>();
  const unique: Authorization.Item[] = [];

  for (const auth of authList) {
    const key = Address.toHex(auth.address);

    if (!seen.has(key)) {
      seen.add(key);
      unique.push(auth);
    }
  }

  return unique;
}

const deduplicated = deduplicateByAddress(authList);
const savedAuths = authList.length - deduplicated.length;
const savedGas = BigInt(savedAuths) * Authorization.PER_AUTH_BASE_COST;

console.log(`Saved ${savedGas} gas by removing ${savedAuths} duplicates`);
```

## Gas Cost Tables

### Base Costs

| Scenario                | Authorizations | Empty Accounts | Gas Cost |
| ----------------------- | -------------- | -------------- | -------- |
| Single (empty)          | 1              | 1              | 37,500   |
| Single (not empty)      | 1              | 0              | 12,500   |
| Batch of 5 (all empty)  | 5              | 5              | 187,500  |
| Batch of 5 (none empty) | 5              | 0              | 62,500   |
| Batch of 10 (5 empty)   | 10             | 5              | 250,000  |

### Cost per Authorization

| Empty Accounts | Gas per Auth     |
| -------------- | ---------------- |
| All empty      | 37,500           |
| None empty     | 12,500           |
| 50% empty      | 25,000 (average) |
| 25% empty      | 18,750 (average) |

## Advanced Patterns

### Dynamic Gas Pricing

Adjust authorization list based on gas price:

```typescript theme={null}
import { Authorization } from 'tevm';

async function optimizeAuthList(
  authList: Authorization.Item[],
  maxGas: bigint
): Promise<Authorization.Item[]> {
  // Calculate costs
  const costs = await calculateIndividualCosts(authList);

  // Sort by cost (cheapest first)
  costs.sort((a, b) => Number(a.gas - b.gas));

  // Include as many as possible within budget
  const optimized: Authorization.Item[] = [];
  let totalGas = 0n;

  for (const cost of costs) {
    if (totalGas + cost.gas <= maxGas) {
      optimized.push(cost.auth);
      totalGas += cost.gas;
    }
  }

  return optimized;
}

const optimized = await optimizeAuthList(authList, 100000n);
```

### Gas Budget Allocation

Allocate gas budget across authorization types:

```typescript theme={null}
import { Authorization } from 'tevm';

interface GasBudget {
  empty: bigint;
  nonEmpty: bigint;
}

function allocateBudget(totalGas: bigint): GasBudget {
  // Reserve 60% for base costs, 40% for empty accounts
  const baseGas = (totalGas * 60n) / 100n;
  const emptyGas = (totalGas * 40n) / 100n;

  return { empty: emptyGas, nonEmpty: baseGas };
}

function calculateMaxAuths(budget: GasBudget): {
  maxEmpty: number;
  maxNonEmpty: number;
} {
  const maxEmpty = Number(budget.empty / Authorization.PER_EMPTY_ACCOUNT_COST);
  const maxNonEmpty = Number(budget.nonEmpty / Authorization.PER_AUTH_BASE_COST);

  return { maxEmpty, maxNonEmpty };
}

const budget = allocateBudget(100000n);
const max = calculateMaxAuths(budget);
console.log(`Can include up to ${max.maxNonEmpty} non-empty or ${max.maxEmpty} empty`);
```

### Gas Monitoring

Track gas usage during processing:

```typescript theme={null}
import { Authorization } from 'tevm';

class GasMonitor {
  private totalGas = 0n;
  private authCount = 0;
  private emptyCount = 0;

  async addAuth(auth: Authorization.Item): Promise<void> {
    const isEmpty = await isAccountEmpty(auth.address);
    const gas = Authorization.getGasCost.call(auth, isEmpty);

    this.totalGas += gas;
    this.authCount++;
    if (isEmpty) this.emptyCount++;
  }

  getStats(): {
    totalGas: bigint;
    authCount: number;
    emptyCount: number;
    avgGasPerAuth: number;
  } {
    return {
      totalGas: this.totalGas,
      authCount: this.authCount,
      emptyCount: this.emptyCount,
      avgGasPerAuth: Number(this.totalGas) / this.authCount
    };
  }

  reset(): void {
    this.totalGas = 0n;
    this.authCount = 0;
    this.emptyCount = 0;
  }
}

const monitor = new GasMonitor();
for (const auth of authList) {
  await monitor.addAuth(auth);
}
console.log(monitor.getStats());
```

## Testing

### Test Gas Calculations

```typescript theme={null}
import { Authorization } from 'tevm';

// Empty list
expect(Authorization.calculateGasCost.call([], 0)).toBe(0n);

// Single non-empty
expect(Authorization.getGasCost.call(auth, false)).toBe(12500n);

// Single empty
expect(Authorization.getGasCost.call(auth, true)).toBe(37500n);

// Batch
const gas = Authorization.calculateGasCost.call([auth1, auth2, auth3], 2);
expect(gas).toBe(87500n); // (3 * 12500) + (2 * 25000)
```

## Performance

Gas calculation is O(1):

```typescript theme={null}
// Constant time calculation
const gas = Authorization.calculateGasCost.call(authList, emptyCount);
// gas = authList.length * 12500 + emptyCount * 25000
```

## See Also

* [Processing](./processing) - Authorization processing
* [EIP-7702](./eip7702) - Gas specification
* [Validation](./validation) - Pre-processing validation
