Repository: evmts/tevm-monorepo
Pull request #1654: feat: create benchmarking boilerplate
Author: login: roninjin10
Created: 2025-05-11T04:10:47Z | Merged: 2025-05-11T05:12:20Z

## Description

This PR improves the WASM build process and adds benchmarking tools for cryptographic operations. It:

1. Updates the `build:wasm` script to properly copy the WASM file to the dist directory
2. Adds benchmarking tools to compare performance of keccak256, hexToBytes, and bytesToHex implementations
3. Implements standard library versions of cryptographic functions in Zig
4. Creates a build script for the standard library WASM file
5. Adds `.claude/settings.local.json` to gitignore

## Testing

- Added comprehensive benchmarks to compare Viem and WASM implementations
- Verified hash results match between implementations
- Tested with various input sizes (32 bytes, 128 bytes, 1024 bytes)
- Included batch operation tests to simulate real-world usage

## Additional Information

- [ ] I read the [contributing docs](../docs/contributing.md) (if this is your first contribution)

Your ENS/address:

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->

## Summary by CodeRabbit

- **New Features**
  - Introduced high-performance cryptographic and conversion utilities using WebAssembly, including keccak256 hashing and hex/byte conversions.
  - Added JavaScript modules to load and interact with WASM modules for cryptographic operations.
  - Provided new benchmarking suites to compare performance and correctness of WASM and JavaScript implementations for hashing and conversions.
  - Enabled batch processing and large data support for cryptographic functions.

- **Chores**
  - Updated workspace and package configurations to support new scripts, dependencies, and WASM build processes.
  - Improved .gitignore to exclude specific local configuration files.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->


Diff:
diff --git a/.gitignore b/.gitignore
index 44f1814cc7..213b6ad416 100644
--- a/.gitignore
+++ b/.gitignore
@@ -85,3 +85,5 @@ zig-out/
 zig-cache/
 
 TODO.md
+
+**/.claude/settings.local.json
diff --git a/package.json b/package.json
index c6a5f1f881..a7e7799c0d 100644
--- a/package.json
+++ b/package.json
@@ -23,7 +23,7 @@
     "build:rust:lib": "nx run-many --target=build --projects=my_rust_node_lib",
     "build:types": "nx run-many --targets=build:types,typecheck",
     "build:zig": "cd src && zig build",
-    "build:wasm": "cd src && zig build wasm && echo \"WASM build completed\" && echo \"WASM size: $(ls -lh ../dist/zigevm.wasm | awk '{print $5}')\" && echo \"WASM path: $(realpath ../dist/zigevm.wasm)\"",
+    "build:wasm": "cd src && zig build wasm && mkdir -p ../dist && find ../.zig-cache -name \"*.wasm\" -exec cp {} ../dist/zigevm.wasm \\; && echo \"WASM build completed\" && echo \"WASM size: $(ls -lh ../dist/zigevm.wasm | awk '{print $5}')\" && echo \"WASM path: $(realpath ../dist/zigevm.wasm)\"",
     "test:zig": "cd src && zig build test",
     "clean": "nx reset && nx run-many --target=clean && rm -rf node_modules && rm -rf .nx",
     "e2e": "nx e2e e2e",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 291cc99fdc..1ef48928d2 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -1594,7 +1594,7 @@ importers:
     devDependencies:
       '@evmts/core':
         specifier: 1.0.0-next.12
-        version: 1.0.0-next.12(viem@2.27.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.24.2))
+        version: 1.0.0-next.12(viem@2.29.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.24.2))
       '@evmts/ts-plugin':
         specifier: 1.0.0-next.18
         version: 1.0.0-next.18(bufferutil@4.0.9)(fast-check@3.23.2)(typescript@5.8.3)(utf-8-validate@5.0.10)
@@ -2257,6 +2257,15 @@ importers:
         specifier: ^2.2.3
         version: 2.2.3
 
+  src:
+    devDependencies:
+      viem:
+        specifier: ^2.29.2
+        version: 2.29.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.24.3)
+      vitest:
+        specifier: ^3.1.3
+        version: 3.1.3(@types/debug@4.1.12)(@types/node@22.15.3)(@vitest/ui@3.1.2)(jiti@2.4.2)(lightningcss@1.29.3)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.1)
+
   test/bench:
     dependencies:
       '@tevm/base-bundler':
@@ -7509,6 +7518,9 @@ packages:
   '@vitest/expect@3.1.2':
     resolution: {integrity: sha512-O8hJgr+zREopCAqWl3uCVaOdqJwZ9qaDwUP7vy3Xigad0phZe9APxKhPcDNqYYi0rX5oMvwJMSCAXY2afqeTSA==}
 
+  '@vitest/expect@3.1.3':
+    resolution: {integrity: sha512-7FTQQuuLKmN1Ig/h+h/GO+44Q1IlglPlR2es4ab7Yvfx+Uk5xsv+Ykk+MEt/M2Yn/xGmzaLKxGw2lgy2bwuYqg==}
+
   '@vitest/mocker@3.0.8':
     resolution: {integrity: sha512-n3LjS7fcW1BCoF+zWZxG7/5XvuYH+lsFg+BDwwAz0arIwHQJFUEsKBQ0BLU49fCxuM/2HSeBPHQD8WjgrxMfow==}
     peerDependencies:
@@ -7542,6 +7554,17 @@ packages:
       vite:
         optional: true
 
+  '@vitest/mocker@3.1.3':
+    resolution: {integrity: sha512-PJbLjonJK82uCWHjzgBJZuR7zmAOrSvKk1QBxrennDIgtH4uK0TB1PvYmc0XBCigxxtiAVPfWtAdy4lpz8SQGQ==}
+    peerDependencies:
+      msw: ^2.4.9
+      vite: ^5.0.0 || ^6.0.0
+    peerDependenciesMeta:
+      msw:
+        optional: true
+      vite:
+        optional: true
+
   '@vitest/pretty-format@3.0.8':
     resolution: {integrity: sha512-BNqwbEyitFhzYMYHUVbIvepOyeQOSFA/NeJMIP9enMntkkxLgOcgABH6fjyXG85ipTgvero6noreavGIqfJcIg==}
 
@@ -7551,6 +7574,9 @@ packages:
   '@vitest/pretty-format@3.1.2':
     resolution: {integrity: sha512-R0xAiHuWeDjTSB3kQ3OQpT8Rx3yhdOAIm/JM4axXxnG7Q/fS8XUwggv/A4xzbQA+drYRjzkMnpYnOGAc4oeq8w==}
 
+  '@vitest/pretty-format@3.1.3':
+    resolution: {integrity: sha512-i6FDiBeJUGLDKADw2Gb01UtUNb12yyXAqC/mmRWuYl+m/U9GS7s8us5ONmGkGpUUo7/iAYzI2ePVfOZTYvUifA==}
+
   '@vitest/runner@3.0.8':
     resolution: {integrity: sha512-c7UUw6gEcOzI8fih+uaAXS5DwjlBaCJUo7KJ4VvJcjL95+DSR1kova2hFuRt3w41KZEFcOEiq098KkyrjXeM5w==}
 
@@ -7560,6 +7586,9 @@ packages:
   '@vitest/runner@3.1.2':
     resolution: {integrity: sha512-bhLib9l4xb4sUMPXnThbnhX2Yi8OutBMA8Yahxa7yavQsFDtwY/jrUZwpKp2XH9DhRFJIeytlyGpXCqZ65nR+g==}
 
+  '@vitest/runner@3.1.3':
+    resolution: {integrity: sha512-Tae+ogtlNfFei5DggOsSUvkIaSuVywujMj6HzR97AHK6XK8i3BuVyIifWAm/sE3a15lF5RH9yQIrbXYuo0IFyA==}
+
   '@vitest/snapshot@3.0.8':
     resolution: {integrity: sha512-x8IlMGSEMugakInj44nUrLSILh/zy1f2/BgH0UeHpNyOocG18M9CWVIFBaXPt8TrqVZWmcPjwfG/ht5tnpba8A==}
 
@@ -7569,6 +7598,9 @@ packages:
   '@vitest/snapshot@3.1.2':
     resolution: {integrity: sha512-Q1qkpazSF/p4ApZg1vfZSQ5Yw6OCQxVMVrLjslbLFA1hMDrT2uxtqMaw8Tc/jy5DLka1sNs1Y7rBcftMiaSH/Q==}
 
+  '@vitest/snapshot@3.1.3':
+    resolution: {integrity: sha512-XVa5OPNTYUsyqG9skuUkFzAeFnEzDp8hQu7kZ0N25B1+6KjGm4hWLtURyBbsIAOekfWQ7Wuz/N/XXzgYO3deWQ==}
+
   '@vitest/spy@3.0.8':
     resolution: {integrity: sha512-MR+PzJa+22vFKYb934CejhR4BeRpMSoxkvNoDit68GQxRLSf11aT6CTj3XaqUU9rxgWJFnqicN/wxw6yBRkI1Q==}
 
@@ -7578,6 +7610,9 @@ packages:
   '@vitest/spy@3.1.2':
     resolution: {integrity: sha512-OEc5fSXMws6sHVe4kOFyDSj/+4MSwst0ib4un0DlcYgQvRuYQ0+M2HyqGaauUMnjq87tmUaMNDxKQx7wNfVqPA==}
 
+  '@vitest/spy@3.1.3':
+    resolution: {integrity: sha512-x6w+ctOEmEXdWaa6TO4ilb7l9DxPR5bwEb6hILKuxfU1NqWT2mpJD9NJN7t3OTfxmVlOMrvtoFJGdgyzZ605lQ==}
+
   '@vitest/ui@3.0.8':
     resolution: {integrity: sha512-MfTjaLU+Gw/lYorgwFZ06Cym+Mj9hPfZh/Q91d4JxyAHiicAakPTvS7zYCSHF+5cErwu2PVBe1alSjuh6L/UiA==}
     peerDependencies:
@@ -7597,6 +7632,9 @@ packages:
   '@vitest/utils@3.1.2':
     resolution: {integrity: sha512-5GGd0ytZ7BH3H6JTj9Kw7Prn1Nbg0wZVrIvou+UWxm54d+WoXXgAgjFJ8wn3LdagWLFSEfpPeyYrByZaGEZHLg==}
 
+  '@vitest/utils@3.1.3':
+    resolution: {integrity: sha512-2Ltrpht4OmHO9+c/nmHtF09HWiyWdworqnHIwjfvDyWjuwKbdkcS9AnhsDn+8E2RM4x++foD1/tNuLPVvWG1Rg==}
+
   '@volar/language-core@2.4.12':
     resolution: {integrity: sha512-RLrFdXEaQBWfSnYGVxvR2WrO6Bub0unkdHYIdC31HzIEqATIuuhRRzYu76iGPZ6OtA4Au1SnW0ZwIqPP217YhA==}
 
@@ -8391,6 +8429,7 @@ packages:
 
   bun@1.2.5:
     resolution: {integrity: sha512-fbQLt+DPiGUrPKdmsHRRT7cQAlfjdxPVFvLZrsUPmKiTdv+pU50ypdx9yRJluknSbyaZchFVV7Lx2KXikXKX2Q==}
+    cpu: [arm64, x64, aarch64]
     os: [darwin, linux, win32]
     hasBin: true
 
@@ -15469,6 +15508,14 @@ packages:
       typescript:
         optional: true
 
+  viem@2.29.2:
+    resolution: {integrity: sha512-cukRxab90jvQ+TDD84sU3qB3UmejYqgCw4cX8SfWzvh7JPfZXI3kAMUaT5OSR2As1Mgvx1EJawccwPjGqkSSwA==}
+    peerDependencies:
+      typescript: '>=5.0.4'
+    peerDependenciesMeta:
+      typescript:
+        optional: true
+
   vite-node@1.6.1:
     resolution: {integrity: sha512-YAXkfvGtuTzwWbDSACdJSg4A4DZiAqckWe90Zapc/sEX3XvHcw1NdurM/6od8J207tSDqNbSsgdCacBgvJKFuA==}
     engines: {node: ^18.0.0 || >=20.0.0}
@@ -15489,6 +15536,11 @@ packages:
     engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
     hasBin: true
 
+  vite-node@3.1.3:
+    resolution: {integrity: sha512-uHV4plJ2IxCl4u1up1FQRrqclylKAogbtBfOTwcuJ28xFi+89PZ57BRh+naIRvH70HPwxy5QHYzg1OrEaC7AbA==}
+    engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
+    hasBin: true
+
   vite-plugin-node-polyfills@0.23.0:
     resolution: {integrity: sha512-4n+Ys+2bKHQohPBKigFlndwWQ5fFKwaGY6muNDMTb0fSQLyBzS+jjUNRZG9sKF0S/Go4ApG6LFnUGopjkILg3w==}
     peerDependencies:
@@ -15707,6 +15759,34 @@ packages:
       jsdom:
         optional: true
 
+  vitest@3.1.3:
+    resolution: {integrity: sha512-188iM4hAHQ0km23TN/adso1q5hhwKqUpv+Sd6p5sOuh6FhQnRNW3IsiIpvxqahtBabsJ2SLZgmGSpcYK4wQYJw==}
+    engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
+    hasBin: true
+    peerDependencies:
+      '@edge-runtime/vm': '*'
+      '@types/debug': ^4.1.12
+      '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0
+      '@vitest/browser': 3.1.3
+      '@vitest/ui': 3.1.3
+      happy-dom: '*'
+      jsdom: '*'
+    peerDependenciesMeta:
+      '@edge-runtime/vm':
+        optional: true
+      '@types/debug':
+        optional: true
+      '@types/node':
+        optional: true
+      '@vitest/browser':
+        optional: true
+      '@vitest/ui':
+        optional: true
+      happy-dom:
+        optional: true
+      jsdom:
+        optional: true
+
   vm-browserify@1.1.2:
     resolution: {integrity: sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==}
 
@@ -17788,9 +17868,9 @@ snapshots:
       - utf-8-validate
       - zod
 
-  '@evmts/core@1.0.0-next.12(viem@2.27.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.24.2))':
+  '@evmts/core@1.0.0-next.12(viem@2.29.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.24.2))':
     dependencies:
-      viem: 2.27.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.24.2)
+      viem: 2.29.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.24.2)
 
   '@evmts/effect@1.0.0-next.9(bufferutil@4.0.9)(esbuild@0.19.5)(fast-check@3.23.2)(solc@0.8.22)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.24.2)':
     dependencies:
@@ -20932,7 +21012,7 @@ snapshots:
   '@safe-global/safe-apps-sdk@9.1.0(bufferutil@4.0.9)(typescript@5.8.2)(utf-8-validate@5.0.10)(zod@3.24.2)':
     dependencies:
       '@safe-global/safe-gateway-typescript-sdk': 3.22.9
-      viem: 2.27.3(bufferutil@4.0.9)(typescript@5.8.2)(utf-8-validate@5.0.10)(zod@3.24.2)
+      viem: 2.23.11(bufferutil@4.0.9)(typescript@5.8.2)(utf-8-validate@5.0.10)(zod@3.24.2)
     transitivePeerDependencies:
       - bufferutil
       - typescript
@@ -20942,7 +21022,7 @@ snapshots:
   '@safe-global/safe-apps-sdk@9.1.0(bufferutil@4.0.9)(typescript@5.8.2)(utf-8-validate@5.0.10)(zod@3.24.3)':
     dependencies:
       '@safe-global/safe-gateway-typescript-sdk': 3.22.9
-      viem: 2.27.3(bufferutil@4.0.9)(typescript@5.8.2)(utf-8-validate@5.0.10)(zod@3.24.3)
+      viem: 2.23.11(bufferutil@4.0.9)(typescript@5.8.2)(utf-8-validate@5.0.10)(zod@3.24.3)
     transitivePeerDependencies:
       - bufferutil
       - typescript
@@ -22155,13 +22235,12 @@ snapshots:
       chai: 5.2.0
       tinyrainbow: 2.0.0
 
-  '@vitest/mocker@3.0.8(vite@6.3.4(@types/node@22.13.10)(jiti@2.4.2)(lightningcss@1.29.3)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.1))':
+  '@vitest/expect@3.1.3':
     dependencies:
-      '@vitest/spy': 3.0.8
-      estree-walker: 3.0.3
-      magic-string: 0.30.17
-    optionalDependencies:
-      vite: 6.3.4(@types/node@22.13.10)(jiti@2.4.2)(lightningcss@1.29.3)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.1)
+      '@vitest/spy': 3.1.3
+      '@vitest/utils': 3.1.3
+      chai: 5.2.0
+      tinyrainbow: 2.0.0
 
   '@vitest/mocker@3.0.8(vite@6.3.4(@types/node@22.15.3)(jiti@2.4.2)(lightningcss@1.29.3)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.1))':
     dependencies:
@@ -22187,6 +22266,14 @@ snapshots:
     optionalDependencies:
       vite: 6.3.4(@types/node@22.15.3)(jiti@2.4.2)(lightningcss@1.29.3)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.1)
 
+  '@vitest/mocker@3.1.3(vite@6.3.4(@types/node@22.15.3)(jiti@2.4.2)(lightningcss@1.29.3)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.1))':
+    dependencies:
+      '@vitest/spy': 3.1.3
+      estree-walker: 3.0.3
+      magic-string: 0.30.17
+    optionalDependencies:
+      vite: 6.3.4(@types/node@22.15.3)(jiti@2.4.2)(lightningcss@1.29.3)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.1)
+
   '@vitest/pretty-format@3.0.8':
     dependencies:
       tinyrainbow: 2.0.0
@@ -22199,6 +22286,10 @@ snapshots:
     dependencies:
       tinyrainbow: 2.0.0
 
+  '@vitest/pretty-format@3.1.3':
+    dependencies:
+      tinyrainbow: 2.0.0
+
   '@vitest/runner@3.0.8':
     dependencies:
       '@vitest/utils': 3.0.8
@@ -22214,6 +22305,11 @@ snapshots:
       '@vitest/utils': 3.1.2
       pathe: 2.0.3
 
+  '@vitest/runner@3.1.3':
+    dependencies:
+      '@vitest/utils': 3.1.3
+      pathe: 2.0.3
+
   '@vitest/snapshot@3.0.8':
     dependencies:
       '@vitest/pretty-format': 3.0.8
@@ -22232,6 +22328,12 @@ snapshots:
       magic-string: 0.30.17
       pathe: 2.0.3
 
+  '@vitest/snapshot@3.1.3':
+    dependencies:
+      '@vitest/pretty-format': 3.1.3
+      magic-string: 0.30.17
+      pathe: 2.0.3
+
   '@vitest/spy@3.0.8':
     dependencies:
       tinyspy: 3.0.2
@@ -22244,6 +22346,10 @@ snapshots:
     dependencies:
       tinyspy: 3.0.2
 
+  '@vitest/spy@3.1.3':
+    dependencies:
+      tinyspy: 3.0.2
+
   '@vitest/ui@3.0.8(vitest@3.0.8)':
     dependencies:
       '@vitest/utils': 3.0.8
@@ -22253,7 +22359,7 @@ snapshots:
       sirv: 3.0.1
       tinyglobby: 0.2.12
       tinyrainbow: 2.0.0
-      vitest: 3.0.8(@types/debug@4.1.12)(@types/node@22.13.10)(@vitest/ui@3.0.8)(jiti@2.4.2)(lightningcss@1.29.3)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.1)
+      vitest: 3.0.8(@types/debug@4.1.12)(@types/node@22.15.3)(@vitest/ui@3.0.8)(jiti@2.4.2)(lightningcss@1.29.3)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.1)
 
   '@vitest/ui@3.1.2(vitest@3.1.2)':
     dependencies:
@@ -22284,6 +22390,12 @@ snapshots:
       loupe: 3.1.3
       tinyrainbow: 2.0.0
 
+  '@vitest/utils@3.1.3':
+    dependencies:
+      '@vitest/pretty-format': 3.1.3
+      loupe: 3.1.3
+      tinyrainbow: 2.0.0
+
   '@volar/language-core@2.4.12':
     dependencies:
       '@volar/source-map': 2.4.12
@@ -25395,7 +25507,7 @@ snapshots:
     transitivePeerDependencies:
       - supports-color
 
-  eslint-import-resolver-webpack@0.13.10(eslint-plugin-import@2.31.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.8.2))(eslint@8.57.1))(webpack@5.98.0(@swc/core@1.11.9(@swc/helpers@0.5.15))(esbuild@0.25.3)):
+  eslint-import-resolver-webpack@0.13.10(eslint-plugin-import@2.31.0)(webpack@5.98.0(@swc/core@1.11.9(@swc/helpers@0.5.15))(esbuild@0.25.3)):
     dependencies:
       debug: 3.2.7
       enhanced-resolve: 0.9.1
@@ -25419,7 +25531,7 @@ snapshots:
       '@typescript-eslint/parser': 7.18.0(eslint@8.57.1)(typescript@5.8.2)
       eslint: 8.57.1
       eslint-import-resolver-node: 0.3.9
-      eslint-import-resolver-webpack: 0.13.10(eslint-plugin-import@2.31.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.8.2))(eslint@8.57.1))(webpack@5.98.0(@swc/core@1.11.9(@swc/helpers@0.5.15))(esbuild@0.25.3))
+      eslint-import-resolver-webpack: 0.13.10(eslint-plugin-import@2.31.0)(webpack@5.98.0(@swc/core@1.11.9(@swc/helpers@0.5.15))(esbuild@0.25.3))
     transitivePeerDependencies:
       - supports-color
 
@@ -29295,7 +29407,7 @@ snapshots:
     dependencies:
       '@adraffy/ens-normalize': 1.11.0
       '@noble/curves': 1.8.2
-      '@noble/hashes': 1.7.1
+      '@noble/hashes': 1.8.0
       '@scure/bip32': 1.6.2
       '@scure/bip39': 1.5.4
       abitype: 1.0.8(typescript@5.8.2)(zod@3.24.2)
@@ -29309,7 +29421,7 @@ snapshots:
     dependencies:
       '@adraffy/ens-normalize': 1.11.0
       '@noble/curves': 1.8.2
-      '@noble/hashes': 1.7.1
+      '@noble/hashes': 1.8.0
       '@scure/bip32': 1.6.2
       '@scure/bip39': 1.5.4
       abitype: 1.0.8(typescript@5.8.2)(zod@3.24.3)
@@ -32797,41 +32909,24 @@ snapshots:
       - utf-8-validate
       - zod
 
-  viem@2.27.3(bufferutil@4.0.9)(typescript@5.8.2)(utf-8-validate@5.0.10)(zod@3.24.2):
-    dependencies:
-      '@noble/curves': 1.8.2
-      '@noble/hashes': 1.7.2
-      '@scure/bip32': 1.6.2
-      '@scure/bip39': 1.5.4
-      abitype: 1.0.8(typescript@5.8.2)(zod@3.24.2)
-      isows: 1.0.6(ws@8.18.1(bufferutil@4.0.9)(utf-8-validate@5.0.10))
-      ox: 0.6.9(typescript@5.8.2)(zod@3.24.2)
-      ws: 8.18.1(bufferutil@4.0.9)(utf-8-validate@5.0.10)
-    optionalDependencies:
-      typescript: 5.8.2
-    transitivePeerDependencies:
-      - bufferutil
-      - utf-8-validate
-      - zod
-
-  viem@2.27.3(bufferutil@4.0.9)(typescript@5.8.2)(utf-8-validate@5.0.10)(zod@3.24.3):
+  viem@2.27.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.24.3):
     dependencies:
       '@noble/curves': 1.8.2
       '@noble/hashes': 1.7.2
       '@scure/bip32': 1.6.2
       '@scure/bip39': 1.5.4
-      abitype: 1.0.8(typescript@5.8.2)(zod@3.24.3)
+      abitype: 1.0.8(typescript@5.8.3)(zod@3.24.3)
       isows: 1.0.6(ws@8.18.1(bufferutil@4.0.9)(utf-8-validate@5.0.10))
-      ox: 0.6.9(typescript@5.8.2)(zod@3.24.3)
+      ox: 0.6.9(typescript@5.8.3)(zod@3.24.3)
       ws: 8.18.1(bufferutil@4.0.9)(utf-8-validate@5.0.10)
     optionalDependencies:
-      typescript: 5.8.2
+      typescript: 5.8.3
     transitivePeerDependencies:
       - bufferutil
       - utf-8-validate
       - zod
 
-  viem@2.27.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.24.2):
+  viem@2.29.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.24.2):
     dependencies:
       '@noble/curves': 1.8.2
       '@noble/hashes': 1.7.2
@@ -32848,7 +32943,7 @@ snapshots:
       - utf-8-validate
       - zod
 
-  viem@2.27.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.24.3):
+  viem@2.29.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.24.3):
     dependencies:
       '@noble/curves': 1.8.2
       '@noble/hashes': 1.7.2
@@ -32967,6 +33062,27 @@ snapshots:
       - tsx
       - yaml
 
+  vite-node@3.1.3(@types/node@22.15.3)(jiti@2.4.2)(lightningcss@1.29.3)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.1):
+    dependencies:
+      cac: 6.7.14
+      debug: 4.4.0(supports-color@8.1.1)
+      es-module-lexer: 1.7.0
+      pathe: 2.0.3
+      vite: 6.3.4(@types/node@22.15.3)(jiti@2.4.2)(lightningcss@1.29.3)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.1)
+    transitivePeerDependencies:
+      - '@types/node'
+      - jiti
+      - less
+      - lightningcss
+      - sass
+      - sass-embedded
+      - stylus
+      - sugarss
+      - supports-color
+      - terser
+      - tsx
+      - yaml
+
   vite-plugin-node-polyfills@0.23.0(rollup@4.40.1)(vite@6.2.1(@types/node@22.15.3)(jiti@2.4.2)(lightningcss@1.29.3)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.1)):
     dependencies:
       '@rollup/plugin-inject': 5.0.5(rollup@4.40.1)
@@ -33059,7 +33175,7 @@ snapshots:
   vitest@3.0.8(@types/debug@4.1.12)(@types/node@22.13.10)(@vitest/ui@3.0.8)(jiti@2.4.2)(lightningcss@1.29.3)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.1):
     dependencies:
       '@vitest/expect': 3.0.8
-      '@vitest/mocker': 3.0.8(vite@6.3.4(@types/node@22.13.10)(jiti@2.4.2)(lightningcss@1.29.3)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.1))
+      '@vitest/mocker': 3.0.8(vite@6.3.4(@types/node@22.15.3)(jiti@2.4.2)(lightningcss@1.29.3)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.1))
       '@vitest/pretty-format': 3.0.8
       '@vitest/runner': 3.0.8
       '@vitest/snapshot': 3.0.8
@@ -33217,6 +33333,47 @@ snapshots:
       - tsx
       - yaml
 
+  vitest@3.1.3(@types/debug@4.1.12)(@types/node@22.15.3)(@vitest/ui@3.1.2)(jiti@2.4.2)(lightningcss@1.29.3)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.1):
+    dependencies:
+      '@vitest/expect': 3.1.3
+      '@vitest/mocker': 3.1.3(vite@6.3.4(@types/node@22.15.3)(jiti@2.4.2)(lightningcss@1.29.3)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.1))
+      '@vitest/pretty-format': 3.1.3
+      '@vitest/runner': 3.1.3
+      '@vitest/snapshot': 3.1.3
+      '@vitest/spy': 3.1.3
+      '@vitest/utils': 3.1.3
+      chai: 5.2.0
+      debug: 4.4.0(supports-color@8.1.1)
+      expect-type: 1.2.1
+      magic-string: 0.30.17
+      pathe: 2.0.3
+      std-env: 3.9.0
+      tinybench: 2.9.0
+      tinyexec: 0.3.2
+      tinyglobby: 0.2.13
+      tinypool: 1.0.2
+      tinyrainbow: 2.0.0
+      vite: 6.3.4(@types/node@22.15.3)(jiti@2.4.2)(lightningcss@1.29.3)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.1)
+      vite-node: 3.1.3(@types/node@22.15.3)(jiti@2.4.2)(lightningcss@1.29.3)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.1)
+      why-is-node-running: 2.3.0
+    optionalDependencies:
+      '@types/debug': 4.1.12
+      '@types/node': 22.15.3
+      '@vitest/ui': 3.1.2(vitest@3.1.2)
+    transitivePeerDependencies:
+      - jiti
+      - less
+      - lightningcss
+      - msw
+      - sass
+      - sass-embedded
+      - stylus
+      - sugarss
+      - supports-color
+      - terser
+      - tsx
+      - yaml
+
   vm-browserify@1.1.2: {}
 
   vocs@1.0.0-alpha.62(@types/node@22.15.3)(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(acorn@8.14.1)(lightningcss@1.29.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(rollup@4.40.1)(terser@5.39.0)(ts-node@10.9.2(@swc/core@1.11.9(@swc/helpers@0.5.15))(@types/node@22.15.3)(typescript@5.8.2))(typescript@5.8.2):
@@ -33827,7 +33984,7 @@ snapshots:
       eslint-config-xo: 0.45.0(eslint@8.57.1)
       eslint-config-xo-typescript: 5.0.0(@typescript-eslint/eslint-plugin@7.18.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.8.2))(eslint@8.57.1)(typescript@5.8.2))(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.8.2))(eslint@8.57.1)(typescript@5.8.2)
       eslint-formatter-pretty: 6.0.1
-      eslint-import-resolver-webpack: 0.13.10(eslint-plugin-import@2.31.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.8.2))(eslint@8.57.1))(webpack@5.98.0(@swc/core@1.11.9(@swc/helpers@0.5.15))(esbuild@0.25.3))
+      eslint-import-resolver-webpack: 0.13.10(eslint-plugin-import@2.31.0)(webpack@5.98.0(@swc/core@1.11.9(@swc/helpers@0.5.15))(esbuild@0.25.3))
       eslint-plugin-ava: 14.0.0(eslint@8.57.1)
       eslint-plugin-eslint-comments: 3.2.0(eslint@8.57.1)
       eslint-plugin-import: 2.31.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.8.2))(eslint-import-resolver-webpack@0.13.10)(eslint@8.57.1)
diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml
index ab691a8ca2..e290c813bd 100644
--- a/pnpm-workspace.yaml
+++ b/pnpm-workspace.yaml
@@ -13,6 +13,7 @@ packages:
   - lsp/*
   - packages/*
   - scripts
+  - src
   - tevm
   - test/*
 onlyBuiltDependencies:
diff --git a/src/build-stdlib.sh b/src/build-stdlib.sh
new file mode 100755
index 0000000000..563a58257e
--- /dev/null
+++ b/src/build-stdlib.sh
@@ -0,0 +1,9 @@
+#!/bin/bash
+set -e
+
+# Build the standard library version of the WASM file
+zig build-exe -fno-entry -OReleaseSmall -target wasm32-freestanding ./stdlib3.zig -femit-bin=../dist/stdlib.wasm
+
+echo "WASM build completed"
+echo "WASM size: $(ls -lh ../dist/stdlib.wasm | awk '{print $5}')"
+echo "WASM path: $(realpath ../dist/stdlib.wasm)"
\ No newline at end of file
diff --git a/src/comparison.bench.js b/src/comparison.bench.js
new file mode 100644
index 0000000000..eacd3b53c0
--- /dev/null
+++ b/src/comparison.bench.js
@@ -0,0 +1,167 @@
+import { bench, describe } from "vitest";
+import {
+  keccak256 as viemKeccak256,
+  hexToBytes as viemHexToBytes,
+  bytesToHex as viemBytesToHex,
+} from "viem/utils";
+import { instantiateZigModule } from "./wasm-loader.js";
+import fs from "fs";
+import path from "path";
+import { fileURLToPath } from "url";
+
+describe("Comprehensive Implementation Comparison", async () => {
+  const __dirname = path.dirname(fileURLToPath(import.meta.url));
+  const wasmPath = path.resolve(__dirname, "../dist/zigevm.wasm");
+  const wasmBuffer = fs.readFileSync(wasmPath);
+
+  // Initialize WASM instance with all implementation methods
+  const wasmModule = await instantiateZigModule(wasmBuffer);
+
+  // Test data sizes
+  const smallHex = "0x" + "a".repeat(64); // 32 bytes (uint256, typical ETH value)
+  const mediumHex = "0x" + "b".repeat(256); // 128 bytes
+  const largeHex = "0x" + "c".repeat(2048); // 1024 bytes
+
+  // Log all available exports to debug
+  console.log("Available WASM exports:", Object.keys(wasmModule));
+
+  // Verify hash results
+  console.log("Verification with ETH-sized input (32 bytes):");
+  const viemResult = viemKeccak256(smallHex);
+  const wasmResult = wasmModule.keccak256(smallHex);
+  const wasmStdlibResult = wasmModule.keccak256Stdlib(smallHex);
+  // Skip old result until we fix the exports
+  // const wasmOldResult = wasmModule.keccak256Old(smallHex);
+
+  console.log("Viem result:        ", viemResult);
+  console.log("WASM result:        ", wasmResult);
+  console.log("WASM Stdlib result: ", wasmStdlibResult);
+  console.log(
+    "Equal:",
+    viemResult === wasmResult && viemResult === wasmStdlibResult,
+  );
+
+  console.log(
+    "\nImportant Note: keccak256 and keccak256Stdlib should now be identical since we changed the implementation.",
+  );
+
+  // Individual operations (typical Ethereum transaction)
+  console.log("\nBenchmarking ETH value (32 bytes):");
+
+  bench("Viem keccak256", () => {
+    viemKeccak256(smallHex);
+  });
+
+  bench("WASM keccak256 (Stdlib impl)", () => {
+    wasmModule.keccak256(smallHex);
+  });
+
+  bench("WASM keccak256Stdlib", () => {
+    wasmModule.keccak256Stdlib(smallHex);
+  });
+
+  // Old implementation not available in exports
+  // bench('WASM keccak256Old (Custom impl)', () => {
+  //   wasmModule.keccak256Old(smallHex);
+  // });
+
+  // Large data (1024 bytes)
+  console.log("\nBenchmarking large data (1024 bytes):");
+
+  bench("Viem keccak256 - Large", () => {
+    viemKeccak256(largeHex);
+  });
+
+  bench("WASM keccak256 (Stdlib impl) - Large", () => {
+    wasmModule.keccak256(largeHex);
+  });
+
+  bench("WASM keccak256Stdlib - Large", () => {
+    wasmModule.keccak256Stdlib(largeHex);
+  });
+
+  // Old implementation not available in exports
+  // bench('WASM keccak256Old (Custom impl) - Large', () => {
+  //   wasmModule.keccak256Old(largeHex);
+  // });
+
+  // Batch operations
+  console.log("\nBenchmarking batch operations (100 hashes):");
+
+  // Create array of 100 slightly different inputs
+  const batchInputs = Array(100)
+    .fill()
+    .map((_, i) => "0x" + i.toString(16).padStart(64, "a"));
+
+  bench("Viem keccak256 - Batch", () => {
+    for (const input of batchInputs) {
+      viemKeccak256(input);
+    }
+  });
+
+  bench("WASM keccak256 (Stdlib impl) - Batch", () => {
+    for (const input of batchInputs) {
+      wasmModule.keccak256(input);
+    }
+  });
+
+  bench("WASM keccak256Stdlib - Batch", () => {
+    for (const input of batchInputs) {
+      wasmModule.keccak256Stdlib(input);
+    }
+  });
+
+  // Old implementation not available in exports
+  // bench('WASM keccak256Old (Custom impl) - Batch', () => {
+  //   for (const input of batchInputs) {
+  //     wasmModule.keccak256Old(input);
+  //   }
+  // });
+
+  // Add bytesToHex and hexToBytes benchmarks
+  console.log("\nBenchmarking hex conversion functions:");
+
+  // Convert smallHex to bytes for bytesToHex benchmarks
+  const smallBytes = viemKeccak256(smallHex).slice(2);
+  const mediumBytes = viemKeccak256(mediumHex).slice(2);
+
+  // hexToBytes benchmarks
+  console.log("\nBenchmarking hexToBytes (32 bytes):");
+
+  bench("Viem hexToBytes", () => {
+    viemHexToBytes(smallHex);
+  });
+
+  bench("WASM hexToBytes (Stdlib impl)", () => {
+    wasmModule.hexToBytes(smallHex);
+  });
+
+  bench("WASM hexToBytesStdlib", () => {
+    wasmModule.hexToBytesStdlib(smallHex);
+  });
+
+  // Skipping Old implementation for now
+  // bench('WASM hexToBytesOld', () => {
+  //   wasmModule.hexToBytesOld(smallHex);
+  // });
+
+  // bytesToHex benchmarks
+  console.log("\nBenchmarking bytesToHex (32 bytes):");
+
+  bench("Viem bytesToHex", () => {
+    viemBytesToHex(smallBytes);
+  });
+
+  bench("WASM bytesToHex (Stdlib impl)", () => {
+    wasmModule.bytesToHex(smallBytes);
+  });
+
+  bench("WASM bytesToHexStdlib", () => {
+    wasmModule.bytesToHexStdlib(smallBytes);
+  });
+
+  // Skipping Old implementation for now
+  // bench('WASM bytesToHexOld', () => {
+  //   wasmModule.bytesToHexOld(smallBytes);
+  // });
+});
diff --git a/src/conversion.bench.js b/src/conversion.bench.js
new file mode 100644
index 0000000000..648647af46
--- /dev/null
+++ b/src/conversion.bench.js
@@ -0,0 +1,70 @@
+import { bench, describe } from 'vitest';
+import { bytesToHex, hexToBytes } from 'viem/utils';
+import { initWasm, bytesToHex as wasmBytesToHex, hexToBytes as wasmHexToBytes } from './wasm-loader.js';
+
+describe('Conversion Functions Benchmark', async () => {
+  // Initialize WASM module before running benchmarks
+  const wasmInstance = await initWasm();
+
+  // Create test data of various sizes
+  const sizes = [32, 128, 512, 1024, 16384, 65536]; // Bytes
+  
+  // Generate test data for each size
+  const testData = sizes.map(size => {
+    const bytes = new Uint8Array(size);
+    // Fill with repeating pattern
+    for (let i = 0; i < size; i++) {
+      bytes[i] = i % 256;
+    }
+    return bytes;
+  });
+  
+  // Generate hex strings for each size
+  const testHexes = testData.map(bytes => bytesToHex(bytes));
+  
+  // Verify conversions work correctly for largest size
+  const largeBytes = testData[testData.length - 1];
+  const largeHex = testHexes[testHexes.length - 1];
+  
+  const viemBytesToHexResult = bytesToHex(largeBytes);
+  const wasmBytesToHexResult = wasmBytesToHex(wasmInstance, largeBytes);
+  
+  const viemHexToBytesResult = hexToBytes(largeHex);
+  const wasmHexToBytesResult = wasmHexToBytes(wasmInstance, largeHex);
+  
+  console.log(`Verification for size ${largeBytes.length} bytes:`);
+  console.log('bytesToHex match:', viemBytesToHexResult === wasmBytesToHexResult);
+  console.log('hexToBytes match:', viemHexToBytesResult.length === wasmHexToBytesResult.length && 
+    viemHexToBytesResult.every((val, i) => val === wasmHexToBytesResult[i]));
+  console.log('');
+  
+  // Benchmark bytesToHex for each size
+  console.log('Benchmarking bytesToHex:');
+  for (let i = 0; i < sizes.length; i++) {
+    const size = sizes[i];
+    const bytes = testData[i];
+    
+    bench(`Viem bytesToHex - ${size} bytes`, () => {
+      bytesToHex(bytes);
+    });
+    
+    bench(`WASM bytesToHex - ${size} bytes`, () => {
+      wasmBytesToHex(wasmInstance, bytes);
+    });
+  }
+  
+  // Benchmark hexToBytes for each size
+  console.log('\nBenchmarking hexToBytes:');
+  for (let i = 0; i < sizes.length; i++) {
+    const size = sizes[i];
+    const hex = testHexes[i];
+    
+    bench(`Viem hexToBytes - ${size} bytes`, () => {
+      hexToBytes(hex);
+    });
+    
+    bench(`WASM hexToBytes - ${size} bytes`, () => {
+      wasmHexToBytes(wasmInstance, hex);
+    });
+  }
+});
\ No newline at end of file
diff --git a/src/final.bench.js b/src/final.bench.js
new file mode 100644
index 0000000000..9d79a3be7b
--- /dev/null
+++ b/src/final.bench.js
@@ -0,0 +1,95 @@
+import { bench, describe } from 'vitest';
+import { keccak256 as viemKeccak256 } from 'viem/utils';
+import { initWasm, keccak256 as wasmKeccak256, keccak256Stdlib as wasmKeccak256Stdlib } from './wasm-loader.js';
+
+describe('Final Benchmark Comparison', async () => {
+  // Initialize WASM instance
+  const wasmInstance = await initWasm();
+  
+  // Test data sizes
+  const smallHex = '0x' + 'a'.repeat(64);  // 32 bytes (uint256, typical ETH value)
+  const mediumHex = '0x' + 'b'.repeat(256); // 128 bytes
+  const largeHex = '0x' + 'c'.repeat(2048); // 1024 bytes
+  
+  // Verify hash results
+  console.log('Verification with ETH-sized input (32 bytes):');
+  const viemResult = viemKeccak256(smallHex);
+  const wasmResult = wasmKeccak256(wasmInstance, smallHex);
+  const wasmStdlibResult = wasmKeccak256Stdlib(wasmInstance, smallHex);
+  console.log('Viem result:', viemResult);
+  console.log('WASM result:', wasmResult);
+  console.log('WASM Stdlib result:', wasmStdlibResult);
+  console.log('All Equal:', viemResult === wasmResult && viemResult === wasmStdlibResult);
+  
+  // Individual operations (typical Ethereum transaction)
+  console.log('\nBenchmarking individual operations (ETH transaction):');
+  
+  bench('Viem keccak256 - ETH value', () => {
+    viemKeccak256(smallHex);
+  });
+  
+  bench('WASM keccak256 - ETH value', () => {
+    wasmKeccak256(wasmInstance, smallHex);
+  });
+
+  bench('WASM Stdlib keccak256 - ETH value', () => {
+    wasmKeccak256Stdlib(wasmInstance, smallHex);
+  });
+  
+  // Batch operations (multiple operations in succession)
+  console.log('\nBenchmarking batch operations (100 hashes):');
+  
+  // Create array of 100 slightly different inputs
+  const batchInputs = Array(100).fill().map((_, i) => 
+    '0x' + i.toString(16).padStart(64, 'a')
+  );
+  
+  // Large data (1024 bytes)
+  console.log('\nBenchmarking large data (1024 bytes):');
+  
+  bench('Viem keccak256 - Large data', () => {
+    viemKeccak256(largeHex);
+  });
+  
+  bench('WASM keccak256 - Large data', () => {
+    wasmKeccak256(wasmInstance, largeHex);
+  });
+
+  bench('WASM Stdlib keccak256 - Large data', () => {
+    wasmKeccak256Stdlib(wasmInstance, largeHex);
+  });
+  
+  // Batch operation benchmark
+  bench('Viem keccak256 - Batch (100 hashes)', () => {
+    for (const input of batchInputs) {
+      viemKeccak256(input);
+    }
+  });
+  
+  bench('WASM keccak256 - Batch (100 hashes)', () => {
+    for (const input of batchInputs) {
+      wasmKeccak256(wasmInstance, input);
+    }
+  });
+
+  bench('WASM Stdlib keccak256 - Batch (100 hashes)', () => {
+    for (const input of batchInputs) {
+      wasmKeccak256Stdlib(wasmInstance, input);
+    }
+  });
+  
+  // Smart contract deployment (larger data + intensive processing)
+  const contractCode = '0x' + 'e'.repeat(10000); // 5KB contract
+  
+  bench('Viem keccak256 - Contract deployment', () => {
+    viemKeccak256(contractCode);
+  });
+  
+  bench('WASM keccak256 - Contract deployment', () => {
+    wasmKeccak256(wasmInstance, contractCode);
+  });
+
+  bench('WASM Stdlib keccak256 - Contract deployment', () => {
+    wasmKeccak256Stdlib(wasmInstance, contractCode);
+  });
+});
\ No newline at end of file
diff --git a/src/keccak.bench.js b/src/keccak.bench.js
new file mode 100644
index 0000000000..eda7de2e07
--- /dev/null
+++ b/src/keccak.bench.js
@@ -0,0 +1,72 @@
+import { bench, describe } from 'vitest';
+import { keccak256 as viemKeccak256, bytesToHex, hexToBytes } from 'viem/utils';
+import { initWasm, keccak256 as wasmKeccak256, bytesToHex as wasmBytesToHex, hexToBytes as wasmHexToBytes } from './wasm-loader.js';
+
+describe('Keccak256 Benchmark', async () => {
+  // Initialize WASM module before running benchmarks
+  const wasmInstance = await initWasm();
+
+  // Test data with both Uint8Array and hex string formats
+  const smallData = new Uint8Array(32).fill(0xAA);
+  const smallHex = bytesToHex(smallData);
+
+  const mediumData = new Uint8Array(1024).fill(0xBB);
+  const mediumHex = bytesToHex(mediumData);
+
+  const largeData = new Uint8Array(32768).fill(0xCC); // 32KB
+  const largeHex = bytesToHex(largeData);
+
+  // Verify implementations with hex string input
+  const viemResult = viemKeccak256(smallHex);
+  const wasmResult = wasmKeccak256(wasmInstance, smallHex);
+
+  console.log('Verification with hex input (should be equal):');
+  console.log('Viem:', viemResult);
+  console.log('WASM:', wasmResult);
+  console.log('Equal:', viemResult === wasmResult);
+  console.log('');
+
+  // Benchmark small data with hex string input
+  bench('Viem keccak256 - Small hex string (32 bytes)', () => {
+    viemKeccak256(smallHex);
+  });
+
+  bench('WASM keccak256 - Small hex string (32 bytes)', () => {
+    wasmKeccak256(wasmInstance, smallHex);
+  });
+
+  // Benchmark medium data with hex string input
+  bench('Viem keccak256 - Medium hex string (1KB)', () => {
+    viemKeccak256(mediumHex);
+  });
+
+  bench('WASM keccak256 - Medium hex string (1KB)', () => {
+    wasmKeccak256(wasmInstance, mediumHex);
+  });
+
+  // Benchmark large data with hex string input
+  bench('Viem keccak256 - Large hex string (32KB)', () => {
+    viemKeccak256(largeHex);
+  });
+
+  bench('WASM keccak256 - Large hex string (32KB)', () => {
+    wasmKeccak256(wasmInstance, largeHex);
+  });
+
+  // Also benchmark the bytesToHex and hexToBytes functions
+  bench('Viem bytesToHex - Small data (32 bytes)', () => {
+    bytesToHex(smallData);
+  });
+
+  bench('WASM bytesToHex - Small data (32 bytes)', () => {
+    wasmBytesToHex(wasmInstance, smallData);
+  });
+
+  bench('Viem hexToBytes - Small hex (32 bytes)', () => {
+    hexToBytes(smallHex);
+  });
+
+  bench('WASM hexToBytes - Small hex (32 bytes)', () => {
+    wasmHexToBytes(wasmInstance, smallHex);
+  });
+});
\ No newline at end of file
diff --git a/src/package.json b/src/package.json
new file mode 100644
index 0000000000..bd8cf0d977
--- /dev/null
+++ b/src/package.json
@@ -0,0 +1,15 @@
+{
+  "name": "@tevm/zig",
+  "version": "0.0.1",
+  "private": true,
+  "type": "module",
+  "scripts": {
+    "test": "vitest run",
+    "test:watch": "vitest",
+    "bench": "vitest bench"
+  },
+  "devDependencies": {
+    "viem": "^2.29.2",
+    "vitest": "^3.1.3"
+  }
+}
\ No newline at end of file
diff --git a/src/root.zig b/src/root.zig
index cabaa478fe..48f504bf92 100644
--- a/src/root.zig
+++ b/src/root.zig
@@ -31,4 +31,110 @@ pub fn main() void {
     if (!is_wasm) {
         _ = runEvm();
     }
-}
\ No newline at end of file
+}
+
+// Helper function to convert a hex character to its numerical value
+fn hexCharToValue(c: u8) ?u8 {
+    return switch (c) {
+        '0'...'9' => c - '0',
+        'a'...'f' => c - 'a' + 10,
+        'A'...'F' => c - 'A' + 10,
+        else => null, // Invalid hex char
+    };
+}
+
+// WASM-compatible keccak256 function with bytes input/output
+export fn zig_keccak256(input_ptr: [*]const u8, input_len: usize, output_ptr: [*]u8) void {
+    const input = input_ptr[0..input_len];
+    const output = output_ptr[0..32];
+    std.crypto.hash.sha3.Keccak256.hash(input, output, .{});
+}
+
+// These functions use standard library implementions where possible
+export fn zig_hexToBytes(hex_ptr: [*]const u8, hex_len: usize, output_ptr: [*]u8) usize {
+    // Skip "0x" prefix if present
+    var start_idx: usize = 0;
+    if (hex_len >= 2 and hex_ptr[0] == '0' and (hex_ptr[1] == 'x' or hex_ptr[1] == 'X')) {
+        start_idx = 2;
+    }
+
+    // Get the hex string (without prefix)
+    const hex_string = hex_ptr[start_idx..hex_len];
+
+    // Calculate output buffer size (each pair of hex chars = 1 byte)
+    const hex_len_adjusted = hex_len - start_idx;
+    const out_len = (hex_len_adjusted + 1) / 2; // Handle odd length
+
+    // Create output slice for std.fmt.hexToBytes
+    const out_slice = output_ptr[0..out_len];
+
+    // Manual conversion using std functions for greater compatibility
+    var out_idx: usize = 0;
+    var i: usize = 0;
+
+    // Handle odd number of hex digits
+    if (hex_len_adjusted % 2 != 0) {
+        if (std.fmt.parseInt(u8, hex_string[0..1], 16)) |val| {
+            out_slice[out_idx] = val;
+            out_idx += 1;
+            i += 1;
+        } else |_| {
+            // Handle error by skipping this char
+        }
+    }
+
+    // Process the rest of the pairs
+    while (i < hex_len_adjusted) : (i += 2) {
+        if (i + 1 >= hex_len_adjusted) {
+            break;
+        }
+
+        if (std.fmt.parseInt(u8, hex_string[i .. i + 2], 16)) |val| {
+            out_slice[out_idx] = val;
+            out_idx += 1;
+        } else |_| {
+            // Handle error by skipping this pair
+        }
+    }
+
+    return out_idx;
+}
+
+// WASM-compatible bytesToHex function using std fmt utilities
+export fn zig_bytesToHex(bytes_ptr: [*]const u8, bytes_len: usize, output_ptr: [*]u8) usize {
+    // Write the 0x prefix
+    output_ptr[0] = '0';
+    output_ptr[1] = 'x';
+
+    // Create a slice for the output (excluding prefix)
+    const hex_out = output_ptr[2 .. 2 + bytes_len * 2];
+    const bytes = bytes_ptr[0..bytes_len];
+
+    // Manual conversion using std.fmt.digitToChar
+    for (bytes, 0..) |byte, i| {
+        const hex_idx = i * 2;
+        const hi_nib = @as(u4, @truncate(byte >> 4));
+        const lo_nib = @as(u4, @truncate(byte & 0x0F));
+
+        hex_out[hex_idx] = std.fmt.digitToChar(hi_nib, std.fmt.Case.lower);
+        hex_out[hex_idx + 1] = std.fmt.digitToChar(lo_nib, std.fmt.Case.lower);
+    }
+
+    return 2 + bytes_len * 2;
+}
+
+// WASM-compatible keccak256 function that takes a hex string and returns a hex string
+// using stdlib hex conversion
+export fn zig_keccak256_hex(hex_ptr: [*]const u8, hex_len: usize, output_ptr: [*]u8) usize {
+    var binary_buffer: [1024]u8 = undefined; // Buffer for binary data converted from hex
+
+    // Convert hex to bytes using stdlib
+    const binary_len = zig_hexToBytes(hex_ptr, hex_len, &binary_buffer);
+
+    // Compute keccak256 hash
+    var hash: [32]u8 = undefined;
+    std.crypto.hash.sha3.Keccak256.hash(binary_buffer[0..binary_len], &hash, .{});
+
+    // Convert hash to hex string using stdlib
+    return zig_bytesToHex(&hash, 32, output_ptr);
+}
diff --git a/src/stdlib-loader.js b/src/stdlib-loader.js
new file mode 100644
index 0000000000..32591aee73
--- /dev/null
+++ b/src/stdlib-loader.js
@@ -0,0 +1,178 @@
+import fs from 'fs';
+import { dirname, resolve } from 'path';
+import { fileURLToPath } from 'url';
+
+const __dirname = dirname(fileURLToPath(import.meta.url));
+const wasmPath = resolve(__dirname, '../dist/stdlib.wasm');
+const wasmBuffer = fs.readFileSync(wasmPath);
+
+/**
+ * Initializes the WebAssembly module
+ * @returns {Promise<WebAssembly.Instance>} The WebAssembly instance
+ */
+export async function initWasm() {
+  const { instance } = await WebAssembly.instantiate(wasmBuffer);
+
+  // Debug: Log all available exports
+  console.log('WASM exports:', Object.keys(instance.exports));
+
+  return instance;
+}
+
+/**
+ * Convert hex string to bytes using Zig's implementation
+ * @param {WebAssembly.Instance} instance - WASM instance
+ * @param {string} hexString - Hex string (with or without 0x prefix)
+ * @returns {Uint8Array} - Resulting byte array
+ */
+export function hexToBytes(instance, hexString) {
+  const memory = instance.exports.memory;
+  
+  // Convert hex string to UTF-8 encoding
+  const encoder = new TextEncoder();
+  const hexBytes = encoder.encode(hexString);
+  
+  // Ensure sufficient memory
+  const inputLen = hexBytes.length;
+  const outputLen = Math.ceil(inputLen / 2); // Approximate length of binary output
+  const memoryNeeded = inputLen + outputLen;
+  
+  const currentMemoryPages = memory.buffer.byteLength / (64 * 1024);
+  const pagesNeeded = Math.ceil(memoryNeeded / (64 * 1024));
+  
+  if (pagesNeeded > currentMemoryPages) {
+    memory.grow(pagesNeeded - currentMemoryPages);
+  }
+  
+  // Get memory buffer after potential resize
+  const memoryArray = new Uint8Array(memory.buffer);
+  
+  // Input pointer (hex string)
+  const inputPtr = 0;
+  memoryArray.set(hexBytes, inputPtr);
+  
+  // Output pointer (binary data)
+  const outputPtr = inputLen;
+  
+  // Call WASM function
+  const bytesWritten = instance.exports.zig_hexToBytes(inputPtr, inputLen, outputPtr);
+  
+  // Copy output to a new array
+  return new Uint8Array(memoryArray.buffer, outputPtr, bytesWritten);
+}
+
+/**
+ * Convert bytes to hex string using Zig's implementation
+ * @param {WebAssembly.Instance} instance - WASM instance
+ * @param {Uint8Array} bytes - Byte array to convert
+ * @returns {string} - Hex string with 0x prefix
+ */
+export function bytesToHex(instance, bytes) {
+  const memory = instance.exports.memory;
+  
+  // Ensure sufficient memory
+  const inputLen = bytes.length;
+  const outputLen = 2 + (inputLen * 2); // '0x' prefix + 2 chars per byte
+  const memoryNeeded = inputLen + outputLen;
+  
+  const currentMemoryPages = memory.buffer.byteLength / (64 * 1024);
+  const pagesNeeded = Math.ceil(memoryNeeded / (64 * 1024));
+  
+  if (pagesNeeded > currentMemoryPages) {
+    memory.grow(pagesNeeded - currentMemoryPages);
+  }
+  
+  // Get memory buffer after potential resize
+  const memoryArray = new Uint8Array(memory.buffer);
+  
+  // Input pointer (binary data)
+  const inputPtr = 0;
+  memoryArray.set(bytes, inputPtr);
+  
+  // Output pointer (hex string)
+  const outputPtr = inputLen;
+  
+  // Call WASM function
+  const hexLen = instance.exports.zig_bytesToHex(inputPtr, inputLen, outputPtr);
+  
+  // Convert output to JavaScript string
+  const decoder = new TextDecoder();
+  return decoder.decode(new Uint8Array(memory.buffer, outputPtr, hexLen));
+}
+
+/**
+ * Compute keccak256 hash using our Zig WASM implementation
+ * @param {WebAssembly.Instance} instance WASM instance
+ * @param {string|Uint8Array} input Input data to hash (hex string or bytes)
+ * @returns {string} Hex string hash result with 0x prefix
+ */
+export function keccak256(instance, input) {
+  if (typeof input === 'string') {
+    // Use the optimized all-in-one hex function
+    const encoder = new TextEncoder();
+    const hexBytes = encoder.encode(input);
+    
+    // Ensure memory is big enough
+    const memory = instance.exports.memory;
+    const inputLen = hexBytes.length;
+    const outputLen = 2 + (32 * 2); // '0x' prefix + 2 chars per byte for 32 byte hash
+    const memoryNeeded = inputLen + outputLen;
+    
+    const currentMemoryPages = memory.buffer.byteLength / (64 * 1024);
+    const pagesNeeded = Math.ceil(memoryNeeded / (64 * 1024));
+    
+    if (pagesNeeded > currentMemoryPages) {
+      memory.grow(pagesNeeded - currentMemoryPages);
+    }
+    
+    // Get memory buffer after potential resize
+    const memoryArray = new Uint8Array(memory.buffer);
+    
+    // Input pointer (hex string)
+    const inputPtr = 0;
+    memoryArray.set(hexBytes, inputPtr);
+    
+    // Output pointer (hex string hash)
+    const outputPtr = inputLen;
+    
+    // Call the all-in-one function
+    const hexLen = instance.exports.zig_keccak256_hex(inputPtr, inputLen, outputPtr);
+    
+    // Convert output to JavaScript string
+    const decoder = new TextDecoder();
+    return decoder.decode(new Uint8Array(memory.buffer, outputPtr, hexLen));
+  } else {
+    // Input is Uint8Array
+    const memory = instance.exports.memory;
+    
+    // Ensure memory is large enough
+    const inputLen = input.length;
+    const memoryNeeded = inputLen + 32; // Input bytes + 32 bytes for output hash
+    
+    const currentMemoryPages = memory.buffer.byteLength / (64 * 1024);
+    const pagesNeeded = Math.ceil(memoryNeeded / (64 * 1024));
+    
+    if (pagesNeeded > currentMemoryPages) {
+      memory.grow(pagesNeeded - currentMemoryPages);
+    }
+    
+    // Get memory buffer after potential resize
+    const memoryArray = new Uint8Array(memory.buffer);
+    
+    // Input pointer (binary data)
+    const inputPtr = 0;
+    memoryArray.set(input, inputPtr);
+    
+    // Output pointer (binary hash)
+    const outputPtr = inputLen;
+    
+    // Call the keccak256 function
+    instance.exports.zig_keccak256(inputPtr, inputLen, outputPtr);
+    
+    // Get the hash as bytes
+    const hashBytes = new Uint8Array(memory.buffer, outputPtr, 32);
+    
+    // Convert to hex string
+    return bytesToHex(instance, hashBytes);
+  }
+}
\ No newline at end of file
diff --git a/src/stdlib.bench.js b/src/stdlib.bench.js
new file mode 100644
index 0000000000..745ede95cc
--- /dev/null
+++ b/src/stdlib.bench.js
@@ -0,0 +1,180 @@
+import { bench, describe } from 'vitest';
+import { keccak256 as viemKeccak256, hexToBytes as viemHexToBytes, bytesToHex as viemBytesToHex } from 'viem/utils';
+import { initWasm as initOriginalWasm, keccak256 as originalKeccak256, hexToBytes as originalHexToBytes, bytesToHex as originalBytesToHex } from './wasm-loader.js';
+import { initWasm as initStdlibWasm, keccak256 as stdlibKeccak256, hexToBytes as stdlibHexToBytes, bytesToHex as stdlibBytesToHex } from './stdlib-loader.js';
+
+describe('Stdlib vs Original Implementation Benchmark', async () => {
+  // Initialize both WASM instances
+  const originalInstance = await initOriginalWasm();
+  const stdlibInstance = await initStdlibWasm();
+  
+  // Test data sizes
+  const smallHex = '0x' + 'a'.repeat(64);  // 32 bytes (uint256, typical ETH value)
+  const mediumHex = '0x' + 'b'.repeat(256); // 128 bytes
+  const largeHex = '0x' + 'c'.repeat(2048); // 1024 bytes
+  
+  // Verify hash results
+  console.log('Verification with ETH-sized input (32 bytes):');
+  const viemResult = viemKeccak256(smallHex);
+  const originalResult = originalKeccak256(originalInstance, smallHex);
+  const stdlibResult = stdlibKeccak256(stdlibInstance, smallHex);
+  
+  console.log('Viem Result:', viemResult);
+  console.log('Original Result:', originalResult);
+  console.log('Stdlib Result:', stdlibResult);
+  console.log('All Equal:', viemResult === originalResult && viemResult === stdlibResult);
+  
+  // Individual operations (typical Ethereum transaction)
+  console.log('\nBenchmarking ETH value (32 bytes):');
+  
+  bench('Viem keccak256 - ETH value (32 bytes)', () => {
+    viemKeccak256(smallHex);
+  });
+  
+  bench('Original WASM keccak256 - ETH value (32 bytes)', () => {
+    originalKeccak256(originalInstance, smallHex);
+  });
+  
+  bench('Stdlib WASM keccak256 - ETH value (32 bytes)', () => {
+    stdlibKeccak256(stdlibInstance, smallHex);
+  });
+  
+  // Medium data (128 bytes)
+  console.log('\nBenchmarking medium data (128 bytes):');
+  
+  bench('Viem keccak256 - Medium data (128 bytes)', () => {
+    viemKeccak256(mediumHex);
+  });
+  
+  bench('Original WASM keccak256 - Medium data (128 bytes)', () => {
+    originalKeccak256(originalInstance, mediumHex);
+  });
+  
+  bench('Stdlib WASM keccak256 - Medium data (128 bytes)', () => {
+    stdlibKeccak256(stdlibInstance, mediumHex);
+  });
+  
+  // Large data (1024 bytes)
+  console.log('\nBenchmarking large data (1024 bytes):');
+  
+  bench('Viem keccak256 - Large data (1024 bytes)', () => {
+    viemKeccak256(largeHex);
+  });
+  
+  bench('Original WASM keccak256 - Large data (1024 bytes)', () => {
+    originalKeccak256(originalInstance, largeHex);
+  });
+  
+  bench('Stdlib WASM keccak256 - Large data (1024 bytes)', () => {
+    stdlibKeccak256(stdlibInstance, largeHex);
+  });
+  
+  // Batch operations (multiple operations in succession)
+  console.log('\nBenchmarking batch operations (100 hashes):');
+  
+  // Create array of 100 slightly different inputs
+  const batchInputs = Array(100).fill().map((_, i) => 
+    '0x' + i.toString(16).padStart(64, 'a')
+  );
+  
+  bench('Viem keccak256 - Batch (100 hashes)', () => {
+    for (const input of batchInputs) {
+      viemKeccak256(input);
+    }
+  });
+  
+  bench('Original WASM keccak256 - Batch (100 hashes)', () => {
+    for (const input of batchInputs) {
+      originalKeccak256(originalInstance, input);
+    }
+  });
+  
+  bench('Stdlib WASM keccak256 - Batch (100 hashes)', () => {
+    for (const input of batchInputs) {
+      stdlibKeccak256(stdlibInstance, input);
+    }
+  });
+
+  // hexToBytes benchmarks
+  console.log('\nBenchmarking hexToBytes (string to bytes conversion):');
+
+  bench('Viem hexToBytes - ETH value (32 bytes)', () => {
+    viemHexToBytes(smallHex);
+  });
+
+  bench('Original WASM hexToBytes - ETH value (32 bytes)', () => {
+    originalHexToBytes(originalInstance, smallHex);
+  });
+
+  bench('Stdlib WASM hexToBytes - ETH value (32 bytes)', () => {
+    stdlibHexToBytes(stdlibInstance, smallHex);
+  });
+
+  bench('Viem hexToBytes - Medium data (128 bytes)', () => {
+    viemHexToBytes(mediumHex);
+  });
+
+  bench('Original WASM hexToBytes - Medium data (128 bytes)', () => {
+    originalHexToBytes(originalInstance, mediumHex);
+  });
+
+  bench('Stdlib WASM hexToBytes - Medium data (128 bytes)', () => {
+    stdlibHexToBytes(stdlibInstance, mediumHex);
+  });
+
+  bench('Viem hexToBytes - Large data (1024 bytes)', () => {
+    viemHexToBytes(largeHex);
+  });
+
+  bench('Original WASM hexToBytes - Large data (1024 bytes)', () => {
+    originalHexToBytes(originalInstance, largeHex);
+  });
+
+  bench('Stdlib WASM hexToBytes - Large data (1024 bytes)', () => {
+    stdlibHexToBytes(stdlibInstance, largeHex);
+  });
+
+  // bytesToHex benchmarks
+  console.log('\nBenchmarking bytesToHex (bytes to string conversion):');
+
+  // Convert hex strings to bytes arrays for testing bytesToHex
+  const smallBytes = viemHexToBytes(smallHex);
+  const mediumBytes = viemHexToBytes(mediumHex);
+  const largeBytes = viemHexToBytes(largeHex);
+
+  bench('Viem bytesToHex - ETH value (32 bytes)', () => {
+    viemBytesToHex(smallBytes);
+  });
+
+  bench('Original WASM bytesToHex - ETH value (32 bytes)', () => {
+    originalBytesToHex(originalInstance, smallBytes);
+  });
+
+  bench('Stdlib WASM bytesToHex - ETH value (32 bytes)', () => {
+    stdlibBytesToHex(stdlibInstance, smallBytes);
+  });
+
+  bench('Viem bytesToHex - Medium data (128 bytes)', () => {
+    viemBytesToHex(mediumBytes);
+  });
+
+  bench('Original WASM bytesToHex - Medium data (128 bytes)', () => {
+    originalBytesToHex(originalInstance, mediumBytes);
+  });
+
+  bench('Stdlib WASM bytesToHex - Medium data (128 bytes)', () => {
+    stdlibBytesToHex(stdlibInstance, mediumBytes);
+  });
+
+  bench('Viem bytesToHex - Large data (1024 bytes)', () => {
+    viemBytesToHex(largeBytes);
+  });
+
+  bench('Original WASM bytesToHex - Large data (1024 bytes)', () => {
+    originalBytesToHex(originalInstance, largeBytes);
+  });
+
+  bench('Stdlib WASM bytesToHex - Large data (1024 bytes)', () => {
+    stdlibBytesToHex(stdlibInstance, largeBytes);
+  });
+});
\ No newline at end of file
diff --git a/src/vitest.config.js b/src/vitest.config.js
new file mode 100644
index 0000000000..f101e4792e
--- /dev/null
+++ b/src/vitest.config.js
@@ -0,0 +1,10 @@
+import { defineConfig } from 'vitest/config';
+
+export default defineConfig({
+  test: {
+    include: ['**/*.{test,spec,bench}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
+    environment: 'node',
+    globals: true,
+    threads: false, // Disable threading for benchmarks
+  },
+});
\ No newline at end of file
diff --git a/src/wasm-loader.js b/src/wasm-loader.js
new file mode 100644
index 0000000000..33c62e4ae3
--- /dev/null
+++ b/src/wasm-loader.js
@@ -0,0 +1,453 @@
+import fs from 'fs';
+import { dirname, resolve } from 'path';
+import { fileURLToPath } from 'url';
+
+const __dirname = dirname(fileURLToPath(import.meta.url));
+const wasmPath = resolve(__dirname, '../dist/zigevm.wasm');
+const wasmBuffer = fs.readFileSync(wasmPath);
+
+/**
+ * Initializes the WebAssembly module
+ * @returns {Promise<WebAssembly.Instance>} The WebAssembly instance
+ */
+export async function initWasm() {
+  const { instance } = await WebAssembly.instantiate(wasmBuffer);
+
+  // Debug: Log all available exports
+  console.log('WASM exports:', Object.keys(instance.exports));
+
+  return instance;
+}
+
+/**
+ * Instantiates a ZIG WebAssembly module with a provided buffer
+ * @param {ArrayBuffer} wasmBuffer - WebAssembly binary data
+ * @returns {Promise<{keccak256: Function, hexToBytes: Function, bytesToHex: Function, hexToBytesStdlib: Function, bytesToHexStdlib: Function, keccak256Stdlib: Function}>} Module with exposed functions
+ */
+export async function instantiateZigModule(wasmBuffer) {
+  const { instance } = await WebAssembly.instantiate(wasmBuffer);
+
+  return {
+    keccak256: (input) => keccak256(instance, input),
+    hexToBytes: (hexStr) => hexToBytes(instance, hexStr),
+    bytesToHex: (bytes) => bytesToHex(instance, bytes),
+    hexToBytesStdlib: (hexStr) => hexToBytesStdlib(instance, hexStr),
+    bytesToHexStdlib: (bytes) => bytesToHexStdlib(instance, bytes),
+    keccak256Stdlib: (input) => keccak256Stdlib(instance, input),
+
+    // Added old implementations
+    hexToBytesOld: (hexStr) => {
+      const memory = instance.exports.memory;
+      const encoder = new TextEncoder();
+      const hexBytes = encoder.encode(hexStr);
+
+      const inputLen = hexBytes.length;
+      const outputLen = Math.ceil(inputLen / 2);
+      const memoryNeeded = inputLen + outputLen;
+
+      const currentMemoryPages = memory.buffer.byteLength / (64 * 1024);
+      const pagesNeeded = Math.ceil(memoryNeeded / (64 * 1024));
+
+      if (pagesNeeded > currentMemoryPages) {
+        memory.grow(pagesNeeded - currentMemoryPages);
+      }
+
+      const memoryArray = new Uint8Array(memory.buffer);
+      const inputPtr = 0;
+      memoryArray.set(hexBytes, inputPtr);
+      const outputPtr = inputLen;
+
+      const bytesWritten = instance.exports.zig_hexToBytes_old(inputPtr, inputLen, outputPtr);
+      return new Uint8Array(memoryArray.buffer, outputPtr, bytesWritten);
+    },
+
+    bytesToHexOld: (bytes) => {
+      const memory = instance.exports.memory;
+      const inputLen = bytes.length;
+      const outputLen = 2 + (inputLen * 2);
+      const memoryNeeded = inputLen + outputLen;
+
+      const currentMemoryPages = memory.buffer.byteLength / (64 * 1024);
+      const pagesNeeded = Math.ceil(memoryNeeded / (64 * 1024));
+
+      if (pagesNeeded > currentMemoryPages) {
+        memory.grow(pagesNeeded - currentMemoryPages);
+      }
+
+      const memoryArray = new Uint8Array(memory.buffer);
+      const inputPtr = 0;
+      memoryArray.set(bytes, inputPtr);
+      const outputPtr = inputLen;
+
+      const hexLen = instance.exports.zig_bytesToHex_old(inputPtr, inputLen, outputPtr);
+      const decoder = new TextDecoder();
+      return decoder.decode(new Uint8Array(memory.buffer, outputPtr, hexLen));
+    },
+
+    keccak256Old: (input) => {
+      if (typeof input === 'string') {
+        const encoder = new TextEncoder();
+        const hexBytes = encoder.encode(input);
+
+        const memory = instance.exports.memory;
+        const inputLen = hexBytes.length;
+        const outputLen = 2 + (32 * 2);
+        const memoryNeeded = inputLen + outputLen;
+
+        const currentMemoryPages = memory.buffer.byteLength / (64 * 1024);
+        const pagesNeeded = Math.ceil(memoryNeeded / (64 * 1024));
+
+        if (pagesNeeded > currentMemoryPages) {
+          memory.grow(pagesNeeded - currentMemoryPages);
+        }
+
+        const memoryArray = new Uint8Array(memory.buffer);
+        const inputPtr = 0;
+        memoryArray.set(hexBytes, inputPtr);
+        const outputPtr = inputLen;
+
+        const hexLen = instance.exports.zig_keccak256_hex_old(inputPtr, inputLen, outputPtr);
+        const decoder = new TextDecoder();
+        return decoder.decode(new Uint8Array(memory.buffer, outputPtr, hexLen));
+      } else {
+        const hashBytes = keccak256Bytes(instance, input);
+        const bytesToHexFn = instance.bytesToHexOld || bytesToHexOld;
+        return bytesToHexFn(instance, hashBytes);
+      }
+    }
+  };
+}
+
+/**
+ * Creates memory for use with WASM
+ * @param {number} size Size in pages (64KB per page)
+ * @returns {WebAssembly.Memory} WebAssembly memory
+ */
+export function createWasmMemory(size = 1) {
+  return new WebAssembly.Memory({ initial: size, maximum: 100 });
+}
+
+/**
+ * Convert hex string to bytes using Zig's implementation
+ * @param {WebAssembly.Instance} instance - WASM instance
+ * @param {string} hexString - Hex string (with or without 0x prefix)
+ * @returns {Uint8Array} - Resulting byte array
+ */
+export function hexToBytes(instance, hexString) {
+  const memory = instance.exports.memory;
+
+  // Convert hex string to UTF-8 encoding
+  const encoder = new TextEncoder();
+  const hexBytes = encoder.encode(hexString);
+
+  // Ensure sufficient memory
+  const inputLen = hexBytes.length;
+  const outputLen = Math.ceil(inputLen / 2); // Approximate length of binary output
+  const memoryNeeded = inputLen + outputLen;
+
+  const currentMemoryPages = memory.buffer.byteLength / (64 * 1024);
+  const pagesNeeded = Math.ceil(memoryNeeded / (64 * 1024));
+
+  if (pagesNeeded > currentMemoryPages) {
+    memory.grow(pagesNeeded - currentMemoryPages);
+  }
+
+  // Get memory buffer after potential resize
+  const memoryArray = new Uint8Array(memory.buffer);
+
+  // Input pointer (hex string)
+  const inputPtr = 0;
+  memoryArray.set(hexBytes, inputPtr);
+
+  // Output pointer (binary data)
+  const outputPtr = inputLen;
+
+  // Call WASM function
+  const bytesWritten = instance.exports.zig_hexToBytes(inputPtr, inputLen, outputPtr);
+
+  // Copy output to a new array
+  return new Uint8Array(memoryArray.buffer, outputPtr, bytesWritten);
+}
+
+/**
+ * Convert bytes to hex string using Zig's implementation
+ * @param {WebAssembly.Instance} instance - WASM instance
+ * @param {Uint8Array} bytes - Byte array to convert
+ * @returns {string} - Hex string with 0x prefix
+ */
+export function bytesToHex(instance, bytes) {
+  const memory = instance.exports.memory;
+
+  // Ensure sufficient memory
+  const inputLen = bytes.length;
+  const outputLen = 2 + (inputLen * 2); // '0x' prefix + 2 chars per byte
+  const memoryNeeded = inputLen + outputLen;
+
+  const currentMemoryPages = memory.buffer.byteLength / (64 * 1024);
+  const pagesNeeded = Math.ceil(memoryNeeded / (64 * 1024));
+
+  if (pagesNeeded > currentMemoryPages) {
+    memory.grow(pagesNeeded - currentMemoryPages);
+  }
+
+  // Get memory buffer after potential resize
+  const memoryArray = new Uint8Array(memory.buffer);
+
+  // Input pointer (binary data)
+  const inputPtr = 0;
+  memoryArray.set(bytes, inputPtr);
+
+  // Output pointer (hex string)
+  const outputPtr = inputLen;
+
+  // Call WASM function
+  const hexLen = instance.exports.zig_bytesToHex(inputPtr, inputLen, outputPtr);
+
+  // Convert output to JavaScript string
+  const decoder = new TextDecoder();
+  return decoder.decode(new Uint8Array(memoryArray.buffer, outputPtr, hexLen));
+}
+
+/**
+ * Compute keccak256 hash using our Zig WASM implementation with binary input/output
+ * @param {WebAssembly.Instance} instance WASM instance
+ * @param {Uint8Array} input Input data to hash
+ * @returns {Uint8Array} 32-byte hash result
+ */
+export function keccak256Bytes(instance, input) {
+  // Ensure our memory is large enough
+  const memory = instance.exports.memory;
+
+  // Ensure memory is large enough for input and output (input + 32 bytes for output)
+  const memoryNeeded = input.length + 32;
+  const currentMemoryPages = memory.buffer.byteLength / (64 * 1024);
+  const pagesNeeded = Math.ceil(memoryNeeded / (64 * 1024));
+
+  if (pagesNeeded > currentMemoryPages) {
+    memory.grow(pagesNeeded - currentMemoryPages);
+  }
+
+  // Get the current memory buffer after potential growth
+  const memoryArray = new Uint8Array(memory.buffer);
+
+  // Allocate memory for input (starting at position 0)
+  const inputPtr = 0;
+  const inputLen = input.length;
+
+  // Write input to memory
+  memoryArray.set(input, inputPtr);
+
+  // Output buffer starts after input
+  const outputPtr = inputPtr + inputLen;
+
+  // Call WASM function
+  instance.exports.zig_keccak256(inputPtr, inputLen, outputPtr);
+
+  // Read result from memory
+  const result = new Uint8Array(32);
+  for (let i = 0; i < 32; i++) {
+    result[i] = memoryArray[outputPtr + i];
+  }
+
+  return result;
+}
+
+/**
+ * Compute keccak256 hash with hex string input/output
+ * This version accepts either a Uint8Array or a hex string and returns a hex string,
+ * matching the viem interface.
+ *
+ * @param {WebAssembly.Instance} instance WASM instance
+ * @param {Uint8Array|string} input Input data to hash (Uint8Array or hex string)
+ * @returns {string} Hex string hash result with 0x prefix
+ */
+export function keccak256(instance, input) {
+  if (typeof input === 'string') {
+    // Use the optimized all-in-one hex function
+    const encoder = new TextEncoder();
+    const hexBytes = encoder.encode(input);
+
+    // Ensure memory is big enough
+    const memory = instance.exports.memory;
+    const inputLen = hexBytes.length;
+    const outputLen = 2 + (32 * 2); // '0x' prefix + 2 chars per byte for 32 byte hash
+    const memoryNeeded = inputLen + outputLen;
+
+    const currentMemoryPages = memory.buffer.byteLength / (64 * 1024);
+    const pagesNeeded = Math.ceil(memoryNeeded / (64 * 1024));
+
+    if (pagesNeeded > currentMemoryPages) {
+      memory.grow(pagesNeeded - currentMemoryPages);
+    }
+
+    // Get memory buffer after potential resize
+    const memoryArray = new Uint8Array(memory.buffer);
+
+    // Input pointer (hex string)
+    const inputPtr = 0;
+    memoryArray.set(hexBytes, inputPtr);
+
+    // Output pointer (hex string hash)
+    const outputPtr = inputLen;
+
+    // Call the all-in-one function
+    const hexLen = instance.exports.zig_keccak256_hex(inputPtr, inputLen, outputPtr);
+
+    // Convert output to JavaScript string
+    const decoder = new TextDecoder();
+    return decoder.decode(new Uint8Array(memoryArray.buffer, outputPtr, hexLen));
+  } else {
+    // Input is Uint8Array, hash it and convert to hex
+    const hashBytes = keccak256Bytes(instance, input);
+    return bytesToHex(instance, hashBytes);
+  }
+}
+
+/**
+ * Convert hex string to bytes using Zig's stdlib implementation
+ * @param {WebAssembly.Instance} instance - WASM instance
+ * @param {string} hexString - Hex string (with or without 0x prefix)
+ * @returns {Uint8Array} - Resulting byte array
+ */
+export function hexToBytesStdlib(instance, hexString) {
+  const memory = instance.exports.memory;
+
+  // Convert hex string to UTF-8 encoding
+  const encoder = new TextEncoder();
+  const hexBytes = encoder.encode(hexString);
+
+  // Ensure sufficient memory
+  const inputLen = hexBytes.length;
+  const outputLen = Math.ceil(inputLen / 2); // Approximate length of binary output
+  const memoryNeeded = inputLen + outputLen;
+
+  const currentMemoryPages = memory.buffer.byteLength / (64 * 1024);
+  const pagesNeeded = Math.ceil(memoryNeeded / (64 * 1024));
+
+  if (pagesNeeded > currentMemoryPages) {
+    memory.grow(pagesNeeded - currentMemoryPages);
+  }
+
+  // Get memory buffer after potential resize
+  const memoryArray = new Uint8Array(memory.buffer);
+
+  // Input pointer (hex string)
+  const inputPtr = 0;
+  memoryArray.set(hexBytes, inputPtr);
+
+  // Output pointer (binary data)
+  const outputPtr = inputLen;
+
+  // Call WASM function
+  const bytesWritten = instance.exports.zig_hexToBytes_stdlib(inputPtr, inputLen, outputPtr);
+
+  // Copy output to a new array
+  return new Uint8Array(memoryArray.buffer, outputPtr, bytesWritten);
+}
+
+/**
+ * Convert bytes to hex string using Zig's stdlib implementation
+ * @param {WebAssembly.Instance} instance - WASM instance
+ * @param {Uint8Array} bytes - Byte array to convert
+ * @returns {string} - Hex string with 0x prefix
+ */
+export function bytesToHexStdlib(instance, bytes) {
+  const memory = instance.exports.memory;
+
+  // Ensure sufficient memory
+  const inputLen = bytes.length;
+  const outputLen = 2 + (inputLen * 2); // '0x' prefix + 2 chars per byte
+  const memoryNeeded = inputLen + outputLen;
+
+  const currentMemoryPages = memory.buffer.byteLength / (64 * 1024);
+  const pagesNeeded = Math.ceil(memoryNeeded / (64 * 1024));
+
+  if (pagesNeeded > currentMemoryPages) {
+    memory.grow(pagesNeeded - currentMemoryPages);
+  }
+
+  // Get memory buffer after potential resize
+  const memoryArray = new Uint8Array(memory.buffer);
+
+  // Input pointer (binary data)
+  const inputPtr = 0;
+  memoryArray.set(bytes, inputPtr);
+
+  // Output pointer (hex string)
+  const outputPtr = inputLen;
+
+  // Call WASM function
+  const hexLen = instance.exports.zig_bytesToHex_stdlib(inputPtr, inputLen, outputPtr);
+
+  // Convert output to JavaScript string
+  const decoder = new TextDecoder();
+  return decoder.decode(new Uint8Array(memory.buffer, outputPtr, hexLen));
+}
+
+/**
+ * Compute keccak256 hash using Zig stdlib implementation for conversions
+ * @param {WebAssembly.Instance} instance WASM instance
+ * @param {string|Uint8Array} input Input data to hash (hex string or bytes)
+ * @returns {string} Hex string hash result with 0x prefix
+ */
+export function keccak256Stdlib(instance, input) {
+  if (typeof input === 'string') {
+    // Use the optimized all-in-one hex function
+    const encoder = new TextEncoder();
+    const hexBytes = encoder.encode(input);
+
+    // Ensure memory is big enough
+    const memory = instance.exports.memory;
+    const inputLen = hexBytes.length;
+    const outputLen = 2 + (32 * 2); // '0x' prefix + 2 chars per byte for 32 byte hash
+    const memoryNeeded = inputLen + outputLen;
+
+    const currentMemoryPages = memory.buffer.byteLength / (64 * 1024);
+    const pagesNeeded = Math.ceil(memoryNeeded / (64 * 1024));
+
+    if (pagesNeeded > currentMemoryPages) {
+      memory.grow(pagesNeeded - currentMemoryPages);
+    }
+
+    // Get memory buffer after potential resize
+    const memoryArray = new Uint8Array(memory.buffer);
+
+    // Input pointer (hex string)
+    const inputPtr = 0;
+    memoryArray.set(hexBytes, inputPtr);
+
+    // Output pointer (hex string hash)
+    const outputPtr = inputLen;
+
+    // Call the all-in-one function
+    const hexLen = instance.exports.zig_keccak256_hex_stdlib(inputPtr, inputLen, outputPtr);
+
+    // Convert output to JavaScript string
+    const decoder = new TextDecoder();
+    return decoder.decode(new Uint8Array(memory.buffer, outputPtr, hexLen));
+  } else {
+    // Input is Uint8Array, hash it and convert to hex
+    const hashBytes = keccak256Bytes(instance, input);
+    return bytesToHexStdlib(instance, hashBytes);
+  }
+}
+
+// Run the init function when this module is executed directly
+if (import.meta.url === `file://${process.argv[1]}`) {
+  (async () => {
+    try {
+      const instance = await initWasm();
+      console.log('WASM exports details:');
+      for (const key of Object.keys(instance.exports)) {
+        console.log(`- ${key}: ${typeof instance.exports[key]}`);
+      }
+
+      // Test runEvm function
+      if (instance.exports.runEvm) {
+        console.log('Result of runEvm():', instance.exports.runEvm());
+      }
+    } catch (err) {
+      console.error('Error loading WASM:', err);
+    }
+  })();
+}
\ No newline at end of file


Reviews:
user: login: coderabbitai[bot]
body: **Actionable comments posted: 5**

<details>
<summary>🧹 Nitpick comments (16)</summary><blockquote>

<details>
<summary>src/vitest.config.js (1)</summary><blockquote>

`1-10`: **Clean Vitest configuration for benchmark tests**

The configuration is well-structured with appropriate settings for running benchmarks:
- Proper file pattern inclusion for test/benchmark files
- Node environment correctly specified
- Threading explicitly disabled with helpful comment

This configuration effectively supports the benchmark test suites for cryptographic operations.


As the test suite grows, you might consider separating test patterns (`*.test.*`, `*.spec.*`) from benchmark patterns (`*.bench.*`) to avoid accidentally running benchmarks during regular testing.

</blockquote></details>
<details>
<summary>src/build-stdlib.sh (1)</summary><blockquote>

`1-9`: **Script looks good but should verify the dist directory exists**

The script builds a standard library WASM file from Zig. While it works correctly, it doesn't verify the `../dist` directory exists before writing to it.


Consider adding a `mkdir -p ../dist` command before the build step, similar to the approach in the `build:wasm` script in package.json:

```diff
#!/bin/bash
set -e

+# Ensure dist directory exists
+mkdir -p ../dist
+
# Build the standard library version of the WASM file
zig build-exe -fno-entry -OReleaseSmall -target wasm32-freestanding ./stdlib3.zig -femit-bin=../dist/stdlib.wasm
```

</blockquote></details>
<details>
<summary>src/final.bench.js (3)</summary><blockquote>

`9-13`: **Use template literals instead of string concatenation**

The static analysis tool correctly identifies that template literals are preferred over string concatenation for readability and maintainability.


Consider using template literals instead of string concatenation:

```diff
-const smallHex = '0x' + 'a'.repeat(64);  // 32 bytes (uint256, typical ETH value)
-const mediumHex = '0x' + 'b'.repeat(256); // 128 bytes
-const largeHex = '0x' + 'c'.repeat(2048); // 1024 bytes
+const smallHex = `0x${'a'.repeat(64)}`;  // 32 bytes (uint256, typical ETH value)
+const mediumHex = `0x${'b'.repeat(256)}`; // 128 bytes
+const largeHex = `0x${'c'.repeat(2048)}`; // 1024 bytes
```

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 Biome (1.9.4)</summary>

[error] 10-10: Template literals are preferred over string concatenation.

Unsafe fix: Use a template literal.


(lint/style/useTemplate)

---

[error] 11-11: Template literals are preferred over string concatenation.

Unsafe fix: Use a template literal.


(lint/style/useTemplate)

---

[error] 12-12: Template literals are preferred over string concatenation.

Unsafe fix: Use a template literal.


(lint/style/useTemplate)

</details>

</details>

---

`39-46`: **Use template literals for batch input generation**

Similar to earlier string concatenation, template literals would be more modern here.


```diff
const batchInputs = Array(100).fill().map((_, i) => 
-    '0x' + i.toString(16).padStart(64, 'a')
+    `0x${i.toString(16).padStart(64, 'a')}`
);
```

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 Biome (1.9.4)</summary>

[error] 44-44: Template literals are preferred over string concatenation.

Unsafe fix: Use a template literal.


(lint/style/useTemplate)

</details>

</details>

---

`81-95`: **Contract deployment simulation with large input**

The contract deployment benchmark with a 5KB input is an excellent real-world test case relevant to Ethereum operations.


Use template literals for the contract code:

```diff
-const contractCode = '0x' + 'e'.repeat(10000); // 5KB contract
+const contractCode = `0x${'e'.repeat(10000)}`; // 5KB contract
```

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 Biome (1.9.4)</summary>

[error] 82-82: Template literals are preferred over string concatenation.

Unsafe fix: Use a template literal.


(lint/style/useTemplate)

</details>

</details>

</blockquote></details>
<details>
<summary>src/conversion.bench.js (1)</summary><blockquote>

`41-54`: **Dynamic `bench` registration inside a loop limits reporter output granularity**

Registering hundreds of benches programmatically can make the output noisy and harder to grep.  Consider grouping benches with `describe.each` or a helper to flatten the test matrix, e.g.:

```js
sizes.forEach(size => {
  bench(`bytesToHex (${size}B) ‑ viem`, () => { ... })
  bench(`bytesToHex (${size}B) ‑ wasm`, () => { ... })
});
```

The behaviour is identical, but the test names become predictable and compact.

</blockquote></details>
<details>
<summary>src/stdlib.bench.js (2)</summary><blockquote>

`12-14`: **Prefer template literals over string concatenation (Biome lint `useTemplate`)**

The linter flags these lines.  Switching to template literals improves readability and avoids accidental coercion:

```diff
-const smallHex = '0x' + 'a'.repeat(64);
-const mediumHex = '0x' + 'b'.repeat(256);
-const largeHex = '0x' + 'c'.repeat(2048);
+const smallHex  = `0x${'a'.repeat(64)}`;
+const mediumHex = `0x${'b'.repeat(256)}`;
+const largeHex  = `0x${'c'.repeat(2048)}`;
…
-const batchInputs = Array(100).fill().map((_, i) =>
-  '0x' + i.toString(16).padStart(64, 'a')
-);
+const batchInputs = Array.from({ length: 100 }, (_, i) =>
+  `0x${i.toString(16).padStart(64, 'a')}`
+);
```



Also applies to: 77-78

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 Biome (1.9.4)</summary>

[error] 12-12: Template literals are preferred over string concatenation.

Unsafe fix: Use a template literal.


(lint/style/useTemplate)

---

[error] 13-13: Template literals are preferred over string concatenation.

Unsafe fix: Use a template literal.


(lint/style/useTemplate)

---

[error] 14-14: Template literals are preferred over string concatenation.

Unsafe fix: Use a template literal.


(lint/style/useTemplate)

</details>

</details>

---

`6-10`: **Initialisation in `describe` callback – favour `beforeAll`**

For the same reasons noted in `conversion.bench.js`, moving WASM initialisation into a `beforeAll` block makes the lifecycle explicit and avoids unhandled-promise edge-cases.

</blockquote></details>
<details>
<summary>src/root.zig (1)</summary><blockquote>

`36-44`: **`hexCharToValue` is dead code**

The helper is not referenced after the current refactor.  Delete it or wire it into `zig_hexToBytes` to avoid bloat and keep the export surface minimal.

</blockquote></details>
<details>
<summary>src/comparison.bench.js (2)</summary><blockquote>

`8-10`: **Use the `node:` import specifier for built-ins**

Biome flags these three imports; switching to the `node:` protocol is the modern, explicit form and avoids false-positives in many linters:

```diff
-import fs from "fs";
-import path from "path";
-import { fileURLToPath } from "url";
+import fs from "node:fs";
+import path from "node:path";
+import { fileURLToPath } from "node:url";
```

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 Biome (1.9.4)</summary>

[error] 8-8: A Node.js builtin module should be imported with the node: protocol.

Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.


(lint/style/useNodejsImportProtocol)

---

[error] 9-9: A Node.js builtin module should be imported with the node: protocol.

Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.


(lint/style/useNodejsImportProtocol)

---

[error] 10-10: A Node.js builtin module should be imported with the node: protocol.

Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.


(lint/style/useNodejsImportProtocol)

</details>

</details>

---

`21-25`: **Prefer template literals for the sample hex strings**

Minor style nit – Biome suggests template literals:

```diff
-const smallHex  = "0x" + "a".repeat(64);
+const smallHex  = `0x${"a".repeat(64)}`;
```
(and similarly for `mediumHex` / `largeHex`).

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 Biome (1.9.4)</summary>

[error] 21-21: Template literals are preferred over string concatenation.

Unsafe fix: Use a template literal.


(lint/style/useTemplate)

---

[error] 22-22: Template literals are preferred over string concatenation.

Unsafe fix: Use a template literal.


(lint/style/useTemplate)

---

[error] 23-23: Template literals are preferred over string concatenation.

Unsafe fix: Use a template literal.


(lint/style/useTemplate)

</details>

</details>

</blockquote></details>
<details>
<summary>src/stdlib-loader.js (3)</summary><blockquote>

`1-3`: **Adopt `node:` prefixes for built-in modules**

For consistency with ESM best-practices and to silence Biome:

```diff
-import fs from 'fs';
-import { dirname, resolve } from 'path';
-import { fileURLToPath } from 'url';
+import fs from 'node:fs';
+import { dirname, resolve } from 'node:path';
+import { fileURLToPath } from 'node:url';
```

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 Biome (1.9.4)</summary>

[error] 1-1: A Node.js builtin module should be imported with the node: protocol.

Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.


(lint/style/useNodejsImportProtocol)

---

[error] 2-2: A Node.js builtin module should be imported with the node: protocol.

Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.


(lint/style/useNodejsImportProtocol)

---

[error] 3-3: A Node.js builtin module should be imported with the node: protocol.

Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.


(lint/style/useNodejsImportProtocol)

</details>

</details>

---

`109-178`: **Remove the superfluous `else` branch for cleaner control flow**

After the `if (typeof input === 'string')` branch returns, the `else` is unnecessary and flagged by Biome.  Collapsing the branches also shortens indentation:

```diff
-  if (typeof input === 'string') {
-    ...
-    return decoder.decode(...);
-  } else {
-    // Input is Uint8Array
-    ...
-    return bytesToHex(instance, hashBytes);
-  }
+  if (typeof input === 'string') {
+    ...
+    return decoder.decode(...);
+  }
+
+  // Input is Uint8Array
+  ...
+  return bytesToHex(instance, hashBytes);
```

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 Biome (1.9.4)</summary>

[error] 144-177: This else clause can be omitted because previous branches break early.

Unsafe fix: Omit the else clause.


(lint/style/noUselessElse)

</details>

</details>

---

`28-100`: **Memory-growth logic is repeated in every helper – consider extracting a utility**

Each conversion/hash function repeats ~15 lines to compute pages and call `memory.grow`.  A small helper removes duplication and centralises one potential bug-surface:

```js
function ensureMemory(memory, requiredBytes) {
  const current = memory.buffer.byteLength;
  if (requiredBytes > current) {
    const pagesNeeded = Math.ceil(requiredBytes / 65536);
    const currentPages = current / 65536;
    memory.grow(pagesNeeded - currentPages);
  }
}
```

Then:

```diff
-const currentMemoryPages = memory.buffer.byteLength / (64 * 1024);
-const pagesNeeded = Math.ceil(memoryNeeded / (64 * 1024));
-if (pagesNeeded > currentMemoryPages) {
-  memory.grow(pagesNeeded - currentMemoryPages);
-}
+ensureMemory(memory, memoryNeeded);
```

This keeps the loaders concise and less error-prone.

</blockquote></details>
<details>
<summary>src/wasm-loader.js (2)</summary><blockquote>

`1-3`: **Prefix Node built-ins with `node:`**

Same style improvement as earlier:

```diff
-import fs from 'fs';
-import { dirname, resolve } from 'path';
-import { fileURLToPath } from 'url';
+import fs from 'node:fs';
+import { dirname, resolve } from 'node:path';
+import { fileURLToPath } from 'node:url';
```

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 Biome (1.9.4)</summary>

[error] 1-1: A Node.js builtin module should be imported with the node: protocol.

Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.


(lint/style/useNodejsImportProtocol)

---

[error] 2-2: A Node.js builtin module should be imported with the node: protocol.

Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.


(lint/style/useNodejsImportProtocol)

---

[error] 3-3: A Node.js builtin module should be imported with the node: protocol.

Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.


(lint/style/useNodejsImportProtocol)

</details>

</details>

---

`428-432`: **Minor: drop unnecessary `else` after early return**

Same pattern appears a few times and is flagged by Biome; pruning it clarifies the flow and saves one indentation level.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 Biome (1.9.4)</summary>

[error] 428-432: This else clause can be omitted because previous branches break early.

Unsafe fix: Omit the else clause.


(lint/style/noUselessElse)

</details>

</details>

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between fbc5338b9a7fbd7b14e1c7d7b6dee4788242aae7 and dad7ac9a7fe2a1b7ffddb8eb74770c032c9afe04.

</details>

<details>
<summary>⛔ Files ignored due to path filters (1)</summary>

* `pnpm-lock.yaml` is excluded by `!**/pnpm-lock.yaml`

</details>

<details>
<summary>📒 Files selected for processing (14)</summary>

* `.gitignore` (1 hunks)
* `package.json` (1 hunks)
* `pnpm-workspace.yaml` (1 hunks)
* `src/build-stdlib.sh` (1 hunks)
* `src/comparison.bench.js` (1 hunks)
* `src/conversion.bench.js` (1 hunks)
* `src/final.bench.js` (1 hunks)
* `src/keccak.bench.js` (1 hunks)
* `src/package.json` (1 hunks)
* `src/root.zig` (1 hunks)
* `src/stdlib-loader.js` (1 hunks)
* `src/stdlib.bench.js` (1 hunks)
* `src/vitest.config.js` (1 hunks)
* `src/wasm-loader.js` (1 hunks)

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🧬 Code Graph Analysis (3)</summary>

<details>
<summary>src/final.bench.js (4)</summary><blockquote>

<details>
<summary>src/keccak.bench.js (6)</summary>

* `wasmInstance` (7-7)
* `smallHex` (11-11)
* `mediumHex` (14-14)
* `largeHex` (17-17)
* `viemResult` (20-20)
* `wasmResult` (21-21)

</details>
<details>
<summary>src/wasm-loader.js (2)</summary>

* `initWasm` (13-20)
* `i` (248-248)

</details>
<details>
<summary>src/comparison.bench.js (7)</summary>

* `smallHex` (21-21)
* `mediumHex` (22-22)
* `largeHex` (23-23)
* `viemResult` (30-30)
* `wasmResult` (31-31)
* `wasmStdlibResult` (32-32)
* `batchInputs` (92-94)

</details>
<details>
<summary>src/stdlib.bench.js (5)</summary>

* `smallHex` (12-12)
* `mediumHex` (13-13)
* `largeHex` (14-14)
* `viemResult` (18-18)
* `batchInputs` (76-78)

</details>

</blockquote></details>
<details>
<summary>src/conversion.bench.js (1)</summary><blockquote>

<details>
<summary>src/wasm-loader.js (4)</summary>

* `initWasm` (13-20)
* `i` (248-248)
* `bytesToHex` (178-209)
* `hexToBytes` (136-170)

</details>

</blockquote></details>
<details>
<summary>src/stdlib.bench.js (3)</summary><blockquote>

<details>
<summary>src/final.bench.js (5)</summary>

* `smallHex` (10-10)
* `mediumHex` (11-11)
* `largeHex` (12-12)
* `viemResult` (16-16)
* `batchInputs` (43-45)

</details>
<details>
<summary>src/comparison.bench.js (5)</summary>

* `smallHex` (21-21)
* `mediumHex` (22-22)
* `largeHex` (23-23)
* `viemResult` (30-30)
* `batchInputs` (92-94)

</details>
<details>
<summary>src/wasm-loader.js (1)</summary>

* `i` (248-248)

</details>

</blockquote></details>

</details><details>
<summary>🪛 Biome (1.9.4)</summary>

<details>
<summary>src/final.bench.js</summary>

[error] 10-10: Template literals are preferred over string concatenation.

Unsafe fix: Use a template literal.


(lint/style/useTemplate)

---

[error] 11-11: Template literals are preferred over string concatenation.

Unsafe fix: Use a template literal.


(lint/style/useTemplate)

---

[error] 12-12: Template literals are preferred over string concatenation.

Unsafe fix: Use a template literal.


(lint/style/useTemplate)

---

[error] 44-44: Template literals are preferred over string concatenation.

Unsafe fix: Use a template literal.


(lint/style/useTemplate)

---

[error] 82-82: Template literals are preferred over string concatenation.

Unsafe fix: Use a template literal.


(lint/style/useTemplate)

</details>
<details>
<summary>src/stdlib.bench.js</summary>

[error] 12-12: Template literals are preferred over string concatenation.

Unsafe fix: Use a template literal.


(lint/style/useTemplate)

---

[error] 13-13: Template literals are preferred over string concatenation.

Unsafe fix: Use a template literal.


(lint/style/useTemplate)

---

[error] 14-14: Template literals are preferred over string concatenation.

Unsafe fix: Use a template literal.


(lint/style/useTemplate)

---

[error] 77-77: Template literals are preferred over string concatenation.

Unsafe fix: Use a template literal.


(lint/style/useTemplate)

</details>
<details>
<summary>src/comparison.bench.js</summary>

[error] 8-8: A Node.js builtin module should be imported with the node: protocol.

Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.


(lint/style/useNodejsImportProtocol)

---

[error] 9-9: A Node.js builtin module should be imported with the node: protocol.

Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.


(lint/style/useNodejsImportProtocol)

---

[error] 10-10: A Node.js builtin module should be imported with the node: protocol.

Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.


(lint/style/useNodejsImportProtocol)

---

[error] 21-21: Template literals are preferred over string concatenation.

Unsafe fix: Use a template literal.


(lint/style/useTemplate)

---

[error] 22-22: Template literals are preferred over string concatenation.

Unsafe fix: Use a template literal.


(lint/style/useTemplate)

---

[error] 23-23: Template literals are preferred over string concatenation.

Unsafe fix: Use a template literal.


(lint/style/useTemplate)

---

[error] 94-94: Template literals are preferred over string concatenation.

Unsafe fix: Use a template literal.


(lint/style/useTemplate)

</details>
<details>
<summary>src/stdlib-loader.js</summary>

[error] 1-1: A Node.js builtin module should be imported with the node: protocol.

Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.


(lint/style/useNodejsImportProtocol)

---

[error] 2-2: A Node.js builtin module should be imported with the node: protocol.

Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.


(lint/style/useNodejsImportProtocol)

---

[error] 3-3: A Node.js builtin module should be imported with the node: protocol.

Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.


(lint/style/useNodejsImportProtocol)

---

[error] 144-177: This else clause can be omitted because previous branches break early.

Unsafe fix: Omit the else clause.


(lint/style/noUselessElse)

</details>
<details>
<summary>src/wasm-loader.js</summary>

[error] 1-1: A Node.js builtin module should be imported with the node: protocol.

Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.


(lint/style/useNodejsImportProtocol)

---

[error] 2-2: A Node.js builtin module should be imported with the node: protocol.

Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.


(lint/style/useNodejsImportProtocol)

---

[error] 3-3: A Node.js builtin module should be imported with the node: protocol.

Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.


(lint/style/useNodejsImportProtocol)

---

[error] 112-116: This else clause can be omitted because previous branches break early.

Unsafe fix: Omit the else clause.


(lint/style/noUselessElse)

---

[error] 299-303: This else clause can be omitted because previous branches break early.

Unsafe fix: Omit the else clause.


(lint/style/noUselessElse)

---

[error] 428-432: This else clause can be omitted because previous branches break early.

Unsafe fix: Omit the else clause.


(lint/style/noUselessElse)

</details>

</details>

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (7)</summary>

* GitHub Check: Nx Cloud Agents (5)
* GitHub Check: Nx Cloud Agents (6)
* GitHub Check: Nx Cloud Agents (1)
* GitHub Check: Nx Cloud Agents (4)
* GitHub Check: Nx Cloud Agents (2)
* GitHub Check: Nx Cloud Agents (3)
* GitHub Check: Nx Cloud - Main Job

</details>

<details>
<summary>🔇 Additional comments (14)</summary><blockquote>

<details>
<summary>pnpm-workspace.yaml (1)</summary>

`16-16`: **Workspace configuration correctly updated to include src directory**

The addition of the `src` directory to the workspace packages list properly integrates it with the pnpm monorepo structure, enabling dependency and script management for the new benchmarking tools.

</details>
<details>
<summary>.gitignore (1)</summary>

`89-89`: **Good practice adding Claude AI settings to gitignore**

Adding `**/.claude/settings.local.json` to .gitignore properly prevents personal Claude AI configuration from being committed to version control, which aligns with good practices for excluding local configuration files.

</details>
<details>
<summary>src/package.json (1)</summary>

`1-15`: **Well-structured package.json for benchmarking tools**

The package configuration is clean and follows npm conventions:
- Appropriate namespace and version
- Correctly configured as a private ES module 
- Well-named scripts for testing and benchmarking
- Proper devDependencies with flexible versioning

This setup effectively supports the benchmarking objectives described in the PR.

</details>
<details>
<summary>package.json (1)</summary>

`26-26`: **Improved WASM build script correctly handles directory creation**

The updated `build:wasm` script now creates the `../dist` directory if it doesn't exist and then copies the WASM file from the Zig build cache to the distribution folder. This ensures the WASM artifact is consistently placed in the correct location.

</details>
<details>
<summary>src/keccak.bench.js (5)</summary>

`1-8`: **Well-structured benchmark setup with proper initialization**

The benchmark file is set up correctly with all necessary imports and proper async initialization of the WASM module before running benchmarks.

---

`9-18`: **Good test data preparation with varied sizes**

Test data is well prepared with small (32 bytes), medium (1KB), and large (32KB) sizes, covering a good range of use cases. Both Uint8Array and hex string formats are provided.

---

`19-28`: **Excellent verification step to ensure implementation correctness**

The verification step ensures that both WASM and Viem implementations produce the same hash result, which is crucial for confirming correctness before benchmarking performance.

---

`29-54`: **Well-structured benchmarks for different data sizes**

The benchmarks for small, medium, and large data sizes provide good coverage for performance testing across different input magnitudes.

---

`56-72`: **Comprehensive utility function benchmarks**

The inclusion of benchmarks for the conversion utilities (bytesToHex and hexToBytes) is thorough and provides valuable performance data beyond just the core hashing function.

</details>
<details>
<summary>src/final.bench.js (5)</summary>

`1-8`: **Properly structured benchmark with WASM initialization**

The file is well-organized with proper imports and async initialization of the WASM module.

---

`14-23`: **Comprehensive verification across all three implementations**

Excellent verification step that ensures all three implementations (Viem, WASM, and WASM Stdlib) produce the same hash result before proceeding with benchmarks.

---

`24-38`: **Well-structured individual benchmarks**

The individual operation benchmarks are well-structured and clearly labeled for each implementation.

---

`47-61`: **Good large data benchmarks across implementations**

The large data benchmarks are well-structured and provide insights into how each implementation performs with larger inputs.

---

`62-79`: **Well-designed batch operation benchmarks**

The batch operation benchmarks effectively simulate real-world scenarios where multiple hashes need to be computed in succession.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-11T04:18:46Z

Review comments:
diff_hunk: @@ -0,0 +1,70 @@
+import { bench, describe } from 'vitest';
+import { bytesToHex, hexToBytes } from 'viem/utils';
+import { initWasm, bytesToHex as wasmBytesToHex, hexToBytes as wasmHexToBytes } from './wasm-loader.js';
+
+describe('Conversion Functions Benchmark', async () => {
+  // Initialize WASM module before running benchmarks
+  const wasmInstance = await initWasm();
+
path: src/conversion.bench.js
user: login: coderabbitai[bot]
body: _🛠️ Refactor suggestion_

**Avoid `async` callbacks inside `describe` – use `beforeAll` for setup instead**

Vitest will happily accept an `async` callback, but any un-handled rejection inside the callback will be swallowed and reported as “no tests found”.  A safer pattern is to keep the `describe` callback synchronous and move the WASM initialisation to `beforeAll` / `beforeEach`, e.g.:

```diff
-describe('Conversion Functions Benchmark', async () => {
-  const wasmInstance = await initWasm();
+describe('Conversion Functions Benchmark', () => {
+  let wasmInstance;
+  beforeAll(async () => {
+    wasmInstance = await initWasm();
+  });
```

This also guarantees the instance is ready before any `bench` is scheduled.  



<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

`````suggestion
describe('Conversion Functions Benchmark', () => {
  // Initialize WASM module before running benchmarks
  let wasmInstance;
  beforeAll(async () => {
    wasmInstance = await initWasm();
  });
`````

</details>

<!-- suggestion_end -->

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-05-11T04:18:45Z
author_association: CONTRIBUTOR
diff_hunk: @@ -31,4 +31,110 @@ pub fn main() void {
     if (!is_wasm) {
         _ = runEvm();
     }
-}
\ No newline at end of file
+}
+
+// Helper function to convert a hex character to its numerical value
+fn hexCharToValue(c: u8) ?u8 {
+    return switch (c) {
+        '0'...'9' => c - '0',
+        'a'...'f' => c - 'a' + 10,
+        'A'...'F' => c - 'A' + 10,
+        else => null, // Invalid hex char
+    };
+}
+
+// WASM-compatible keccak256 function with bytes input/output
+export fn zig_keccak256(input_ptr: [*]const u8, input_len: usize, output_ptr: [*]u8) void {
+    const input = input_ptr[0..input_len];
+    const output = output_ptr[0..32];
+    std.crypto.hash.sha3.Keccak256.hash(input, output, .{});
+}
+
+// These functions use standard library implementions where possible
+export fn zig_hexToBytes(hex_ptr: [*]const u8, hex_len: usize, output_ptr: [*]u8) usize {
+    // Skip "0x" prefix if present
+    var start_idx: usize = 0;
+    if (hex_len >= 2 and hex_ptr[0] == '0' and (hex_ptr[1] == 'x' or hex_ptr[1] == 'X')) {
+        start_idx = 2;
+    }
+
+    // Get the hex string (without prefix)
+    const hex_string = hex_ptr[start_idx..hex_len];
+
+    // Calculate output buffer size (each pair of hex chars = 1 byte)
+    const hex_len_adjusted = hex_len - start_idx;
+    const out_len = (hex_len_adjusted + 1) / 2; // Handle odd length
+
+    // Create output slice for std.fmt.hexToBytes
+    const out_slice = output_ptr[0..out_len];
+
+    // Manual conversion using std functions for greater compatibility
+    var out_idx: usize = 0;
+    var i: usize = 0;
+
+    // Handle odd number of hex digits
+    if (hex_len_adjusted % 2 != 0) {
+        if (std.fmt.parseInt(u8, hex_string[0..1], 16)) |val| {
+            out_slice[out_idx] = val;
+            out_idx += 1;
+            i += 1;
+        } else |_| {
+            // Handle error by skipping this char
+        }
+    }
+
+    // Process the rest of the pairs
+    while (i < hex_len_adjusted) : (i += 2) {
+        if (i + 1 >= hex_len_adjusted) {
+            break;
+        }
+
+        if (std.fmt.parseInt(u8, hex_string[i .. i + 2], 16)) |val| {
+            out_slice[out_idx] = val;
+            out_idx += 1;
+        } else |_| {
+            // Handle error by skipping this pair
+        }
+    }
+
+    return out_idx;
+}
+
+// WASM-compatible bytesToHex function using std fmt utilities
+export fn zig_bytesToHex(bytes_ptr: [*]const u8, bytes_len: usize, output_ptr: [*]u8) usize {
+    // Write the 0x prefix
+    output_ptr[0] = '0';
+    output_ptr[1] = 'x';
+
+    // Create a slice for the output (excluding prefix)
+    const hex_out = output_ptr[2 .. 2 + bytes_len * 2];
+    const bytes = bytes_ptr[0..bytes_len];
+
+    // Manual conversion using std.fmt.digitToChar
+    for (bytes, 0..) |byte, i| {
+        const hex_idx = i * 2;
+        const hi_nib = @as(u4, @truncate(byte >> 4));
+        const lo_nib = @as(u4, @truncate(byte & 0x0F));
+
+        hex_out[hex_idx] = std.fmt.digitToChar(hi_nib, std.fmt.Case.lower);
+        hex_out[hex_idx + 1] = std.fmt.digitToChar(lo_nib, std.fmt.Case.lower);
+    }
+
+    return 2 + bytes_len * 2;
+}
+
+// WASM-compatible keccak256 function that takes a hex string and returns a hex string
+// using stdlib hex conversion
+export fn zig_keccak256_hex(hex_ptr: [*]const u8, hex_len: usize, output_ptr: [*]u8) usize {
+    var binary_buffer: [1024]u8 = undefined; // Buffer for binary data converted from hex
+
+    // Convert hex to bytes using stdlib
+    const binary_len = zig_hexToBytes(hex_ptr, hex_len, &binary_buffer);
+
+    // Compute keccak256 hash
+    var hash: [32]u8 = undefined;
+    std.crypto.hash.sha3.Keccak256.hash(binary_buffer[0..binary_len], &hash, .{});
+
+    // Convert hash to hex string using stdlib
+    return zig_bytesToHex(&hash, 32, output_ptr);
+}
path: src/root.zig
user: login: coderabbitai[bot]
body: _⚠️ Potential issue_

**Fixed 1 KiB buffer may overflow for inputs > 2046 hex chars**

`zig_keccak256_hex` allocates `var binary_buffer: [1024]u8`, then writes as many bytes as `zig_hexToBytes` returns.  A 4 KiB hex string (≈2 KiB bytes) will corrupt the stack.

```diff
-var binary_buffer: [1024]u8 = undefined;
-const binary_len = zig_hexToBytes(hex_ptr, hex_len, &binary_buffer);
+const max_bytes = hex_len / 2 + 1;
+var allocator = std.heap.page_allocator;
+const binary_buffer = try allocator.alloc(u8, max_bytes);
+defer allocator.free(binary_buffer);
+const binary_len = zig_hexToBytes(hex_ptr, hex_len, binary_buffer.ptr);
```

Alternatively, document the 2 KiB limit and guard:

```zig
if (hex_len > 2046) return 0; // signal overflow
```

Unchecked stack writes in WASM exhibit as silent data corruption—best to fix now.

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-05-11T04:18:45Z
author_association: CONTRIBUTOR
diff_hunk: @@ -31,4 +31,110 @@ pub fn main() void {
     if (!is_wasm) {
         _ = runEvm();
     }
-}
\ No newline at end of file
+}
+
+// Helper function to convert a hex character to its numerical value
+fn hexCharToValue(c: u8) ?u8 {
+    return switch (c) {
+        '0'...'9' => c - '0',
+        'a'...'f' => c - 'a' + 10,
+        'A'...'F' => c - 'A' + 10,
+        else => null, // Invalid hex char
+    };
+}
+
+// WASM-compatible keccak256 function with bytes input/output
+export fn zig_keccak256(input_ptr: [*]const u8, input_len: usize, output_ptr: [*]u8) void {
+    const input = input_ptr[0..input_len];
+    const output = output_ptr[0..32];
+    std.crypto.hash.sha3.Keccak256.hash(input, output, .{});
+}
+
+// These functions use standard library implementions where possible
+export fn zig_hexToBytes(hex_ptr: [*]const u8, hex_len: usize, output_ptr: [*]u8) usize {
+    // Skip "0x" prefix if present
+    var start_idx: usize = 0;
+    if (hex_len >= 2 and hex_ptr[0] == '0' and (hex_ptr[1] == 'x' or hex_ptr[1] == 'X')) {
+        start_idx = 2;
+    }
+
+    // Get the hex string (without prefix)
+    const hex_string = hex_ptr[start_idx..hex_len];
+
+    // Calculate output buffer size (each pair of hex chars = 1 byte)
+    const hex_len_adjusted = hex_len - start_idx;
+    const out_len = (hex_len_adjusted + 1) / 2; // Handle odd length
+
+    // Create output slice for std.fmt.hexToBytes
+    const out_slice = output_ptr[0..out_len];
+
+    // Manual conversion using std functions for greater compatibility
+    var out_idx: usize = 0;
+    var i: usize = 0;
+
+    // Handle odd number of hex digits
+    if (hex_len_adjusted % 2 != 0) {
+        if (std.fmt.parseInt(u8, hex_string[0..1], 16)) |val| {
+            out_slice[out_idx] = val;
+            out_idx += 1;
+            i += 1;
+        } else |_| {
+            // Handle error by skipping this char
+        }
+    }
+
+    // Process the rest of the pairs
+    while (i < hex_len_adjusted) : (i += 2) {
+        if (i + 1 >= hex_len_adjusted) {
+            break;
+        }
+
+        if (std.fmt.parseInt(u8, hex_string[i .. i + 2], 16)) |val| {
+            out_slice[out_idx] = val;
+            out_idx += 1;
+        } else |_| {
+            // Handle error by skipping this pair
+        }
+    }
+
+    return out_idx;
path: src/root.zig
user: login: coderabbitai[bot]
body: _⚠️ Potential issue_

**`zig_hexToBytes` lacks bounds checks and does silent error swallowing**

1. The caller must pre-allocate an output buffer large enough; otherwise writes run past `output_ptr`.
2. Invalid hex pairs are silently skipped, producing unpredictable output lengths.

Consider:

```diff
-const out_len = (hex_len_adjusted + 1) / 2;
+const out_len_needed = (hex_len_adjusted + 1) / 2;
+if (out_len_needed > bytes_len_available) {
+    return 0; // or signal error
+}
```

…and returning `error!usize` so JavaScript can detect malformed input instead of guessing.  



> Committable suggestion skipped: line range outside the PR's diff.

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-05-11T04:18:45Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,167 @@
+import { bench, describe } from "vitest";
+import {
+  keccak256 as viemKeccak256,
+  hexToBytes as viemHexToBytes,
+  bytesToHex as viemBytesToHex,
+} from "viem/utils";
+import { instantiateZigModule } from "./wasm-loader.js";
+import fs from "fs";
+import path from "path";
+import { fileURLToPath } from "url";
+
+describe("Comprehensive Implementation Comparison", async () => {
+  const __dirname = path.dirname(fileURLToPath(import.meta.url));
+  const wasmPath = path.resolve(__dirname, "../dist/zigevm.wasm");
+  const wasmBuffer = fs.readFileSync(wasmPath);
+
+  // Initialize WASM instance with all implementation methods
+  const wasmModule = await instantiateZigModule(wasmBuffer);
+
path: src/comparison.bench.js
user: login: coderabbitai[bot]
body: _🛠️ Refactor suggestion_

**Avoid `async` callbacks inside `describe`; move async setup to `beforeAll`**

Vitest does **not** await the promise returned by an `async` `describe` callback, so your benchmark definitions may be registered *after* the runner starts executing other suites, leading to race-conditions or missed benches.

```diff
-describe("Comprehensive Implementation Comparison", async () => {
-  const __dirname = ...
-  ...
-  const wasmModule = await instantiateZigModule(wasmBuffer);
-  ...
-});
+describe("Comprehensive Implementation Comparison", () => {
+  let wasmModule;
+
+  beforeAll(async () => {
+    const __dirname = path.dirname(fileURLToPath(import.meta.url));
+    const wasmPath   = path.resolve(__dirname, "../dist/zigevm.wasm");
+    const wasmBuffer = fs.readFileSync(wasmPath);
+    wasmModule       = await instantiateZigModule(wasmBuffer);
+    console.log("Available WASM exports:", Object.keys(wasmModule));
+  });
+
+  // ⬇️  keep the bench definitions here – they can safely reference `wasmModule`
+});
```

This keeps the suite deterministic and aligns with Vitest’s recommended lifecycle hooks.  



<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

`````suggestion
describe("Comprehensive Implementation Comparison", () => {
  let wasmModule;

  beforeAll(async () => {
    const __dirname  = path.dirname(fileURLToPath(import.meta.url));
    const wasmPath   = path.resolve(__dirname, "../dist/zigevm.wasm");
    const wasmBuffer = fs.readFileSync(wasmPath);
    wasmModule       = await instantiateZigModule(wasmBuffer);
    console.log("Available WASM exports:", Object.keys(wasmModule));
  });

  // ⬇️  keep the bench definitions here – they can safely reference `wasmModule`
});
`````

</details>

<!-- suggestion_end -->

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-05-11T04:18:46Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,453 @@
+import fs from 'fs';
+import { dirname, resolve } from 'path';
+import { fileURLToPath } from 'url';
+
+const __dirname = dirname(fileURLToPath(import.meta.url));
+const wasmPath = resolve(__dirname, '../dist/zigevm.wasm');
+const wasmBuffer = fs.readFileSync(wasmPath);
+
+/**
+ * Initializes the WebAssembly module
+ * @returns {Promise<WebAssembly.Instance>} The WebAssembly instance
+ */
+export async function initWasm() {
+  const { instance } = await WebAssembly.instantiate(wasmBuffer);
+
+  // Debug: Log all available exports
+  console.log('WASM exports:', Object.keys(instance.exports));
+
+  return instance;
+}
+
+/**
+ * Instantiates a ZIG WebAssembly module with a provided buffer
+ * @param {ArrayBuffer} wasmBuffer - WebAssembly binary data
+ * @returns {Promise<{keccak256: Function, hexToBytes: Function, bytesToHex: Function, hexToBytesStdlib: Function, bytesToHexStdlib: Function, keccak256Stdlib: Function}>} Module with exposed functions
+ */
+export async function instantiateZigModule(wasmBuffer) {
+  const { instance } = await WebAssembly.instantiate(wasmBuffer);
+
+  return {
+    keccak256: (input) => keccak256(instance, input),
+    hexToBytes: (hexStr) => hexToBytes(instance, hexStr),
+    bytesToHex: (bytes) => bytesToHex(instance, bytes),
+    hexToBytesStdlib: (hexStr) => hexToBytesStdlib(instance, hexStr),
+    bytesToHexStdlib: (bytes) => bytesToHexStdlib(instance, bytes),
+    keccak256Stdlib: (input) => keccak256Stdlib(instance, input),
+
+    // Added old implementations
+    hexToBytesOld: (hexStr) => {
+      const memory = instance.exports.memory;
+      const encoder = new TextEncoder();
+      const hexBytes = encoder.encode(hexStr);
+
+      const inputLen = hexBytes.length;
+      const outputLen = Math.ceil(inputLen / 2);
+      const memoryNeeded = inputLen + outputLen;
+
+      const currentMemoryPages = memory.buffer.byteLength / (64 * 1024);
+      const pagesNeeded = Math.ceil(memoryNeeded / (64 * 1024));
+
+      if (pagesNeeded > currentMemoryPages) {
+        memory.grow(pagesNeeded - currentMemoryPages);
+      }
+
+      const memoryArray = new Uint8Array(memory.buffer);
+      const inputPtr = 0;
+      memoryArray.set(hexBytes, inputPtr);
+      const outputPtr = inputLen;
+
+      const bytesWritten = instance.exports.zig_hexToBytes_old(inputPtr, inputLen, outputPtr);
+      return new Uint8Array(memoryArray.buffer, outputPtr, bytesWritten);
+    },
+
+    bytesToHexOld: (bytes) => {
+      const memory = instance.exports.memory;
+      const inputLen = bytes.length;
+      const outputLen = 2 + (inputLen * 2);
+      const memoryNeeded = inputLen + outputLen;
+
+      const currentMemoryPages = memory.buffer.byteLength / (64 * 1024);
+      const pagesNeeded = Math.ceil(memoryNeeded / (64 * 1024));
+
+      if (pagesNeeded > currentMemoryPages) {
+        memory.grow(pagesNeeded - currentMemoryPages);
+      }
+
+      const memoryArray = new Uint8Array(memory.buffer);
+      const inputPtr = 0;
+      memoryArray.set(bytes, inputPtr);
+      const outputPtr = inputLen;
+
+      const hexLen = instance.exports.zig_bytesToHex_old(inputPtr, inputLen, outputPtr);
+      const decoder = new TextDecoder();
+      return decoder.decode(new Uint8Array(memory.buffer, outputPtr, hexLen));
+    },
+
+    keccak256Old: (input) => {
+      if (typeof input === 'string') {
+        const encoder = new TextEncoder();
+        const hexBytes = encoder.encode(input);
+
+        const memory = instance.exports.memory;
+        const inputLen = hexBytes.length;
+        const outputLen = 2 + (32 * 2);
+        const memoryNeeded = inputLen + outputLen;
+
+        const currentMemoryPages = memory.buffer.byteLength / (64 * 1024);
+        const pagesNeeded = Math.ceil(memoryNeeded / (64 * 1024));
+
+        if (pagesNeeded > currentMemoryPages) {
+          memory.grow(pagesNeeded - currentMemoryPages);
+        }
+
+        const memoryArray = new Uint8Array(memory.buffer);
+        const inputPtr = 0;
+        memoryArray.set(hexBytes, inputPtr);
+        const outputPtr = inputLen;
+
+        const hexLen = instance.exports.zig_keccak256_hex_old(inputPtr, inputLen, outputPtr);
+        const decoder = new TextDecoder();
+        return decoder.decode(new Uint8Array(memory.buffer, outputPtr, hexLen));
+      } else {
+        const hashBytes = keccak256Bytes(instance, input);
+        const bytesToHexFn = instance.bytesToHexOld || bytesToHexOld;
+        return bytesToHexFn(instance, hashBytes);
+      }
path: src/wasm-loader.js
user: login: coderabbitai[bot]
body: _⚠️ Potential issue_

**`bytesToHexOld` is out of scope – this will throw at runtime**

Inside `keccak256Old`’s Uint8Array branch you attempt to fall back to `bytesToHexOld`, but that identifier is **not** defined in the current lexical scope (properties on the returned object don’t create variables). At runtime this path triggers a `ReferenceError`.

```diff
-        const hashBytes = keccak256Bytes(instance, input);
-        const bytesToHexFn = instance.bytesToHexOld || bytesToHexOld;
-        return bytesToHexFn(instance, hashBytes);
+        const hashBytes = keccak256Bytes(instance, input);
+        return bytesToHexOld(instance, hashBytes);
```

Alternatively, lift the helper outside the object literal or reference it via `module.bytesToHexOld` once the module is constructed.




> Committable suggestion skipped: line range outside the PR's diff.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 Biome (1.9.4)</summary>

[error] 112-116: This else clause can be omitted because previous branches break early.

Unsafe fix: Omit the else clause.


(lint/style/noUselessElse)

</details>

</details>

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-05-11T04:18:46Z
author_association: CONTRIBUTOR

PR comments:
user: login: vercel[bot]
created_at: 2025-05-11T04:10:50Z
body: [vc]: #OT2ntkBTmBSgUlnHgNdCf0FClwFyjiByeWtl0vhP8Vk=:eyJpc01vbm9yZXBvIjp0cnVlLCJ0eXBlIjoiZ2l0aHViIiwicHJvamVjdHMiOlt7Im5hbWUiOiJub2RlIiwicm9vdERpcmVjdG9yeSI6ImRvY3Mvbm9kZSIsImluc3BlY3RvclVybCI6Imh0dHBzOi8vdmVyY2VsLmNvbS9ldm10cy9ub2RlL0NrenRYVVBtY1UzU0RQczlKZkZKbk5EM29uUEYiLCJwcmV2aWV3VXJsIjoibm9kZS1naXQtYmVuY2htYXJraW5nLWtlY2Nhay1ldm10cy52ZXJjZWwuYXBwIiwibmV4dENvbW1pdFN0YXR1cyI6IkRFUExPWUVEIn0seyJuYW1lIjoidGV2bS1tb25vcmVwby10ZXZtIiwicm9vdERpcmVjdG9yeSI6bnVsbCwiaW5zcGVjdG9yVXJsIjoiaHR0cHM6Ly92ZXJjZWwuY29tL2V2bXRzL3Rldm0tbW9ub3JlcG8tdGV2bS9mSkVXczlIQjNRZDZhblBWbnNSeFM4cEVZOTlrIiwibmV4dENvbW1pdFN0YXR1cyI6IklHTk9SRUQifSx7Im5hbWUiOiJ0ZXZtLW1vbm9yZXBvLWFwcCIsInJvb3REaXJlY3RvcnkiOiJkb2NzL25vZGUiLCJpbnNwZWN0b3JVcmwiOiJodHRwczovL3ZlcmNlbC5jb20vZXZtdHMvdGV2bS1tb25vcmVwby1hcHAvNkt0WVNoejJZZTU1aTJzQWlOejczSnBVc2pSbSIsInByZXZpZXdVcmwiOiJ0ZXZtLW1vbm9yZXBvLWFwcC1naXQtYmVuY2htYXJraW5nLWtlY2Nhay1ldm10cy52ZXJjZWwuYXBwIiwibmV4dENvbW1pdFN0YXR1cyI6IkRFUExPWUVEIn1dfQ==
**The latest updates on your projects**. Learn more about [Vercel for Git ↗︎](https://vercel.link/github-learn-more)

| Name | Status | Preview | Updated (UTC) |
| :--- | :----- | :------ | :------ |
| **node** | ✅ Ready ([Inspect](https://vercel.com/evmts/node/CkztXUPmcU3SDPs9JfFJnND3onPF)) | [Visit Preview](https://node-git-benchmarking-keccak-evmts.vercel.app) | May 11, 2025 4:19am |
| **tevm-monorepo-app** | ✅ Ready ([Inspect](https://vercel.com/evmts/tevm-monorepo-app/6KtYShz2Ye55i2sAiNz73JpUsjRm)) | [Visit Preview](https://tevm-monorepo-app-git-benchmarking-keccak-evmts.vercel.app) | May 11, 2025 4:19am |

<details><summary>1 Skipped Deployment</summary>

| Name | Status | Preview | Updated (UTC) |
| :--- | :----- | :------ | :------ |
| **tevm-monorepo-tevm** | ⬜️ Ignored ([Inspect](https://vercel.com/evmts/tevm-monorepo-tevm/fJEWs9HB3Qd6anPVnsRxS8pEY99k)) |  | May 11, 2025 4:19am |
</details>




author_association: NONE
user: login: changeset-bot[bot]
created_at: 2025-05-11T04:10:50Z
body: ###  ⚠️  No Changeset found

Latest commit: dad7ac9a7fe2a1b7ffddb8eb74770c032c9afe04

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. **If these changes should result in a version bump, you need to add a changeset.**

<details><summary>This PR includes no changesets</summary>

  When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

</details>

[Click here to learn what changesets are, and how to add one](https://github.com/changesets/changesets/blob/main/docs/adding-a-changeset.md).

[Click here if you're a maintainer who wants to add a changeset to this PR](https://github.com/evmts/tevm-monorepo/new/benchmarking-keccak?filename=.changeset/big-trainers-rhyme.md&value=---%0A%22%40tevm%2Fzig%22%3A%20patch%0A---%0A%0Afeat%3A%20create%20benchmarking%20boilerplate%0A)


author_association: NONE
user: login: coderabbitai[bot]
created_at: 2025-05-11T04:10:54Z
body: <!-- This is an auto-generated comment: summarize by coderabbit.ai -->
<!-- walkthrough_start -->

## Walkthrough

This update introduces a comprehensive Zig/WebAssembly (WASM) cryptography and encoding toolkit within the project. It adds new Zig functions for keccak256 hashing and hex/byte conversions, exposes them via WASM modules, and provides JavaScript loaders to interact with these modules. Extensive Vitest-based benchmarks compare WASM and JavaScript implementations. Build scripts and workspace configuration are also updated.

## Changes

| File(s)                                                                                  | Change Summary                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
|------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `.gitignore`                                                                             | Added rule to ignore all `settings.local.json` files within any `.claude` directory at any depth.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| `package.json`                                                                           | Modified the `build:wasm` script to ensure the output directory exists and copies the WASM artifact from the Zig cache to a distribution folder after building.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| `pnpm-workspace.yaml`                                                                    | Added the `src` directory to the workspace packages list for pnpm management.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| `src/build-stdlib.sh`                                                                    | New shell script to build a Zig WASM binary (`stdlib3.zig`) using `zig build-exe`, outputting `stdlib.wasm` to the `dist` directory, with confirmation and file size logging.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| `src/comparison.bench.js`<br>`src/conversion.bench.js`<br>`src/final.bench.js`<br>`src/keccak.bench.js`<br>`src/stdlib.bench.js` | Added multiple Vitest benchmark suites to compare WASM and JavaScript implementations of keccak256 hashing and hex/byte conversion functions across various input sizes and batch scenarios. Each suite initializes WASM modules, verifies correctness, and benchmarks performance.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| `src/package.json`                                                                      | New `package.json` for `@tevm/zig` package with metadata, scripts for testing and benchmarking, and devDependencies on `viem` and `vitest`.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| `src/root.zig`                                                                          | Added and exported new Zig functions for WASM: `zig_keccak256`, `zig_hexToBytes`, `zig_bytesToHex`, and `zig_keccak256_hex`, implementing hashing and hex/byte conversions.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| `src/stdlib-loader.js`                                                                  | New JavaScript module to load and interact with the WASM module, providing wrappers for `hexToBytes`, `bytesToHex`, and `keccak256`, handling memory management and input/output conversions.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| `src/vitest.config.js`                                                                  | New Vitest configuration file specifying test patterns, node environment, global variables, and disabled threading for benchmarks.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| `src/wasm-loader.js`                                                                    | New JavaScript module to load and instantiate the Zig WASM module, exposing cryptographic and encoding utilities, both modern and legacy, with careful WASM memory management and utility functions for use in tests and benchmarks.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |

## Sequence Diagram(s)

```mermaid
sequenceDiagram
    participant JS as JavaScript (Test/Benchmark)
    participant Loader as WASM Loader (wasm-loader.js / stdlib-loader.js)
    participant WASM as Zig WASM Module (root.zig)
    JS->>Loader: initWasm()
    Loader->>WASM: Instantiate WASM module
    Loader-->>JS: Return WASM instance

    JS->>Loader: keccak256(instance, input)
    alt input is hex string
        Loader->>WASM: zig_keccak256_hex(hex_ptr, hex_len, output_ptr)
        WASM-->>Loader: Hash as hex string in WASM memory
    else input is byte array
        Loader->>WASM: zig_keccak256(input_ptr, input_len, output_ptr)
        WASM-->>Loader: Hash as bytes in WASM memory
        Loader->>WASM: zig_bytesToHex(bytes_ptr, bytes_len, output_ptr)
        WASM-->>Loader: Hash as hex string in WASM memory
    end
    Loader-->>JS: Return hash as hex string

    JS->>Loader: hexToBytes(instance, hexString)
    Loader->>WASM: zig_hexToBytes(hex_ptr, hex_len, output_ptr)
    WASM-->>Loader: Output bytes in WASM memory
    Loader-->>JS: Return Uint8Array

    JS->>Loader: bytesToHex(instance, bytes)
    Loader->>WASM: zig_bytesToHex(bytes_ptr, bytes_len, output_ptr)
    WASM-->>Loader: Output hex string in WASM memory
    Loader-->>JS: Return string
```

## Possibly related PRs

- **evmts/tevm-monorepo#1653**: Adds build scripts, ignore patterns, and workspace config related to Zig and WASM build outputs, closely related to this PR's Zig/WASM integration and build setup.

## Poem

> In the warren, code does hum,  
> Zig and WASM—what a scrum!  
> Hex and bytes now swiftly dance,  
> Benchmarks run, the hares advance.  
> With hashing swift as bunny feet,  
> This toolkit’s hop is hard to beat!  
> 🐇✨

<!-- walkthrough_end -->
<!-- internal state start -->


<!-- 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 -->

<!-- internal state end -->
<!-- finishing_touch_checkbox_start -->

<details open="true">
<summary>✨ Finishing Touches</summary>

- [ ] <!-- {"checkboxId": "7962f53c-55bc-4827-bfbf-6a18da830691"} --> 📝 Generate Docstrings

</details>

<!-- finishing_touch_checkbox_end -->
<!-- tips_start -->

---

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

<details>
<summary>❤️ Share</summary>

- [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai)
- [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai)
- [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai)
- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code)

</details>

<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=evmts/tevm-monorepo&utm_content=1654):

- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
  - `I pushed a fix in commit <commit_id>, please review it.`
  - `Generate unit testing code for this file.`
  - `Open a follow-up GitHub issue for this discussion.`
- Files and specific lines of code (under the "Files changed" tab): Tag `@coderabbitai` in a new review comment at the desired location with your query. Examples:
  - `@coderabbitai generate unit testing code for this file.`
  -	`@coderabbitai modularize this function.`
- PR comments: Tag `@coderabbitai` in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
  - `@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.`
  - `@coderabbitai read src/utils.ts and generate unit testing code.`
  - `@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.`
  - `@coderabbitai help me debug CodeRabbit configuration file.`

### Support

Need help? Create a ticket on our [support page](https://www.coderabbit.ai/contact-us/support) for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

### CodeRabbit Commands (Invoked using PR comments)

- `@coderabbitai pause` to pause the reviews on a PR.
- `@coderabbitai resume` to resume the paused reviews.
- `@coderabbitai review` to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
- `@coderabbitai full review` to do a full review from scratch and review all the files again.
- `@coderabbitai summary` to regenerate the summary of the PR.
- `@coderabbitai generate docstrings` to [generate docstrings](https://docs.coderabbit.ai/finishing-touches/docstrings) for this PR.
- `@coderabbitai generate sequence diagram` to generate a sequence diagram of the changes in this PR.
- `@coderabbitai resolve` resolve all the CodeRabbit review comments.
- `@coderabbitai configuration` to show the current CodeRabbit configuration for the repository.
- `@coderabbitai help` to get help.

### Other keywords and placeholders

- Add `@coderabbitai ignore` anywhere in the PR description to prevent this PR from being reviewed.
- Add `@coderabbitai summary` to generate the high-level summary at a specific location in the PR description.
- Add `@coderabbitai` anywhere in the PR title to generate the title automatically.

### CodeRabbit Configuration File (`.coderabbit.yaml`)

- You can programmatically configure CodeRabbit by adding a `.coderabbit.yaml` file to the root of your repository.
- Please see the [configuration documentation](https://docs.coderabbit.ai/guides/configure-coderabbit) for more information.
- If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: `# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json`

### Documentation and Community

- Visit our [Documentation](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->
author_association: CONTRIBUTOR
user: login: roninjin10
created_at: 2025-05-11T04:11:18Z
body: * **#1655** <a href="https://app.graphite.dev/github/pr/evmts/tevm-monorepo/1655?utm_source=stack-comment-icon" target="_blank"><img src="https://static.graphite.dev/graphite-32x32-black.png" alt="Graphite" width="10px" height="10px"/></a>
* **#1654** <a href="https://app.graphite.dev/github/pr/evmts/tevm-monorepo/1654?utm_source=stack-comment-icon" target="_blank"><img src="https://static.graphite.dev/graphite-32x32-black.png" alt="Graphite" width="10px" height="10px"/></a> 👈 <a href="https://app.graphite.dev/github/pr/evmts/tevm-monorepo/1654?utm_source=stack-comment-view-in-graphite" target="_blank">(View in Graphite)</a>
* `main`


<h2></h2>

This stack of pull requests is managed by <a href="https://graphite.dev?utm-source=stack-comment"><b>Graphite</b></a>. Learn more about <a href="https://stacking.dev/?utm_source=stack-comment">stacking</a>.
<!-- Current dependencies on/for this PR: -->
author_association: COLLABORATOR