Skip to content

Commit dca9144

Browse files
authored
Remove abi_comptime module: unify selector/hash API (#25)
* Remove abi_comptime module: unify selector/hash API for comptime+runtime Library functions no longer restrict callers with comptime parameters. keccak.selector() and keccak.hash() work at both comptime and runtime -- the caller decides by using the `comptime` keyword or not. Closes #23 * Remove comptime_address: rename to addressFromHex for comptime+runtime use Same pattern as the selector/hash fix -- the caller decides whether to evaluate at comptime, not the library.
1 parent e7e2125 commit dca9144

22 files changed

Lines changed: 86 additions & 202 deletions

CONTRIBUTING.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ Layer 1: Primitives (zero deps, no allocator needed)
3535
primitives.zig, uint256.zig, hex.zig
3636
3737
Layer 2: Encoding (-> primitives)
38-
rlp.zig, abi_encode.zig, abi_decode.zig, abi_types.zig, abi_comptime.zig
38+
rlp.zig, abi_encode.zig, abi_decode.zig, abi_types.zig
3939
4040
Layer 3: Crypto (-> primitives)
4141
keccak.zig, secp256k1.zig, signature.zig

README.md

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -92,16 +92,19 @@ const name = try token.name();
9292
defer allocator.free(name);
9393
```
9494

95-
### Comptime function selectors and event topics
95+
### Function selectors and event topics
9696

9797
```zig
9898
const eth = @import("eth");
9999
100100
// Computed at compile time -- zero runtime cost
101-
const transfer_sel = eth.abi_comptime.comptimeSelector("transfer(address,uint256)");
101+
const transfer_sel = comptime eth.keccak.selector("transfer(address,uint256)");
102102
// transfer_sel == [4]u8{ 0xa9, 0x05, 0x9c, 0xbb }
103103
104-
const transfer_topic = eth.abi_comptime.comptimeTopic("Transfer(address,address,uint256)");
104+
// Same function works at runtime too
105+
const runtime_sel = eth.keccak.selector(runtime_signature);
106+
107+
const transfer_topic = comptime eth.keccak.hash("Transfer(address,address,uint256)");
105108
// transfer_topic == keccak256("Transfer(address,address,uint256)")
106109
```
107110

@@ -174,7 +177,7 @@ cd examples && zig build && ./zig-out/bin/01_derive_address
174177
| Layer | Modules | Description |
175178
|-------|---------|-------------|
176179
| **Primitives** | `primitives`, `uint256`, `hex` | Address, Hash, Bytes32, u256, hex encoding |
177-
| **Encoding** | `rlp`, `abi_encode`, `abi_decode`, `abi_types`, `abi_comptime` | RLP and ABI encoding/decoding, comptime selectors |
180+
| **Encoding** | `rlp`, `abi_encode`, `abi_decode`, `abi_types` | RLP and ABI encoding/decoding |
178181
| **Crypto** | `secp256k1`, `signer`, `signature`, `keccak`, `eip155` | ECDSA signing (RFC 6979), Keccak-256, EIP-155 |
179182
| **Types** | `transaction`, `receipt`, `block`, `blob`, `access_list` | Legacy, EIP-2930, EIP-1559, EIP-4844 transactions |
180183
| **Accounts** | `mnemonic`, `hd_wallet` | BIP-32/39/44 HD wallets and mnemonic generation |

docs/content/docs/comptime.mdx

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,31 @@
11
---
22
title: Comptime Selectors
3-
description: Compile-time function selectors and event topics -- a key differentiator of eth.zig.
3+
description: Function selectors and event topics that work at both compile time and runtime.
44
---
55

6-
One of eth.zig's most powerful features is **comptime-first design**. Function selectors and event topics are computed at compile time, eliminating runtime hashing entirely.
6+
eth.zig provides unified `keccak.selector()` and `keccak.hash()` functions that work at both compile time and runtime. The **caller** decides when to evaluate -- the library never restricts you.
77

88
## Function Selectors
99

10-
A Solidity function selector is the first 4 bytes of the Keccak-256 hash of the function signature. In eth.zig, this is done at compile time:
10+
A Solidity function selector is the first 4 bytes of the Keccak-256 hash of the function signature. Use `comptime` for zero runtime cost:
1111

1212
```zig
1313
const eth = @import("eth");
1414
15-
// Computed at compile time -- zero runtime cost
16-
const transfer_sel = eth.abi_comptime.comptimeSelector("transfer(address,uint256)");
15+
// Evaluated at compile time -- zero runtime cost
16+
const transfer_sel = comptime eth.keccak.selector("transfer(address,uint256)");
1717
// transfer_sel == [4]u8{ 0xa9, 0x05, 0x9c, 0xbb }
1818
19-
const approve_sel = eth.abi_comptime.comptimeSelector("approve(address,uint256)");
19+
const approve_sel = comptime eth.keccak.selector("approve(address,uint256)");
2020
// approve_sel == [4]u8{ 0x09, 0x5e, 0xa7, 0xb3 }
2121
```
2222

23-
The Zig compiler evaluates `comptimeSelector` during compilation. The resulting binary contains only the precomputed 4-byte selectors -- no hashing at runtime.
23+
The same function also works at runtime with dynamic strings:
24+
25+
```zig
26+
// Runtime -- useful when the signature is only known at runtime
27+
const runtime_sel = eth.keccak.selector(some_signature);
28+
```
2429

2530
## Event Topics
2631

@@ -29,21 +34,18 @@ Event topics (used for log filtering) work the same way:
2934
```zig
3035
const eth = @import("eth");
3136
32-
const transfer_topic = eth.abi_comptime.comptimeTopic("Transfer(address,address,uint256)");
37+
const transfer_topic = comptime eth.keccak.hash("Transfer(address,address,uint256)");
3338
// transfer_topic == keccak256("Transfer(address,address,uint256)")
3439
35-
const approval_topic = eth.abi_comptime.comptimeTopic("Approval(address,address,uint256)");
40+
const approval_topic = comptime eth.keccak.hash("Approval(address,address,uint256)");
3641
```
3742

3843
## Why This Matters
3944

40-
In other Ethereum libraries, function selectors are typically computed at runtime:
41-
4245
| Approach | When It Runs | Cost |
4346
|----------|-------------|------|
44-
| eth.zig `comptimeSelector` | Compile time | 0 ns at runtime |
45-
| Runtime `keccak256(signature)` | Every call | ~128 ns per hash |
46-
| Cached/lazy hash | First call | ~128 ns once, then lookup |
47+
| `comptime eth.keccak.selector(...)` | Compile time | 0 ns at runtime |
48+
| `eth.keccak.selector(runtime_str)` | Runtime | ~128 ns per hash |
4749

4850
For hot paths (MEV bots, indexers, high-frequency DeFi), eliminating per-call hashing overhead adds up.
4951

@@ -73,17 +75,17 @@ Define selectors for any contract function:
7375
const eth = @import("eth");
7476
7577
// UniswapV2 Router
76-
const swap_sel = eth.abi_comptime.comptimeSelector(
78+
const swap_sel = comptime eth.keccak.selector(
7779
"swapExactTokensForTokens(uint256,uint256,address[],address,uint256)"
7880
);
7981
8082
// Aave V3 Pool
81-
const supply_sel = eth.abi_comptime.comptimeSelector(
83+
const supply_sel = comptime eth.keccak.selector(
8284
"supply(address,uint256,address,uint16)"
8385
);
8486
8587
// Any custom function
86-
const my_sel = eth.abi_comptime.comptimeSelector(
88+
const my_sel = comptime eth.keccak.selector(
8789
"myFunction(uint256,bytes32,bool)"
8890
);
8991
```

docs/content/docs/contracts.mdx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ Use `contractRead` to call a contract function and decode the result:
1313
const eth = @import("eth");
1414
1515
// Define the function selector (comptime -- zero runtime cost)
16-
const balanceOf_sel = eth.abi_comptime.comptimeSelector("balanceOf(address)");
16+
const balanceOf_sel = comptime eth.keccak.selector("balanceOf(address)");
1717
1818
// Read balanceOf for a given address
1919
const results = try eth.contract.contractRead(
@@ -36,7 +36,7 @@ Use `contractWrite` to send a state-changing transaction:
3636
```zig
3737
const eth = @import("eth");
3838
39-
const transfer_sel = eth.abi_comptime.comptimeSelector("transfer(address,uint256)");
39+
const transfer_sel = comptime eth.keccak.selector("transfer(address,uint256)");
4040
4141
const tx_hash = try eth.contract.contractWrite(
4242
allocator,

docs/content/docs/contributing.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ Layer 1: Primitives (zero deps, no allocator needed)
3838
primitives.zig, uint256.zig, hex.zig
3939
4040
Layer 2: Encoding (-> primitives)
41-
rlp.zig, abi_encode.zig, abi_decode.zig, abi_types.zig, abi_comptime.zig
41+
rlp.zig, abi_encode.zig, abi_decode.zig, abi_types.zig
4242
4343
Layer 3: Crypto (-> primitives)
4444
keccak.zig, secp256k1.zig, signature.zig

docs/content/docs/examples.mdx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,16 +70,19 @@ const name = try token.name();
7070
defer allocator.free(name);
7171
```
7272

73-
## Comptime Function Selectors
73+
## Function Selectors
7474

7575
```zig
7676
const eth = @import("eth");
7777
7878
// Computed at compile time -- zero runtime cost
79-
const transfer_sel = eth.abi_comptime.comptimeSelector("transfer(address,uint256)");
79+
const transfer_sel = comptime eth.keccak.selector("transfer(address,uint256)");
8080
// transfer_sel == [4]u8{ 0xa9, 0x05, 0x9c, 0xbb }
8181
82-
const transfer_topic = eth.abi_comptime.comptimeTopic("Transfer(address,address,uint256)");
82+
// Same function works at runtime too
83+
const runtime_sel = eth.keccak.selector(some_signature);
84+
85+
const transfer_topic = comptime eth.keccak.hash("Transfer(address,address,uint256)");
8386
// transfer_topic == keccak256("Transfer(address,address,uint256)")
8487
```
8588

docs/content/docs/modules.mdx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,19 +26,21 @@ RLP and ABI encoding/decoding with comptime support.
2626
| `abi_encode` | `encode`, `encodePacked` | ABI encoding for function calls and data |
2727
| `abi_decode` | `decode`, `decodeOutput` | ABI decoding of return values and calldata |
2828
| `abi_types` | `AbiType`, `Function`, `Event` | ABI type definitions |
29-
| `abi_comptime` | `comptimeSelector`, `comptimeTopic` | Compile-time function selectors and event topics |
3029
| `abi_json` | `parseAbi` | Parse Solidity JSON ABI files |
3130

32-
### Comptime Selectors
31+
### Function Selectors
3332

3433
```zig
3534
const eth = @import("eth");
3635
3736
// Computed at compile time -- zero runtime cost
38-
const transfer_sel = eth.abi_comptime.comptimeSelector("transfer(address,uint256)");
37+
const transfer_sel = comptime eth.keccak.selector("transfer(address,uint256)");
3938
// transfer_sel == [4]u8{ 0xa9, 0x05, 0x9c, 0xbb }
4039
41-
const transfer_topic = eth.abi_comptime.comptimeTopic("Transfer(address,address,uint256)");
40+
// Same function works at runtime with dynamic strings
41+
const runtime_sel = eth.keccak.selector(some_signature);
42+
43+
const transfer_topic = comptime eth.keccak.hash("Transfer(address,address,uint256)");
4244
// transfer_topic == keccak256("Transfer(address,address,uint256)")
4345
```
4446

docs/content/docs/tokens.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ For state-changing operations, use the contract module with a Wallet:
5050
```zig
5151
const eth = @import("eth");
5252
53-
const transfer_sel = eth.abi_comptime.comptimeSelector("transfer(address,uint256)");
53+
const transfer_sel = comptime eth.keccak.selector("transfer(address,uint256)");
5454
5555
const tx_hash = try eth.contract.contractWrite(
5656
allocator,
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
// Example 07: Unified comptime/runtime selectors and event topics
1+
// Example 07: Function selectors and event topics
22
//
33
// Pure compute -- no RPC connection needed.
4-
// Showcases eth.zig's unified API: keccak.selector() and keccak.hash()
5-
// work at both comptime and runtime. The caller decides.
4+
// keccak.selector() and keccak.hash() work at both comptime and runtime.
5+
// The caller decides by using the `comptime` keyword or not.
66

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

src/abi_comptime.zig

Lines changed: 0 additions & 96 deletions
This file was deleted.

0 commit comments

Comments
 (0)