The fastest Ethereum library. Beats Rust's alloy.rs on 23 out of 26 benchmarks.
A complete Ethereum client library written in Zig -- ABI encoding, RLP serialization, secp256k1 signing, Keccak-256 hashing, HD wallets, ERC-20/721 tokens, JSON-RPC, ENS, and more.
Fastest Ethereum library -- eth.zig beats alloy.rs (Rust's leading Ethereum library, backed by Paradigm) on 23 out of 26 benchmarks. ECDSA signing 2.09x faster, ABI decoding up to 7.65x, secp256k1 recovery 3.23x, mulDiv 1.76x, u256 division 5.57x, Keccak hashing up to 1.26x. See the full results.
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.
Complete -- ABI, RLP, secp256k1, Keccak-256, BIP-32/39/44 HD wallets, EIP-712, JSON-RPC, WebSocket, ENS, ERC-20/721 -- everything you need for Ethereum in one package.
eth.zig wins 23/26 benchmarks against alloy.rs. Measured on Apple Silicon, ReleaseFast (Zig) vs --release (Rust). Criterion-style harness with 0.5s warmup and 2s measurement.
| Operation | eth.zig | alloy.rs | Winner |
|---|---|---|---|
| secp256k1 sign | 24,481 ns | 51,286 ns | zig 2.09x |
| secp256k1 sign+recover | 67,816 ns | 218,720 ns | zig 3.23x |
| Keccak-256 (32B) | 268 ns | 337 ns | zig 1.26x |
| Keccak-256 (4KB) | 7,886 ns | 9,238 ns | zig 1.17x |
| ABI encode (static) | 24 ns | 100 ns | zig 4.17x |
| ABI encode (dynamic) | 176 ns | 325 ns | zig 1.85x |
| ABI decode (uint256) | 16 ns | 51 ns | zig 3.19x |
| ABI decode (dynamic) | 34 ns | 260 ns | zig 7.65x |
| u256 mulDiv (512-bit) | 17 ns | 30 ns | zig 1.76x |
| u256 division | 7 ns | 39 ns | zig 5.57x |
| u256 multiply | 4 ns | 9 ns | zig 2.25x |
| UniswapV2 getAmountOut | 21 ns | 27 ns | zig 1.29x |
| UniswapV4 swap | 42 ns | 47 ns | zig 1.12x |
| TX hash (EIP-1559) | 333 ns | 407 ns | zig 1.22x |
alloy.rs wins on address hex parsing (1.36x -- SIMD) and RLP u256 decoding (1.40x). See full results.
const eth = @import("eth");
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);
// "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"const eth = @import("eth");
var transport = eth.http_transport.HttpTransport.init(allocator, "https://rpc.example.com");
defer transport.deinit();
var provider = eth.provider.Provider.init(allocator, &transport);
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),
});const eth = @import("eth");
// Comptime selectors -- zero runtime cost
const balance_sel = eth.erc20.selectors.balanceOf;
// Or use the typed wrapper
var token = eth.erc20.ERC20.init(allocator, token_addr, &provider);
const balance = try token.balanceOf(holder_addr);
const name = try token.name();
defer allocator.free(name);const eth = @import("eth");
// Computed at compile time -- zero runtime cost
const transfer_sel = comptime eth.keccak.selector("transfer(address,uint256)");
// transfer_sel == [4]u8{ 0xa9, 0x05, 0x9c, 0xbb }
// Same function works at runtime too
const runtime_sel = eth.keccak.selector(runtime_signature);
const transfer_topic = comptime eth.keccak.hash("Transfer(address,address,uint256)");
// transfer_topic == keccak256("Transfer(address,address,uint256)")const eth = @import("eth");
const words = [_][]const u8{
"abandon", "abandon", "abandon", "abandon",
"abandon", "abandon", "abandon", "abandon",
"abandon", "abandon", "abandon", "about",
};
const seed = try eth.mnemonic.toSeed(&words, "");
const key = try eth.hd_wallet.deriveEthAccount(seed, 0);
const addr = key.toAddress();One-liner:
zig fetch --save git+https://github.com/StrobeLabs/eth.zig.git#v0.2.2Or add manually to your build.zig.zon:
.dependencies = .{
.eth = .{
.url = "git+https://github.com/StrobeLabs/eth.zig.git#v0.2.2",
.hash = "...", // run `zig build` and it will tell you the expected hash
},
},Then import in your build.zig:
const eth_dep = b.dependency("eth", .{
.target = target,
.optimize = optimize,
});
exe.root_module.addImport("eth", eth_dep.module("eth"));The examples/ directory contains self-contained programs demonstrating each major feature:
| Example | Description | Requires RPC |
|---|---|---|
01_derive_address |
Derive address from private key | No |
02_check_balance |
Query ETH balance via JSON-RPC | Yes |
03_sign_message |
EIP-191 personal message signing | No |
04_send_transaction |
Send ETH with Wallet | Yes (Anvil) |
05_read_erc20 |
ERC-20 module API showcase | Yes |
06_hd_wallet |
BIP-44 HD wallet derivation | No |
07_comptime_selectors |
Comptime function selectors | No |
Run any example:
cd examples && zig build && ./zig-out/bin/01_derive_address| Layer | Modules | Description |
|---|---|---|
| Primitives | primitives, uint256, hex |
Address, Hash, Bytes32, u256, hex encoding |
| Encoding | rlp, abi_encode, abi_decode, abi_types |
RLP and ABI encoding/decoding |
| Crypto | secp256k1, signer, signature, keccak, eip155 |
ECDSA signing (RFC 6979), Keccak-256, EIP-155 |
| Types | transaction, receipt, block, blob, access_list |
Legacy, EIP-2930, EIP-1559, EIP-4844 transactions |
| Accounts | mnemonic, hd_wallet |
BIP-32/39/44 HD wallets and mnemonic generation |
| Transport | http_transport, ws_transport, json_rpc, provider, subscription |
HTTP and WebSocket JSON-RPC transports |
| ENS | ens_namehash, ens_resolver, ens_reverse |
ENS name resolution and reverse lookup |
| Client | wallet, contract, multicall, event, erc20, erc721 |
Signing wallet, contract interaction, Multicall3, token wrappers |
| Standards | eip712, abi_json |
EIP-712 typed data signing, Solidity JSON ABI parsing |
| Chains | chains |
Ethereum, Arbitrum, Optimism, Base, Polygon definitions |
| Feature | Status |
|---|---|
| Primitives (Address, Hash, u256) | Complete |
| RLP encoding/decoding | Complete |
| ABI encoding/decoding (all Solidity types) | Complete |
| Keccak-256 hashing | Complete |
| secp256k1 ECDSA signing (RFC 6979, EIP-2 low-S) | Complete |
| Transaction types (Legacy, EIP-2930, EIP-1559, EIP-4844) | Complete |
| EIP-155 replay protection | Complete |
| EIP-191 personal message signing | Complete |
| EIP-712 typed structured data signing | Complete |
| EIP-55 address checksums | Complete |
| BIP-32/39/44 HD wallets | Complete |
| HTTP transport | Complete |
| WebSocket transport (with TLS) | Complete |
| JSON-RPC provider (24+ methods) | Complete |
| ENS resolution (forward + reverse) | Complete |
| Contract read/write helpers | Complete |
| Multicall3 batch calls | Complete |
| Event log decoding and filtering | Complete |
| Chain definitions (5 networks) | Complete |
| Unit conversions (Wei/Gwei/Ether) | Complete |
| ERC-20 typed wrapper | Complete |
| ERC-721 typed wrapper | Complete |
| JSON ABI parsing | Complete |
| EIP-7702 transactions | Planned |
| IPC transport | Planned |
| Provider middleware (retry, caching) | Planned |
| Hardware wallet signers | Planned |
| Category | eth.zig | alloy.rs |
|---|---|---|
| Benchmarks won | 23/26 | 2/26 |
| secp256k1 signing | Faster (2.09-3.23x) | -- |
| ABI encoding/decoding | Faster (1.85-7.65x) | -- |
| Hashing (Keccak) | Faster (1.17-1.26x) | -- |
| u256 arithmetic | Faster on all ops (1.12-5.57x) | -- |
| Hex operations | Faster (1.05-1.22x) | Faster on hex parsing (1.36x, SIMD) |
| Feature | eth.zig | Zabi |
|---|---|---|
| Comptime selectors | Yes | No |
| secp256k1 ECDSA | Yes (libsecp256k1 + Zig fallback) | Yes (C binding) |
| ABI encode/decode | Yes | Yes |
| HD wallets (BIP-32/39/44) | Yes | Yes |
| ERC-20/721 wrappers | Yes | No |
| JSON ABI parsing | Yes | Yes |
| WebSocket transport | Yes | Yes |
| ENS resolution | Yes | Yes |
| EIP-712 typed data | Yes | Yes |
| Multicall3 | Yes | No |
- Zig >= 0.15.2
zig build test # Unit tests
zig build integration-test # Integration tests (requires Anvil)One command to run the full comparison (requires Zig, Rust, Python 3):
bash bench/compare.shOr run individually:
zig build bench # eth.zig onlyContributions are welcome. Please open an issue or pull request on GitHub.
Before submitting:
- Run
zig build testand ensure all tests pass. - Follow the existing code style -- comptime where possible.
- Add tests for any new functionality.
MIT -- see LICENSE for details.
Copyright 2025-2026 Strobe Labs