JavaScript API Reference¶
Complete API reference for the Node.js bindings.
Installation¶
Or when published to npm:
EVM Class¶
Constructor¶
Create a new EVM instance.
Methods¶
destroy¶
Destroy EVM and free resources.
Warning
Always call destroy() when done to prevent memory leaks.
reset¶
Reset execution state (keeps accounts).
setGasLimit¶
Set maximum gas for execution.
setBlockNumber¶
Set current block number.
setTimestamp¶
Set block timestamp.
setChainId¶
Set chain ID.
setCoinbase¶
Set coinbase address.
setAddress¶
Set current contract address.
setCaller¶
Set caller address (msg.sender).
setOrigin¶
Set transaction origin (tx.origin).
setValue¶
Set call value in wei.
setBalance¶
Set account balance.
setCode¶
Set account bytecode.
setStorage¶
setStorage(address: string | Buffer,
key: number | bigint | string | Buffer,
value: number | bigint | string | Buffer): void
Set storage slot.
getStorage¶
Get storage slot value.
Returns: 32-byte Buffer
execute¶
Execute bytecode.
Parameters: - code: EVM bytecode - calldata: Optional input data
Returns: EVMResult
getReturnData¶
Get return data from last execution.
getLogs¶
Get logs emitted during execution.
Properties¶
gasUsed¶
Gas used in last execution.
gasRemaining¶
Gas remaining after execution.
stackDepth¶
Current stack depth.
memorySize¶
Current memory size in bytes.
Debugging Methods¶
stackPeek¶
Peek at stack value.
Parameters: - index: Stack index (0 = top, default)
Returns: 32-byte Buffer or null
memoryRead¶
Read memory region.
EVMResult¶
interface EVMResult {
success: boolean;
errorCode: number;
errorName: string;
gasUsed: bigint;
gasRemaining: bigint;
returnData: Buffer;
reverted: boolean;
}
| Field | Type | Description |
|---|---|---|
success | boolean | Whether execution succeeded |
errorCode | number | Error code (0 = success) |
errorName | string | Human-readable error name |
gasUsed | bigint | Gas consumed |
gasRemaining | bigint | Gas remaining |
returnData | Buffer | Data from RETURN opcode |
reverted | boolean | Whether REVERT was called |
Log¶
| Field | Type | Description |
|---|---|---|
address | Buffer | 20-byte contract address |
topics | Buffer[] | 0-4 topics (32 bytes each) |
data | Buffer | Log data |
BatchExecutor¶
For parallel transaction execution.
Constructor¶
interface BatchExecutorConfig {
maxThreads?: number;
enableParallel?: boolean;
enableSpeculation?: boolean;
chainId?: bigint;
blockNumber?: bigint;
blockTimestamp?: bigint;
blockGasLimit?: bigint;
coinbase?: string | Buffer;
}
const executor = new BatchExecutor(config: BatchExecutorConfig);
Methods¶
setAccount¶
setAccount(options: {
address: string | Buffer;
balance?: bigint;
nonce?: number;
code?: Buffer;
}): void
Set account state.
setStorage¶
setStorage(address: string | Buffer,
key: number | bigint | string | Buffer,
value: number | bigint | string | Buffer): void
Set storage slot.
execute¶
Execute transactions in parallel.
getResults¶
Get individual transaction results.
BatchTransaction¶
interface BatchTransaction {
from: string | Buffer;
to?: string | Buffer;
value?: bigint;
data?: Buffer;
gasLimit?: bigint;
gasPrice?: bigint;
nonce?: number;
}
BatchStats¶
interface BatchStats {
totalTransactions: number;
successfulTransactions: number;
failedTransactions: number;
revertedTransactions: number;
totalGasUsed: bigint;
executionTimeNs: bigint;
parallelWaves: number;
maxParallelism: number;
}
BatchResult¶
interface BatchResult {
txIndex: number;
success: boolean;
reverted: boolean;
gasUsed: bigint;
returnData: Buffer;
errorCode: number;
logsCount: number;
createdAddress?: Buffer;
}
Examples¶
Basic Execution¶
const { EVM } = require('zigevm');
const evm = new EVM();
evm.setGasLimit(100000n);
// PUSH1 3, PUSH1 5, ADD, STOP
const code = Buffer.from([0x60, 0x03, 0x60, 0x05, 0x01, 0x00]);
const result = evm.execute(code);
console.log(`Success: ${result.success}`);
console.log(`Gas used: ${result.gasUsed}`);
evm.destroy();
Working with Storage¶
const { EVM } = require('zigevm');
const evm = new EVM();
evm.setGasLimit(100000n);
const address = '0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa';
evm.setAddress(address);
// Set storage
evm.setStorage(address, 0, 42);
// SLOAD slot 0
const code = Buffer.from([0x60, 0x00, 0x54, 0x00]);
const result = evm.execute(code);
// Check stack
const value = evm.stackPeek(0);
console.log(`Value: ${value.readBigUInt64BE(24)}`); // 42
evm.destroy();
Reading Logs¶
const { EVM } = require('zigevm');
const evm = new EVM();
evm.setGasLimit(100000n);
const result = evm.execute(code);
for (const log of evm.getLogs()) {
console.log(`Address: 0x${log.address.toString('hex')}`);
log.topics.forEach((topic, i) => {
console.log(` Topic ${i}: 0x${topic.toString('hex')}`);
});
console.log(` Data: 0x${log.data.toString('hex')}`);
}
evm.destroy();
Parallel Execution¶
const { BatchExecutor } = require('zigevm');
const executor = new BatchExecutor({
maxThreads: 8,
enableParallel: true,
chainId: 1n,
blockNumber: 12345678n,
});
// Set up accounts
for (let i = 0; i < 10; i++) {
executor.setAccount({
address: `0x${'00'.repeat(19)}${i.toString(16).padStart(2, '0')}`,
balance: 100n * 10n**18n,
});
}
// Create transactions
const transactions = Array(1000).fill(null).map((_, i) => ({
from: `0x${'00'.repeat(19)}${(i % 10).toString(16).padStart(2, '0')}`,
to: `0x${'00'.repeat(19)}${((i + 1) % 10).toString(16).padStart(2, '0')}`,
value: 1n * 10n**18n,
gasLimit: 21000n,
}));
// Execute
const stats = await executor.execute(transactions);
console.log(`Transactions: ${stats.totalTransactions}`);
console.log(`Parallel waves: ${stats.parallelWaves}`);
console.log(`Speedup: ${stats.maxParallelism}x`);
// Check results
for (const result of executor.getResults()) {
if (!result.success) {
console.log(`Tx ${result.txIndex} failed: ${result.errorCode}`);
}
}
With ethers.js¶
const { ethers } = require('ethers');
const { EVM } = require('zigevm');
async function simulateCall(contractAddress, calldata) {
const evm = new EVM();
evm.setGasLimit(3000000n);
// Get contract code
const code = await provider.getCode(contractAddress);
evm.setCode(contractAddress, Buffer.from(code.slice(2), 'hex'));
evm.setAddress(contractAddress);
// Execute
const result = evm.execute(
Buffer.from(code.slice(2), 'hex'),
Buffer.from(calldata.slice(2), 'hex')
);
evm.destroy();
return result;
}
TypeScript¶
import { EVM, EVMResult, Log, EVMError } from 'zigevm';
const evm = new EVM();
// Full type support
const result: EVMResult = evm.execute(code, calldata);
const logs: Log[] = evm.getLogs();
const gasUsed: bigint = evm.gasUsed;
evm.destroy();
Error Handling¶
const { EVM } = require('zigevm');
const evm = new EVM();
evm.setGasLimit(100n); // Very low
try {
const result = evm.execute(expensiveCode);
if (!result.success) {
if (result.errorCode === 1) { // OutOfGas
console.log('Increase gas limit');
} else if (result.reverted) {
console.log(`Reverted: ${result.returnData.toString('hex')}`);
} else {
console.log(`Error: ${result.errorName}`);
}
}
} catch (e) {
console.log(`FFI error: ${e.message}`);
} finally {
evm.destroy();
}
Value Formats¶
// Numbers
evm.setBalance(address, 1000000);
// BigInts (recommended for large values)
evm.setBalance(address, 1000000000000000000n);
// Hex strings
evm.setBalance(address, '0x1000');
// Buffers (32 bytes, big-endian)
evm.setBalance(address, Buffer.alloc(32));