C FFI Reference¶
Complete C ABI reference for embedding Zig EVM in C/C++ and other languages.
Building the Library¶
# Build shared and static libraries
zig build lib
# Output:
# - zig-out/lib/libzigevm.so (Linux)
# - zig-out/lib/libzigevm.dylib (macOS)
# - zig-out/lib/libzigevm.dll (Windows)
# - zig-out/lib/libzigevm.a (static)
# - zig-out/include/zigevm.h (header)
Header¶
Error Codes¶
typedef enum {
EVM_OK = 0,
EVM_OUT_OF_GAS = 1,
EVM_STACK_UNDERFLOW = 2,
EVM_STACK_OVERFLOW = 3,
EVM_INVALID_OPCODE = 4,
EVM_INVALID_JUMP = 5,
EVM_REVERT = 6,
EVM_STATIC_CALL_VIOLATION = 7,
EVM_OUT_OF_MEMORY = 8,
EVM_CALL_DEPTH_EXCEEDED = 9,
EVM_INSUFFICIENT_BALANCE = 10,
EVM_INVALID_ARGUMENT = 11,
EVM_UNKNOWN_ERROR = 255,
} EVMError;
Single Execution API¶
Lifecycle¶
evm_create¶
Create a new EVM instance.
Returns: Handle to the EVM, or NULL on failure.
evm_destroy¶
Destroy an EVM instance and free all resources.
evm_reset¶
Reset EVM state for new execution. Preserves accounts and storage.
Configuration¶
evm_set_gas_limit¶
Set the maximum gas allowed for execution.
evm_set_block_number¶
Set the current block number.
evm_set_timestamp¶
Set the block timestamp.
evm_set_chain_id¶
Set the chain ID (1 = mainnet).
evm_set_coinbase¶
Set the coinbase (block producer) address.
Parameters: - addr: 20-byte address
evm_set_address¶
Set the current contract address.
evm_set_caller¶
Set the caller address (msg.sender).
evm_set_origin¶
Set the transaction origin (tx.origin).
evm_set_value¶
Set the call value.
Parameters: - value: 32-byte big-endian value
Account Management¶
evm_set_balance¶
Set an account's balance.
Parameters: - addr: 20-byte address - balance: 32-byte big-endian balance
evm_set_code¶
Set an account's bytecode.
evm_set_storage¶
EVMError evm_set_storage(EVMHandle handle, const uint8_t* addr,
const uint8_t* key, const uint8_t* value);
Set a storage slot value.
Parameters: - addr: 20-byte address - key: 32-byte storage key - value: 32-byte storage value
evm_get_storage¶
Get a storage slot value.
Parameters: - out: 32-byte buffer to receive value
Execution¶
evm_execute¶
EVMResult evm_execute(EVMHandle handle, const uint8_t* code, size_t code_len,
const uint8_t* calldata, size_t calldata_len);
Execute EVM bytecode.
Returns: EVMResult structure:
typedef struct {
bool success; // True if execution succeeded
EVMError error_code; // Error code if failed
uint64_t gas_used; // Gas consumed
uint64_t gas_remaining; // Gas remaining
uint8_t* return_data; // Return data (owned by EVM)
size_t return_data_len; // Return data length
bool reverted; // True if REVERT was called
} EVMResult;
Result Access¶
evm_gas_used¶
Get gas used in last execution.
evm_gas_remaining¶
Get remaining gas after last execution.
evm_return_data_len¶
Get return data length.
evm_return_data_copy¶
Copy return data to buffer.
Returns: Number of bytes copied.
Logs Access¶
evm_logs_count¶
Get number of logs emitted.
evm_log_address¶
Get log address at index.
evm_log_topics_count¶
Get number of topics (0-4) for a log.
evm_log_topic¶
Get a specific topic from a log.
evm_log_data_len¶
Get log data length.
evm_log_data_copy¶
Copy log data to buffer.
Debugging¶
evm_stack_depth¶
Get number of items on stack.
evm_stack_peek¶
Peek stack value at index (0 = top).
evm_memory_size¶
Get memory size in bytes.
evm_memory_copy¶
Copy memory region to buffer.
Version¶
evm_version¶
Get library version string.
Batch Execution API¶
Structures¶
BatchConfig¶
typedef struct {
uint32_t max_threads; // Maximum worker threads
bool enable_parallel; // Enable parallel execution
bool enable_speculation; // Enable speculative execution
uint64_t chain_id; // Chain ID
uint64_t block_number; // Block number
uint64_t block_timestamp; // Block timestamp
uint64_t block_gas_limit; // Block gas limit
uint8_t coinbase[20]; // Coinbase address
} BatchConfig;
BatchTransaction¶
typedef struct {
uint8_t from[20]; // Sender address
uint8_t to[20]; // Recipient address
bool has_to; // True if to address is set
uint8_t value[32]; // Value in wei (big-endian)
const uint8_t* data; // Calldata
size_t data_len; // Calldata length
uint64_t gas_limit; // Gas limit
uint8_t gas_price[32]; // Gas price (big-endian)
uint64_t nonce; // Nonce
bool has_nonce; // True if nonce is set
} BatchTransaction;
BatchResult¶
typedef struct {
uint32_t tx_index; // Transaction index
bool success; // True if succeeded
bool reverted; // True if reverted
uint64_t gas_used; // Gas used
uint8_t* return_data; // Return data pointer
size_t return_data_len; // Return data length
EVMError error_code; // Error code
size_t logs_count; // Number of logs
uint8_t created_address[20]; // Created contract address
bool has_created_address; // True if contract created
} BatchResult;
BatchStats¶
typedef struct {
uint32_t total_transactions; // Total transactions
uint32_t successful_transactions; // Successful count
uint32_t failed_transactions; // Failed count
uint32_t reverted_transactions; // Reverted count
uint64_t total_gas_used; // Total gas used
uint64_t execution_time_ns; // Execution time
uint32_t parallel_waves; // Parallel waves
uint32_t max_parallelism; // Max parallelism
} BatchStats;
Functions¶
batch_create¶
Create a batch executor.
batch_destroy¶
Destroy a batch executor.
batch_set_account¶
EVMError batch_set_account(BatchHandle handle, const uint8_t* addr,
const uint8_t* balance, uint64_t nonce,
const uint8_t* code, size_t code_len);
Set account state in batch executor.
batch_set_storage¶
EVMError batch_set_storage(BatchHandle handle, const uint8_t* addr,
const uint8_t* key, const uint8_t* value);
Set storage in batch executor.
batch_execute¶
EVMError batch_execute(BatchHandle handle,
const BatchTransaction* transactions,
size_t tx_count, BatchStats* stats_out);
Execute a batch of transactions.
batch_results_count¶
Get number of results from last execution.
batch_get_result¶
Get a specific result.
batch_result_return_data¶
Copy return data from a result.
Complete Example¶
#include <stdio.h>
#include <string.h>
#include "zigevm.h"
int main() {
// Create EVM
EVMHandle evm = evm_create();
if (!evm) {
fprintf(stderr, "Failed to create EVM\n");
return 1;
}
// Configure
evm_set_gas_limit(evm, 1000000);
evm_set_chain_id(evm, 1);
// Set up account
uint8_t addr[20] = {0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa};
uint8_t balance[32] = {0};
balance[31] = 100;
evm_set_balance(evm, addr, balance);
evm_set_address(evm, addr);
// Bytecode: PUSH1 42, PUSH1 0, MSTORE, PUSH1 32, PUSH1 0, RETURN
uint8_t code[] = {
0x60, 0x2a, // PUSH1 42
0x60, 0x00, // PUSH1 0
0x52, // MSTORE
0x60, 0x20, // PUSH1 32
0x60, 0x00, // PUSH1 0
0xf3 // RETURN
};
// Execute
EVMResult result = evm_execute(evm, code, sizeof(code), NULL, 0);
if (result.success) {
printf("Execution successful!\n");
printf("Gas used: %lu\n", result.gas_used);
printf("Return data length: %zu\n", result.return_data_len);
if (result.return_data_len > 0) {
printf("Return data: ");
for (size_t i = 0; i < result.return_data_len; i++) {
printf("%02x", result.return_data[i]);
}
printf("\n");
}
} else {
printf("Execution failed with error: %d\n", result.error_code);
if (result.reverted) {
printf("Transaction reverted\n");
}
}
// Cleanup
evm_destroy(evm);
return 0;
}
Linking¶
Linux/macOS¶
Windows¶
Thread Safety¶
- Each EVM instance is NOT thread-safe
- Create separate instances for concurrent use
- BatchExecutor handles internal threading
- FFI functions are safe to call from any thread