A JavaScript-native Ethereum Virtual Machine
Tevm is a complete Ethereum execution environment implemented entirely in JavaScript that runs across any JS environment, including browsers, Node.js, Deno, and Bun. It provides the full functionality of an Ethereum node without requiring any blockchain client installation or native dependencies.
Conceptually, it works similarly to Anvil and Hardhat, but with more powerful TypeScript-native interoperability and cross-platform compatibility.
- JavaScript-Native EVM - Run an Ethereum environment anywhere JavaScript runs
- Cross-Platform Compatibility - The same code works in browsers, Node.js, Deno, and Bun
- Zero Native Dependencies - Pure JavaScript implementation with no compilation required
- Network Forking - Create local sandboxes of any EVM-compatible chain
- Fine-grained EVM Control - Access execution at any level of detail, from transactions to opcodes
- Direct Solidity Imports - Import
.sol
files directly into TypeScript with the bundler - Type-safe Interactions - Full TypeScript support throughout the entire API surface
# Install Tevm in your project
npm install tevm viem@latest
Create your first Tevm client:
// In-memory client (fastest, fully isolated)
import { createMemoryClient } from "tevm";
const client = createMemoryClient();
// OR: Fork client (use existing chain state)
import { createMemoryClient, http } from "tevm";
import { mainnet } from "tevm/chains";
const forkClient = createMemoryClient({
fork: {
transport: http("https://eth-mainnet.g.alchemy.com/v2/YOUR_API_KEY"),
common: mainnet,
},
});
import { createMemoryClient, http, PREFUNDED_ACCOUNTS } from "tevm";
import { optimism } from "tevm/common";
import { parseAbi } from "viem";
// Create a client as a fork of Optimism mainnet
const client = createMemoryClient({
common: optimism,
fork: {
transport: http("https://mainnet.optimism.io")
},
});
// Wait for the fork to be ready
await client.tevmReady();
// Setup a test account with funds
const account = "0x" + "baD60A7".padStart(40, "0");
await client.setBalance({
address: account,
value: 10000000000000000000n // 10 ETH
});
// Define contract interface
const greeterAbi = parseAbi([
'function greet() view returns (string)',
'function setGreeting(string memory _greeting) public'
]);
const greeterAddress = "0x10ed0b176048c34d69ffc0712de06CbE95730748";
// Read from contract
const greeting = await client.readContract({
address: greeterAddress,
abi: greeterAbi,
functionName: 'greet',
});
console.log(`Current greeting: ${greeting}`);
// Write to contract
const txHash = await client.writeContract({
account,
address: greeterAddress,
abi: greeterAbi,
functionName: 'setGreeting',
args: ["Hello from Tevm!"],
});
// Mine a block to include our transaction
await client.mine({ blocks: 1 });
// Verify the updated greeting
const newGreeting = await client.readContract({
address: greeterAddress,
abi: greeterAbi,
functionName: 'greet',
});
console.log(`Updated greeting: ${newGreeting}`);
One of Tevm's most powerful features is the ability to import Solidity files directly into your TypeScript code using the Tevm Bundler:
// Import a .sol file directly
import { ERC20 } from '@openzeppelin/contracts/token/ERC20/ERC20.sol';
import { createMemoryClient } from 'tevm';
const client = createMemoryClient();
// With full TypeScript support
const tokenContract = ERC20.withAddress('0x123...');
// Type-safe contract methods
const balance = await client.readContract(
tokenContract.read.balanceOf('0x456...')
);
See the Bundler Quickstart guide for setup instructions.
- Performance: Eliminate network latency with local execution
- Enhanced UX: Enable offline capabilities, optimistic UI updates, and sophisticated simulations
- Developer Experience: Advanced debugging, deterministic testing, and portable environments
- Ecosystem Integration: Leverage the entire JavaScript ecosystem and tooling
await client.tevmContract({
address: contractAddress,
abi: contractAbi,
functionName: 'transfer',
args: ['0x...', 100n],
// Step through execution
onStep: (data, next) => {
console.log(`Opcode: ${data.opcode.name}`);
console.log(`Stack: ${data.stack.join(', ')}`);
next();
}
});
import { createMemoryClient, http } from 'tevm';
import { optimism } from 'tevm/chains';
// Fork from Optimism mainnet
const client = createMemoryClient({
fork: {
transport: http('https://mainnet.optimism.io'),
common: optimism
}
});
// Access any contract or account state from the forked network
const balance = await client.getBalance({
address: '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045' // vitalik.eth
});
// Manual mining (default)
await client.sendTransaction({ /* ... */ });
await client.mine({ blocks: 1 }); // Explicitly mine when ready
// Auto-mining
client.setMining({ mode: 'auto' }); // Mine on each transaction
// Interval mining
client.setMining({
mode: 'interval',
interval: 5000 // Mine every 5 seconds
});
For comprehensive documentation, visit node.tevm.sh for:
- Getting Started Guide
- Viem Integration
- Ethers Integration
- Bundler Quickstart
- API Reference
- Examples and Tutorials
Contributions are welcome! Please see CONTRIBUTING.md for details on how to contribute.
Most files are licensed under the MIT license. Some files copied from ethereumjs inherit the MPL-2.0 license. These files are individually marked at the top.