Skip to content

evmts/guillotine

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

βš”οΈ Guillotine (Pre-Alpha)

CI Status Telegram Ask DeepWiki

Guillotine Logo

A very fast EVM written in Zig


🧭 Overview

Guillotine is a new EVM implementation built in Zig by @FUCORY, the creator of Tevm. It’s designed for:

  • πŸ•ΈοΈ Browser-readiness
  • ⚑ Extreme speed
  • πŸ“¦ Minimal bundle size
  • πŸ’„ elegance and modularity

Despite its early status, it's already very fast and vrey tiny.


🚧 Development Status

We’re wrapping up the Alpha release. We will be testing vs all ethereum hardforks and doing extensive benchmarking. Expect benchmarks and bundle size reports within a week. Stay tuned!


πŸ“Š Benchmarks & Bundle Size

πŸ’₯ Official benchmarks and bundle size reports will be included with the Alpha drop. You can expect:

  • ⏱️ Best in class Performance
  • πŸͺΆ Significant bundle size reduction

Compared to other EVM implementations


🧩 Subpackages

Guillotine is a modular Ethereum stack in Zig:

  • primitives β€” Low-level Ethereum utilities (like Alloy or Ethers.js in Zig)
  • compilers β€” Zig bindings for the Foundry compiler (Rust)
  • crypto β€” πŸ§ͺ Zig-based crypto lib (unaudited)
  • devtool (WIP) β€” Native app (Zig + Solid.js) β€” a future local-first Tenderly
  • provider (WIP) β€” HTTP-based Ethereum provider

πŸ” Relationship to Tevm

Once stable, Guillotine’s WASM build will replace the current JavaScript EVM in Tevm. Upgrades include:

  • πŸš€ Up to 1000x performance boost
  • πŸ“‰ 300KB (75%) bundle size reduction
  • πŸ”§ Foundry-compatible compiler support
  • 🧱 Cross-language bindings (primitives, compiler, provider)

It also unlocks Solidity and Vyper compatibility for the tevm compiler.


✨ Key Features

  • 🏎️ Fast & Small β€” Zig = uncompromising performance and minimal footprint
  • 🧩 C FFI Compatible β€” Use it from Python, Rust, Go, Swift, etc.
  • πŸ–₯️ Multi-target builds β€” Native + WASM (x86 / ARM)
  • πŸ—οΈ Builder pattern β€” Intuitive API for managing VM execution
  • πŸ§ͺ Reliable β€” Unit, integration, fuzz, E2E, and benchmark test suite

πŸ“¦ Installation

πŸ”§ Zig Package Manager

zig fetch --save git+https://github.com/evmts/Guillotine#main

Add to build.zig.zon:

.dependencies = .{
    .guillotine = .{
        .url = "git+https://github.com/evmts/Guillotine#main",
        .hash = "<hash from zig fetch>",
    },
},

βœ… Prerequisites

  • πŸ› οΈ Zig v0.14.1 or later
  • πŸ¦€ Rust toolchain β€” for BN254 native precompiles (will be replaced with Zig #1)

⚑ Quick Start

Example: Basic EVM Execution

const std = @import("std");
const Evm = @import("guillotine").Evm;
const primitives = @import("guillotine").primitives;

pub fn main() !void {
    const allocator = std.heap.page_allocator;

    var memory_db = Evm.MemoryDatabase.init(allocator);
    defer memory_db.deinit();

    const db_interface = memory_db.to_database_interface();
    var vm = try Evm.Evm.init(allocator, db_interface);
    defer vm.deinit();

    const bytecode = [_]u8{
        0x60, 0x2A, 0x60, 0x00, 0x52,
        0x60, 0x20, 0x60, 0x00, 0xF3,
    };

    const contract_address = primitives.Address.from_u256(0x1234);
    var contract = Evm.Contract.init_at_address(
        contract_address,
        contract_address,
        0,
        100_000,
        &bytecode,
        &[_]u8{},
        false,
    );
    defer contract.deinit(allocator, null);

    try vm.state.set_code(contract_address, &bytecode);

    const result = try vm.interpret(&contract, &[_]u8{});
    defer if (result.output) |output| allocator.free(output);

    std.debug.print("Execution status: {}\n", .{result.status});
    if (result.output) |output| {
        std.debug.print("Return value: {}\n", .{
            std.mem.readInt(u256, output[0..32], .big)
        });
    }
}

🧱 Design Principles

  1. 🧼 Zero Allocation Philosophy – Allocates once, avoids reallocations
  2. πŸ” Explicit Error Handling – All errors are typed and recoverable
  3. 🧩 Modular Boundaries – Clear interfaces between components
  4. πŸ§ͺ Test Everything – Coverage across all levels
  5. πŸ› οΈ Optimized for Size & Speed – comptime wherever it counts

🧬 Precompiled Contracts

Address Name Native WASM Implementation
0x01 ECRECOVER βœ… βœ… Pure Zig
0x02 SHA256 βœ… βœ… Pure Zig
0x03 RIPEMD160 βœ… βœ… Pure Zig
0x04 IDENTITY βœ… βœ… Pure Zig
0x05 MODEXP βœ… βœ… Pure Zig
0x06 ECADD (BN254) βœ… βœ… Pure Zig
0x07 ECMUL (BN254) βœ… ⚠️ Rust (to be replaced)
0x08 ECPAIRING (BN254) βœ… ⚠️ Rust (partial)
0x09 BLAKE2F βœ… βœ… Pure Zig
0x0a KZG_POINT_EVALUATION βœ… βœ… C-KZG-4844

πŸ§ͺ Crypto implementations live in src/crypto. ⚠️ Some are unaudited β€” not production-ready.


🀝 Contributing

We welcome contributions of all kinds!

See our Contributing Guide to get started.

πŸ“š Library Integration

For external projects that want to integrate Guillotine as a library dependency.

⚠️ Note: The requirements below are temporary and will be removed in upcoming releases as we migrate to pure Zig implementations.

Required Dependencies (Temporary)

BN254 Rust Wrapper

Guillotine currently uses a Rust-based BN254 elliptic curve implementation for production-grade scalar multiplication and pairing operations:

  • Location: src/bn254_wrapper/
  • Dependencies: arkworks ecosystem (ark-bn254, ark-ec, ark-ff, ark-serialize)
  • Build: Static library built from Rust using cargo
  • Status: Will be replaced with pure Zig implementation

c-kzg-4844

KZG commitment library for EIP-4844 blob transactions:

  • Dependency: ethereum/c-kzg-4844
  • Purpose: KZG point evaluation precompile (0x0a)
  • Status: May be replaced with pure Zig implementation

System Libraries (Temporary)

Linux:

dl, pthread, m, rt

macOS:

Security framework, CoreFoundation framework

These system library requirements will be eliminated when Rust dependencies are removed.

Example build.zig Integration

const std = @import("std");

pub fn build(b: *std.Build) void {
    const target = b.standardTargetOptions(.{});
    const optimize = b.standardOptimizeOption(.{});

    // Add Guillotine as dependency
    const guillotine = b.dependency("guillotine", .{
        .target = target,
        .optimize = optimize,
    });

    // Get Guillotine modules
    const evm_mod = guillotine.module("evm");
    const primitives_mod = guillotine.module("primitives");
    
    // Your executable
    const exe = b.addExecutable(.{
        .name = "your-app",
        .root_source_file = b.path("src/main.zig"),
        .target = target,
        .optimize = optimize,
    });
    
    // Link Guillotine modules
    exe.root_module.addImport("evm", evm_mod);
    exe.root_module.addImport("primitives", primitives_mod);
    
    // Link required libraries (automatically handled by Guillotine modules)
    // The bn254_wrapper and c-kzg-4844 libraries are linked automatically
    // when you import the evm module
    
    b.installArtifact(exe);
}

build.zig.zon Configuration

.{
    .name = "your-project",
    .version = "0.1.0",
    .dependencies = .{
        .guillotine = .{
            .url = "https://github.com/evmts/Guillotine/archive/<commit-hash>.tar.gz",
            .hash = "<hash>",
        },
    },
    .paths = .{""},
}

Minimal Module Usage

For projects that only need specific Guillotine functionality:

// Use only primitives (Address, Hex, RLP, etc.)
const primitives = b.dependency("guillotine", .{}).module("primitives");
exe.root_module.addImport("primitives", primitives);

// Use only EVM execution (includes all dependencies)
const evm = b.dependency("guillotine", .{}).module("evm");
exe.root_module.addImport("evm", evm);

Integration Notes

  1. Automatic Linking: When you import the evm module, all required libraries (BN254 wrapper, c-kzg-4844, system libraries) are automatically linked.

  2. Cross-Platform: The build system automatically detects the target platform and links appropriate system libraries (Security/CoreFoundation on macOS, dl/pthread/m/rt on Linux).

  3. WASM Compatibility: For WASM targets, BN254 operations use placeholder implementations. Full zkSNARK support requires host environment integration.

  4. Memory Management: All Guillotine operations require an allocator. Use std.testing.allocator for tests or your application's allocator for production.

  5. Future Simplification: Integration will become much simpler once pure Zig implementations replace the current Rust dependencies, eliminating the need for Rust toolchain and system library requirements.

Troubleshooting

  • Signal 4 (Illegal Instruction): Ensure all system libraries are properly linked. This typically occurs when BN254 operations fail due to missing dependencies. Note: This issue will be resolved when pure Zig implementations are complete.
  • Build Failures: Verify Zig version compatibility (0.14.1+ required) and ensure Rust toolchain is available for BN254 wrapper compilation. Note: Rust toolchain requirement will be removed in future releases.
  • Import Errors: Use the module system rather than direct file imports. Import evm and primitives modules as shown above.

πŸ“œ License

MIT License. Free for all use. 🌍


πŸ™ Acknowledgments

  • πŸ›οΈ Ethereum Foundation and OP RPGF β€” for funding support
  • βš™οΈ Zig Community β€” for an incredible systems programming language
  • 🧠 @SamBacha β€” for the name Guillotine
  • πŸ’¬ Tevm Telegram β€” for community feedback and direction

About

An ultra-high performance and flexible EVM. Written in zig

Resources

License

Code of conduct

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published