eth.zig

eth.zig

The fastest Ethereum library. Pure Zig. Zero dependencies.

The fastest Ethereum library. Pure Zig. Zero dependencies.

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 19 out of 26 benchmarks, including ABI encoding, Keccak-256 hashing, u256 arithmetic, and UniswapV4 mulDiv.
  • Zero dependencies -- Built entirely on Zig's standard library. No C bindings, no vendored C code, no system libraries. Just zig build and go.
  • 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.
  • Pure Zig crypto -- secp256k1 ECDSA, Keccak-256, BIP-32/39/44 HD wallets -- all implemented in pure Zig. No OpenSSL, no libsecp256k1, no FFI.

Performance vs alloy.rs

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

Operationeth.zigalloy.rsWinner
Keccak-256 (32B)128 ns175 nszig 1.37x
ABI encode (static)29 ns50 nszig 1.72x
ABI decode (dynamic)75 ns133 nszig 1.77x
u256 division3 ns12 nszig 4.00x
u256 multiply2 ns5 nszig 2.50x
UniswapV4 mulDiv12 ns17 nszig 1.42x
Hex decode (32B)12 ns24 nszig 2.00x
Address from hex8 ns13 nszig 1.62x

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(.{}){};
    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