Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions bench/bench.zig
Original file line number Diff line number Diff line change
Expand Up @@ -114,19 +114,19 @@ fn benchKeccak32() void {
}

fn benchKeccak256b() void {
const data: [256]u8 = .{0xAB} ** 256;
const data: [256]u8 = @splat(0xAB);
const result = eth.keccak.hash(&data);
std.mem.doNotOptimizeAway(&result);
}

fn benchKeccak1k() void {
const data: [1024]u8 = .{0xAB} ** 1024;
const data: [1024]u8 = @splat(0xAB);
const result = eth.keccak.hash(&data);
std.mem.doNotOptimizeAway(&result);
}

fn benchKeccak4k() void {
const data: [4096]u8 = .{0xAB} ** 4096;
const data: [4096]u8 = @splat(0xAB);
const result = eth.keccak.hash(&data);
std.mem.doNotOptimizeAway(&result);
}
Expand Down Expand Up @@ -475,7 +475,7 @@ pub fn main() !void {
const stdout = &w.interface;

try stdout.print("\n{s:<34} {s:>12} {s:>14}\n", .{ "Benchmark", "ns/op", "iters" });
try stdout.print("{s}\n", .{"-" ** 64});
try stdout.print("{s}\n", .{"" ++ @as([64]u8, @splat('-'))});

// Keccak256
try runAndPrint("keccak256_empty", benchKeccakEmpty, stdout);
Expand Down
10 changes: 5 additions & 5 deletions bench/keccak_compare.zig
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ const std = @import("std");
const eth = @import("eth");

// Test data
const DATA_32: [32]u8 = .{0xAB} ** 32;
const DATA_256: [256]u8 = .{0xAB} ** 256;
const DATA_1K: [1024]u8 = .{0xAB} ** 1024;
const DATA_4K: [4096]u8 = .{0xAB} ** 4096;
const DATA_32: [32]u8 = @splat(0xAB);
const DATA_256: [256]u8 = @splat(0xAB);
const DATA_1K: [1024]u8 = @splat(0xAB);
const DATA_4K: [4096]u8 = @splat(0xAB);

// ============================================================================
// Benchmark harness (same as bench.zig / u256_bench.zig)
Expand Down Expand Up @@ -115,7 +115,7 @@ pub fn main() !void {
const stdout = &w.interface;

try stdout.print("\n{s:<30} {s:>12} {s:>14}\n", .{ "Benchmark", "ns/op", "iters" });
try stdout.print("{s}\n", .{"-" ** 60});
try stdout.print("{s}\n", .{"" ++ @as([60]u8, @splat('-'))});

// eth.zig
try runAndPrint("eth.zig keccak empty", benchEthKeccakEmpty, stdout);
Expand Down
2 changes: 1 addition & 1 deletion bench/u256_bench.zig
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ pub fn main() !void {
const stdout = &w.interface;

try stdout.print("\n{s:<32} {s:>12} {s:>14}\n", .{ "Benchmark", "ns/op", "iters" });
try stdout.print("{s}\n", .{"-" ** 62});
try stdout.print("{s}\n", .{"" ++ @as([62]u8, @splat('-'))});

try runAndPrint("u256_add", benchAdd, stdout);
try runAndPrint("u256_mul_small", benchMulSmall, stdout);
Expand Down
46 changes: 23 additions & 23 deletions src/abi_decode.zig
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ test "decode single uint256" {
const allocator = testing.allocator;

// Encode uint256(100) = 32 zero bytes with 0x64 at position 31
var data: [32]u8 = [_]u8{0} ** 32;
var data: [32]u8 = @as([32]u8, @splat(0));
data[31] = 0x64;

const types = [_]AbiType{.uint256};
Expand All @@ -255,7 +255,7 @@ test "decode single address" {
const allocator = testing.allocator;

// Address is left-padded: 12 zero bytes + 20 address bytes
var data: [32]u8 = [_]u8{0} ** 32;
var data: [32]u8 = @as([32]u8, @splat(0));
data[12] = 0xdE;
data[13] = 0xAD;
data[30] = 0xBE;
Expand All @@ -275,15 +275,15 @@ test "decode single address" {
test "decode bool true and false" {
const allocator = testing.allocator;

var true_data: [32]u8 = [_]u8{0} ** 32;
var true_data: [32]u8 = @as([32]u8, @splat(0));
true_data[31] = 1;

const types = [_]AbiType{.bool};
const true_values = try decodeValues(&true_data, &types, allocator);
defer freeValues(true_values, allocator);
try testing.expect(true_values[0].boolean);

var false_data: [32]u8 = [_]u8{0} ** 32;
var false_data: [32]u8 = @as([32]u8, @splat(0));
const false_values = try decodeValues(&false_data, &types, allocator);
defer freeValues(false_values, allocator);
try testing.expect(!false_values[0].boolean);
Expand All @@ -293,7 +293,7 @@ test "decode int256 negative" {
const allocator = testing.allocator;

// -1 in two's complement = all 0xff bytes
var data: [32]u8 = [_]u8{0xff} ** 32;
var data: [32]u8 = @as([32]u8, @splat(0xff));

const types = [_]AbiType{.int256};
const values = try decodeValues(&data, &types, allocator);
Expand All @@ -305,7 +305,7 @@ test "decode int256 negative" {
test "decode fixed bytes4" {
const allocator = testing.allocator;

var data: [32]u8 = [_]u8{0} ** 32;
var data: [32]u8 = @as([32]u8, @splat(0));
data[0] = 0xde;
data[1] = 0xad;
data[2] = 0xbe;
Expand All @@ -326,7 +326,7 @@ test "decode multiple static values" {
const allocator = testing.allocator;

// address, uint256, bool
var data: [96]u8 = [_]u8{0} ** 96;
var data: [96]u8 = @as([96]u8, @splat(0));
// Address at word 0
data[31] = 0x01;
// uint256(100) at word 1
Expand All @@ -351,7 +351,7 @@ test "decode dynamic bytes" {
// Word 0: offset = 32 (0x20)
// Word 1: length = 5
// Word 2: "hello" + padding
var data: [96]u8 = [_]u8{0} ** 96;
var data: [96]u8 = @as([96]u8, @splat(0));
data[31] = 0x20; // offset = 32
data[63] = 0x05; // length = 5
data[64] = 'h';
Expand All @@ -371,7 +371,7 @@ test "decode dynamic bytes" {
test "decode string" {
const allocator = testing.allocator;

var data: [96]u8 = [_]u8{0} ** 96;
var data: [96]u8 = @as([96]u8, @splat(0));
data[31] = 0x20; // offset = 32
data[63] = 0x0b; // length = 11
@memcpy(data[64..75], "hello world");
Expand All @@ -387,7 +387,7 @@ test "decode string" {
test "decode empty bytes" {
const allocator = testing.allocator;

var data: [64]u8 = [_]u8{0} ** 64;
var data: [64]u8 = @as([64]u8, @splat(0));
data[31] = 0x20; // offset = 32
// length = 0 (all zeros)

Expand All @@ -407,7 +407,7 @@ test "decode mixed static and dynamic" {
// Word 2: 7
// Word 3: string length = 2
// Word 4: "hi" padded
var data: [160]u8 = [_]u8{0} ** 160;
var data: [160]u8 = @as([160]u8, @splat(0));
data[31] = 42; // uint256(42)
data[63] = 0x60; // offset = 96
data[95] = 7; // uint256(7)
Expand All @@ -428,15 +428,15 @@ test "decode mixed static and dynamic" {
test "decode too short data returns error" {
const allocator = testing.allocator;

const data = [_]u8{0} ** 16; // Only 16 bytes, need at least 32
const data = @as([16]u8, @splat(0)); // Only 16 bytes, need at least 32
const types = [_]AbiType{.uint256};
const result = decodeValues(&data, &types, allocator);
try testing.expectError(error.DataTooShort, result);
}

test "decode empty types returns empty slice" {
const allocator = testing.allocator;
const data = [_]u8{0} ** 32;
const data = @as([32]u8, @splat(0));
const types = [_]AbiType{};
const values = try decodeValues(&data, &types, allocator);
defer freeValues(values, allocator);
Expand All @@ -446,7 +446,7 @@ test "decode empty types returns empty slice" {
test "decode invalid bool returns error" {
const allocator = testing.allocator;

var data: [32]u8 = [_]u8{0} ** 32;
var data: [32]u8 = @as([32]u8, @splat(0));
data[31] = 2; // Invalid bool value

const types = [_]AbiType{.bool};
Expand All @@ -458,7 +458,7 @@ test "encode then decode roundtrip - static types" {
const allocator = testing.allocator;
const encode_mod = @import("abi_encode.zig");

var addr: [20]u8 = [_]u8{0} ** 20;
var addr: [20]u8 = @as([20]u8, @splat(0));
addr[0] = 0xdE;
addr[1] = 0xAD;
addr[19] = 0xEF;
Expand Down Expand Up @@ -522,7 +522,7 @@ test "encode then decode roundtrip - mixed static and dynamic" {
const allocator = testing.allocator;
const encode_mod = @import("abi_encode.zig");

var addr: [20]u8 = [_]u8{0} ** 20;
var addr: [20]u8 = @as([20]u8, @splat(0));
addr[0] = 0xAB;

const original = [_]AbiValue{
Expand Down Expand Up @@ -572,7 +572,7 @@ test "decodeFunctionReturn works same as decodeValues" {
const allocator = testing.allocator;

// Encode a simple return: bool(true)
var data: [32]u8 = [_]u8{0} ** 32;
var data: [32]u8 = @as([32]u8, @splat(0));
data[31] = 1;

const types = [_]AbiType{.bool};
Expand All @@ -585,7 +585,7 @@ test "decodeFunctionReturn works same as decodeValues" {
test "decode uint8 and uint128" {
const allocator = testing.allocator;

var data: [64]u8 = [_]u8{0} ** 64;
var data: [64]u8 = @as([64]u8, @splat(0));
data[31] = 0xFF; // uint8 max = 255
data[47] = 0x01; // uint128 = 1 << 120
// rest zeros
Expand Down Expand Up @@ -690,7 +690,7 @@ test "decode large dynamic bytes 100 bytes" {
// Word 1: length = 100 (0x64)
// Words 2-5: 100 bytes of 0xAA + 28 bytes zero padding = 128 bytes
// Total: 32 + 32 + 128 = 192 bytes
var data: [192]u8 = [_]u8{0} ** 192;
var data: [192]u8 = @as([192]u8, @splat(0));
data[31] = 0x20; // offset = 32
data[63] = 0x64; // length = 100
for (64..164) |i| {
Expand All @@ -714,7 +714,7 @@ test "decode large string 128 bytes" {
// Word 1: length = 128 (0x80)
// Words 2-5: 128 bytes of 'B' (0x42), exactly 4 words, no padding needed
// Total: 32 + 32 + 128 = 192 bytes
var data: [192]u8 = [_]u8{0} ** 192;
var data: [192]u8 = @as([192]u8, @splat(0));
data[31] = 0x20; // offset = 32
data[62] = 0x00;
data[63] = 0x80; // length = 128
Expand All @@ -736,7 +736,7 @@ test "decode offset out of bounds" {
const allocator = testing.allocator;

// 64-byte buffer where word 0 has offset pointing to position 200
var data: [64]u8 = [_]u8{0} ** 64;
var data: [64]u8 = @as([64]u8, @splat(0));
data[31] = 200; // offset = 200 (way past end of 64-byte buffer)

const types = [_]AbiType{.bytes};
Expand All @@ -748,7 +748,7 @@ test "decode length out of bounds" {
const allocator = testing.allocator;

// 96-byte buffer: word 0 = offset 0x20, word 1 = length 9999
var data: [96]u8 = [_]u8{0} ** 96;
var data: [96]u8 = @as([96]u8, @splat(0));
data[31] = 0x20; // offset = 32
data[62] = 0x27; // 9999 = 0x270F
data[63] = 0x0F;
Expand All @@ -764,7 +764,7 @@ test "decode bytes exact 32-byte alignment" {
// 64 bytes of data = exactly 2 words, no padding needed
// Word 0: offset = 0x20, Word 1: length = 64, Words 2-3: 64 bytes of 0xBB
// Total: 32 + 32 + 64 = 128 bytes
var data: [128]u8 = [_]u8{0} ** 128;
var data: [128]u8 = @as([128]u8, @splat(0));
data[31] = 0x20; // offset = 32
data[63] = 0x40; // length = 64
for (64..128) |i| {
Expand Down
24 changes: 12 additions & 12 deletions src/abi_encode.zig
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ pub const AbiValue = union(enum) {
tuple: []const AbiValue,

pub const FixedBytes = struct {
data: [32]u8 = [_]u8{0} ** 32,
data: [32]u8 = @as([32]u8, @splat(0)),
len: u8,
};

Expand Down Expand Up @@ -179,17 +179,17 @@ fn encodeStaticValueNoAlloc(buf: *std.ArrayList(u8), val: AbiValue) void {
writeUint256NoAlloc(buf, unsigned);
},
.address => |v| {
var word: [32]u8 = [_]u8{0} ** 32;
var word: [32]u8 = @as([32]u8, @splat(0));
@memcpy(word[12..32], &v);
buf.appendSliceAssumeCapacity(&word);
},
.boolean => |v| {
var word: [32]u8 = [_]u8{0} ** 32;
var word: [32]u8 = @as([32]u8, @splat(0));
if (v) word[31] = 1;
buf.appendSliceAssumeCapacity(&word);
},
.fixed_bytes => |v| {
var word: [32]u8 = [_]u8{0} ** 32;
var word: [32]u8 = @as([32]u8, @splat(0));
const size: usize = @intCast(v.len);
@memcpy(word[0..size], v.data[0..size]);
buf.appendSliceAssumeCapacity(&word);
Expand Down Expand Up @@ -419,7 +419,7 @@ test "encode single uint256" {

test "encode single address" {
const allocator = testing.allocator;
var addr: [20]u8 = [_]u8{0} ** 20;
var addr: [20]u8 = @as([20]u8, @splat(0));
addr[0] = 0xde;
addr[1] = 0xad;
addr[18] = 0xbe;
Expand Down Expand Up @@ -569,7 +569,7 @@ test "encode dynamic array" {

test "encode multiple static values" {
const allocator = testing.allocator;
var addr: [20]u8 = [_]u8{0} ** 20;
var addr: [20]u8 = @as([20]u8, @splat(0));
addr[19] = 0x01;

const values = [_]AbiValue{
Expand All @@ -594,7 +594,7 @@ test "encode multiple static values" {

test "encode mixed static and dynamic" {
const allocator = testing.allocator;
var addr: [20]u8 = [_]u8{0} ** 20;
var addr: [20]u8 = @as([20]u8, @splat(0));
addr[19] = 0x01;

const values = [_]AbiValue{
Expand Down Expand Up @@ -635,7 +635,7 @@ test "encodeFunctionCall - transfer(address,uint256)" {
const selector = [_]u8{ 0xa9, 0x05, 0x9c, 0xbb };

// transfer(0x000...0001, 100)
var addr: [20]u8 = [_]u8{0} ** 20;
var addr: [20]u8 = @as([20]u8, @splat(0));
addr[19] = 0x01;

const values = [_]AbiValue{
Expand Down Expand Up @@ -667,7 +667,7 @@ test "encodeFunctionCall - full transfer encoding" {
const sel = keccak_mod.selector("transfer(address,uint256)");
try testing.expectEqualSlices(u8, &.{ 0xa9, 0x05, 0x9c, 0xbb }, &sel);

var addr: [20]u8 = [_]u8{0} ** 20;
var addr: [20]u8 = @as([20]u8, @splat(0));
addr[0] = 0xdE;
addr[1] = 0xAD;

Expand Down Expand Up @@ -766,7 +766,7 @@ test "encode int256 min value" {

test "encode bytes exactly 32 bytes - no padding needed" {
const allocator = testing.allocator;
const data = [_]u8{0xab} ** 32;
const data = @as([32]u8, @splat(0xab));
const values = [_]AbiValue{.{ .bytes = &data }};
const encoded = try encodeValues(allocator, &values);
defer allocator.free(encoded);
Expand Down Expand Up @@ -849,7 +849,7 @@ test "encodeFunctionCall - balanceOf(address)" {
const sel = keccak_mod.selector("balanceOf(address)");
try testing.expectEqualSlices(u8, &.{ 0x70, 0xa0, 0x82, 0x31 }, &sel);

var addr: [20]u8 = [_]u8{0} ** 20;
var addr: [20]u8 = @as([20]u8, @splat(0));
addr[0] = 0xd8;
addr[1] = 0xdA;
addr[19] = 0x45;
Expand Down Expand Up @@ -1047,7 +1047,7 @@ test "encode ERC20 approve exact bytes" {

test "encode large string 100 bytes" {
const allocator = testing.allocator;
const data = [_]u8{'A'} ** 100;
const data = @as([100]u8, @splat('A'));
const values = [_]AbiValue{.{ .string = &data }};
const encoded = try encodeValues(allocator, &values);
defer allocator.free(encoded);
Expand Down
Loading
Loading