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

# Precompiles Reference

> All 20 EVM precompile implementations

# Precompiles Reference

EVM precompiled contracts in `src/evm/precompiles/`. Each has a fixed address and provides optimized operations.

## Overview

```typescript theme={null}
import { execute, isPrecompile } from "@voltaire/evm/precompiles";

// Check if address is precompile
isPrecompile(address, hardfork);

// Execute precompile
const { output, gasUsed } = execute(address, input, gasLimit, hardfork);
```

## Precompile Addresses

| Address | Name                    | Hardfork  | Purpose                        |
| ------- | ----------------------- | --------- | ------------------------------ |
| 0x01    | ECRECOVER               | Frontier  | Signature recovery             |
| 0x02    | SHA256                  | Frontier  | SHA-256 hash                   |
| 0x03    | RIPEMD160               | Frontier  | RIPEMD-160 hash                |
| 0x04    | IDENTITY                | Frontier  | Data copy                      |
| 0x05    | MODEXP                  | Byzantium | Modular exponentiation         |
| 0x06    | BN254\_ADD              | Byzantium | BN254 G1 addition              |
| 0x07    | BN254\_MUL              | Byzantium | BN254 G1 multiplication        |
| 0x08    | BN254\_PAIRING          | Byzantium | BN254 pairing check            |
| 0x09    | BLAKE2F                 | Istanbul  | Blake2 compression             |
| 0x0A    | POINT\_EVALUATION       | Cancun    | KZG point evaluation           |
| 0x0B    | BLS12\_G1\_ADD          | Prague    | BLS12-381 G1 addition          |
| 0x0C    | BLS12\_G1\_MUL          | Prague    | BLS12-381 G1 multiplication    |
| 0x0D    | BLS12\_G1\_MSM          | Prague    | BLS12-381 G1 multi-scalar mult |
| 0x0E    | BLS12\_G2\_ADD          | Prague    | BLS12-381 G2 addition          |
| 0x0F    | BLS12\_G2\_MUL          | Prague    | BLS12-381 G2 multiplication    |
| 0x10    | BLS12\_G2\_MSM          | Prague    | BLS12-381 G2 multi-scalar mult |
| 0x11    | BLS12\_PAIRING          | Prague    | BLS12-381 pairing check        |
| 0x12    | BLS12\_MAP\_FP\_TO\_G1  | Prague    | Map field element to G1        |
| 0x13    | BLS12\_MAP\_FP2\_TO\_G2 | Prague    | Map field element to G2        |

***

## Frontier Precompiles (0x01-0x04)

### ECRECOVER (0x01)

Recovers signer address from ECDSA signature.

**Input** (128 bytes):

* `[0:32]` - Message hash
* `[32:64]` - v (recovery id, 27 or 28)
* `[64:96]` - r (signature component)
* `[96:128]` - s (signature component)

**Output**: 32 bytes (address right-padded)

**Gas**: 3000

```typescript theme={null}
const input = concat(messageHash, v, r, s);
const { output } = execute(0x01, input, 3000n);
const address = output.slice(12);  // Last 20 bytes
```

**Files**: `ecrecover.zig`, `ecrecover.test.ts`, `ecrecover.bench.ts`

### SHA256 (0x02)

Computes SHA-256 hash.

**Input**: Arbitrary bytes
**Output**: 32 bytes (hash)

**Gas**: `60 + 12 * ceil(len / 64)`

```typescript theme={null}
const { output } = execute(0x02, data, 1000n);
// output is SHA-256 hash
```

**Files**: `sha256.zig`, `sha256.test.ts`, `sha256.bench.ts`

### RIPEMD160 (0x03)

Computes RIPEMD-160 hash.

**Input**: Arbitrary bytes
**Output**: 32 bytes (20-byte hash left-padded with zeros)

**Gas**: `600 + 120 * ceil(len / 64)`

```typescript theme={null}
const { output } = execute(0x03, data, 1000n);
const hash = output.slice(12);  // Last 20 bytes
```

**Files**: `ripemd160.zig`, `ripemd160.test.ts`, `ripemd160.bench.ts`

### IDENTITY (0x04)

Returns input unchanged. Used for memory copying in contracts.

**Input**: Arbitrary bytes
**Output**: Same as input

**Gas**: `15 + 3 * ceil(len / 32)`

```typescript theme={null}
const { output } = execute(0x04, data, 100n);
// output === data
```

**Files**: `identity.zig`, `identity.test.ts`, `identity.bench.ts`

***

## Byzantium Precompiles (0x05-0x08)

### MODEXP (0x05)

Modular exponentiation: `base^exp mod mod`.

**Input**:

* `[0:32]` - base length (Bsize)
* `[32:64]` - exponent length (Esize)
* `[64:96]` - modulus length (Msize)
* `[96:96+Bsize]` - base
* `[96+Bsize:96+Bsize+Esize]` - exponent
* `[96+Bsize+Esize:96+Bsize+Esize+Msize]` - modulus

**Output**: Msize bytes (result)

**Gas**: Complex formula based on input sizes (see EIP-2565)

```typescript theme={null}
const input = concat(
  padLeft(baseLen, 32),
  padLeft(expLen, 32),
  padLeft(modLen, 32),
  base,
  exp,
  mod
);
const { output } = execute(0x05, input, gasLimit);
```

**Files**: `modexp.zig`, `modexp.test.ts`, `modexp.bench.ts`

### BN254\_ADD (0x06)

Adds two points on BN254 G1 curve.

**Input** (128 bytes):

* `[0:32]` - x1
* `[32:64]` - y1
* `[64:96]` - x2
* `[96:128]` - y2

**Output**: 64 bytes (x3, y3)

**Gas**: 150 (post-Istanbul)

```typescript theme={null}
const input = concat(p1.x, p1.y, p2.x, p2.y);
const { output } = execute(0x06, input, 150n);
const result = { x: output.slice(0, 32), y: output.slice(32, 64) };
```

**Files**: `bn254_add.zig`, `bn254_precompiles.test.ts`

### BN254\_MUL (0x07)

Scalar multiplication on BN254 G1 curve.

**Input** (96 bytes):

* `[0:32]` - x
* `[32:64]` - y
* `[64:96]` - scalar

**Output**: 64 bytes (x\_result, y\_result)

**Gas**: 6000 (post-Istanbul)

**Files**: `bn254_mul.zig`

### BN254\_PAIRING (0x08)

Pairing check on BN254 curve.

**Input**: `k * 192` bytes (k pairs of G1, G2 points)

* Each pair: G1 (64 bytes) + G2 (128 bytes)

**Output**: 32 bytes (1 if pairing check passes, 0 otherwise)

**Gas**: `34000 * k + 45000` (post-Istanbul)

```typescript theme={null}
// Verify e(A1, B1) * e(A2, B2) * ... = 1
const input = concat(...pairs.flatMap(p => [p.g1, p.g2]));
const { output } = execute(0x08, input, gasLimit);
const valid = output[31] === 1;
```

**Files**: `bn254_pairing.zig`

***

## Istanbul Precompile (0x09)

### BLAKE2F (0x09)

Blake2b compression function F.

**Input** (213 bytes):

* `[0:4]` - rounds (big-endian uint32)
* `[4:68]` - h (state, 8 uint64s)
* `[68:196]` - m (message block, 16 uint64s)
* `[196:212]` - t (offset counter, 2 uint64s)
* `[212:213]` - f (final block flag, 0 or 1)

**Output**: 64 bytes (new state)

**Gas**: `rounds`

```typescript theme={null}
const input = concat(rounds, h, m, t, f);
const { output } = execute(0x09, input, roundsValue);
```

**Files**: `blake2f.zig`, `blake2f.test.ts`, `blake2f.bench.ts`

***

## Cancun Precompile (0x0A)

### POINT\_EVALUATION (0x0A)

KZG point evaluation for EIP-4844 blob verification.

**Input** (192 bytes):

* `[0:32]` - versioned hash
* `[32:64]` - z (evaluation point)
* `[64:96]` - y (claimed evaluation)
* `[96:144]` - commitment (48 bytes)
* `[144:192]` - proof (48 bytes)

**Output**: 64 bytes

* `[0:32]` - FIELD\_ELEMENTS\_PER\_BLOB (4096)
* `[32:64]` - BLS\_MODULUS

**Gas**: 50000

```typescript theme={null}
const input = concat(versionedHash, z, y, commitment, proof);
const { output } = execute(0x0A, input, 50000n);
// Success if no error thrown
```

**Files**: `point_evaluation.zig`, `precompiles.kzg.test.ts`

***

## Prague Precompiles (0x0B-0x13)

BLS12-381 curve operations for beacon chain compatibility.

### BLS12\_G1\_ADD (0x0B)

Add two G1 points.

**Input**: 256 bytes (two 128-byte G1 points)
**Output**: 128 bytes (G1 point)
**Gas**: 500

### BLS12\_G1\_MUL (0x0C)

Scalar multiply G1 point.

**Input**: 160 bytes (128-byte G1 point + 32-byte scalar)
**Output**: 128 bytes (G1 point)
**Gas**: 12000

### BLS12\_G1\_MSM (0x0D)

Multi-scalar multiplication on G1.

**Input**: `k * 160` bytes (k pairs of point + scalar)
**Output**: 128 bytes (G1 point)
**Gas**: Discount formula based on k

### BLS12\_G2\_ADD (0x0E)

Add two G2 points.

**Input**: 512 bytes (two 256-byte G2 points)
**Output**: 256 bytes (G2 point)
**Gas**: 800

### BLS12\_G2\_MUL (0x0F)

Scalar multiply G2 point.

**Input**: 288 bytes (256-byte G2 point + 32-byte scalar)
**Output**: 256 bytes (G2 point)
**Gas**: 45000

### BLS12\_G2\_MSM (0x10)

Multi-scalar multiplication on G2.

**Input**: `k * 288` bytes
**Output**: 256 bytes (G2 point)
**Gas**: Discount formula based on k

### BLS12\_PAIRING (0x11)

Pairing check.

**Input**: `k * 384` bytes (k pairs of G1 + G2)
**Output**: 32 bytes (1 or 0)
**Gas**: `43000 * k + 65000`

### BLS12\_MAP\_FP\_TO\_G1 (0x12)

Map field element to G1 point.

**Input**: 64 bytes (field element)
**Output**: 128 bytes (G1 point)
**Gas**: 5500

### BLS12\_MAP\_FP2\_TO\_G2 (0x13)

Map Fp2 element to G2 point.

**Input**: 128 bytes (Fp2 element)
**Output**: 256 bytes (G2 point)
**Gas**: 75000

**Files**:

* `bls12_g1_add.zig`, `bls12_g1_mul.zig`, `bls12_g1_msm.zig`
* `bls12_g2_add.zig`, `bls12_g2_mul. zig`, `bls12_g2_msm.zig`
* `bls12_pairing.zig`
* `bls12_map_fp_to_g1.zig`, `bls12_map_fp2_to_g2.zig`
* `precompiles.bls12.test.ts`

***

## Common Utilities

### root.zig exports

```zig theme={null}
// Address constants
pub const ECRECOVER_ADDRESS: Address = 0x01;
pub const SHA256_ADDRESS: Address = 0x02;
// ... etc

// Check if address is precompile
pub fn isPrecompile(address: Address, hardfork: Hardfork) bool;

// Execute precompile
pub fn execute(address: Address, input: []const u8, gas: u64, hardfork: Hardfork) !ExecuteResult;
```

### common.zig

Shared utilities:

* Input validation
* Gas calculation helpers
* Point encoding/decoding
* Error types

### utils.zig

* Big integer operations
* Field element arithmetic
* Padding utilities

***

## Gas Costs by Hardfork

| Precompile     | Frontier     | Byzantium    | Istanbul     | Berlin       |
| -------------- | ------------ | ------------ | ------------ | ------------ |
| ECRECOVER      | 3000         | 3000         | 3000         | 3000         |
| SHA256         | 60+12/word   | 60+12/word   | 60+12/word   | 60+12/word   |
| RIPEMD160      | 600+120/word | 600+120/word | 600+120/word | 600+120/word |
| IDENTITY       | 15+3/word    | 15+3/word    | 15+3/word    | 15+3/word    |
| MODEXP         | -            | Complex      | EIP-2565     | EIP-2565     |
| BN254\_ADD     | -            | 500          | 150          | 150          |
| BN254\_MUL     | -            | 40000        | 6000         | 6000         |
| BN254\_PAIRING | -            | 80k+base     | 34k\*k+45k   | 34k\*k+45k   |
| BLAKE2F        | -            | -            | rounds       | rounds       |

***

## Error Handling

Precompiles return errors for:

* Invalid input length
* Invalid curve points (not on curve)
* Invalid field elements (>= modulus)
* Insufficient gas
* Unsupported hardfork

```zig theme={null}
pub const PrecompileError = error{
    InvalidInputLength,
    InvalidPoint,
    InvalidFieldElement,
    OutOfGas,
    NotSupported,
};
```
