eth.zig

eth.zig

The fastest Ethereum library. Beats Rust on 23 of 26 benchmarks.

The fastest Ethereum library. Beats alloy.rs on 23 of 26 benchmarks.

eth.zig provides everything you need to interact with Ethereum from Zig -- signing transactions, encoding ABI calls, managing HD wallets, reading ERC-20 tokens, talking to nodes over JSON-RPC, and more.

Why eth.zig?

  • Faster than Rust -- eth.zig beats alloy.rs (Rust's leading Ethereum library, backed by Paradigm) on 23 out of 26 benchmarks, including secp256k1 signing (2.10x), ABI decoding (8.00x), mulDiv (1.71x), Keccak-256 hashing, and all u256 arithmetic.
  • Comptime-first -- Function selectors and event topics are computed at compile time with zero runtime cost. The compiler does the hashing so your program doesn't have to.

Performance vs alloy.rs

eth.zig wins 23/26 benchmarks against alloy.rs. Measured on Apple Silicon, ReleaseFast (Zig) vs --release (Rust).

Operationeth.zigalloy.rsWinner
secp256k1 sign24,609 ns51,738 nszig 2.10x
secp256k1 sign+recover54,221 ns218,790 nszig 4.04x
ABI decode (dynamic)32 ns256 nszig 8.00x
ABI encode (static)24 ns97 nszig 4.04x
u256 division7 ns24 nszig 3.43x
u256 mulDiv (512-bit)17 ns29 nszig 1.71x
Keccak-256 (32B)259 ns336 nszig 1.30x
TX hash (EIP-1559)328 ns402 nszig 1.23x

See the full benchmark results for all 26 operations.

Quick Start

const std = @import("std");
const eth = @import("eth");

pub fn main() !void {
    var gpa: std.heap.GeneralPurposeAllocator(.{}) = .init;
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();

    // WARNING: This is the default Anvil/Hardhat test key. Never use it for real funds.
    const private_key = try eth.hex.hexToBytesFixed(32, "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80");
    const signer = eth.signer.Signer.init(private_key);
    const addr = try signer.address();
    const checksum = eth.primitives.addressToChecksum(&addr);
    _ = checksum;

    // Sign and send a transaction
    var transport = eth.http_transport.HttpTransport.init(allocator, "https://rpc.example.com");
    defer transport.deinit();
    var provider = eth.provider.Provider.init(allocator, &transport);

    const recipient_address = try eth.hex.hexToBytesFixed(20, "0000000000000000000000000000000000000000");
    var wallet = eth.wallet.Wallet.init(allocator, private_key, &provider);
    const tx_hash = try wallet.sendTransaction(.{
        .to = recipient_address,
        .value = eth.units.parseEther(1.0),
    });
    _ = tx_hash;
}

Guides

Resources