Skip to content

Tevm Node Overview

Tevm Node is a full Ethereum execution environment that runs natively in JavaScript. It provides the complete functionality of an Ethereum node without requiring any blockchain client installation.

Conceptually, it works very similar to Anvil and Hardhat but with more powerful TypeScript native interop.

What Makes Tevm Unique?

Unlike traditional development environments like Hardhat or Anvil, Tevm Node offers several distinct advantages:

  • Cross-Platform Compatibility — The same code works everywhere JavaScript runs, with zero native dependencies including your applications in the browser
  • Fine-grained EVM Control — Access the execution environment at any level of detail, from high-level transactions to individual EVM opcodes
  • Enhanced User Experience — Enable advanced features like instantaneous gas estimation, optimistic UI updates, and sophisticated transaction simulation
  • Type-safe Interactions — Full TypeScript support throughout the entire API surface
  • Direct Solidity Imports — Import Solidity files directly into TypeScript with the Tevm Bundler

Getting Started

Install Tevm

First, install Tevm in your project:

npm
npm install tevm

Choose Your Client

Tevm offers different client types depending on your needs:

// In-memory client (fastest, fully isolated)
import { createMemoryClient } from "tevm";
const memoryClient = createMemoryClient();
 
// Fork client (use existing chain state)
import { createMemoryClient } from "tevm";
import { http } from "viem";
import { mainnet } from "tevm/chains";
const forkClient = createMemoryClient({
  fork: {
    transport: http("https://eth-mainnet.g.alchemy.com/v2/YOUR_API_KEY"),
    common: mainnet,
  },
});
 
// Tree-shakable client (lighter weight)
import { createClient, http, custom } from "viem";
import { createTevmNode } from "tevm";
import { optimism } from "tevm/common";
import { eip1193Request } from "tevm/decorators";
const node = createTevmNode({
  fork: {
    transport: http("https://mainnet.optimism.io"),
    common: optimism,
  },
}).extend(eip1193Request());
const client = createClient({
  transport: custom(node),
});
import { getBlockNumber } from "viem";
await getBlockNumber(client);
 
// Ethers client
import { TevmProvider } from "tevm/ethers";
import { http, toHex, parseEth } from "tevm";
const provider = await TevmProvider.createMemoryProvider({
  fork: {
    transport: http("https://mainnet.optimism.io"),
  },
});
await provider.send("tevm_setAccount", [
  {
    address: `0x${"69".repeat(20)}`,
    nonce: toHex(1),
    balance: toHex(parseEth("25")),
  },
]);

Use your client to read and write to an in-memory blockchain

Below is a complete typical flow of using Tevm to:

  1. Add a contract to the Tevm state
  2. Write to the contract with viem
  3. Mine a new block with the transaction
  4. Read from contract with viem
import { createMemoryClient, PREFUNDED_ACCOUNTS } from "tevm";
import { http } from "viem";
import { SimpleContract } from "tevm/contract";
import { optimism } from "tevm/common";
 
// Create an in-memory Ethereum client forking optimism
const client = createMemoryClient({
  common: optimism,
  fork: { transport: http("https://mainnet.optimism.io") },
});
 
const contract = SimpleContract.withAddress(`0x${"40".repeat(20)}`);
 
// Deploy contract bytecode. There are many ways to do this including tevmDeploy.
// Here we just use an anvil test action
await client.setCode({
  address: contract.address,
  bytecode: contract.deployedBytecode,
});
 
// Write to contract
await client.writeContract({
  account: PREFUNDED_ACCOUNTS[0],
  abi: contract.abi,
  functionName: "set",
  args: [420n],
  address: contract.address,
});
 
await client.tevmMine();
 
// Read from contract
const value = await client.readContract({
  abi: contract.abi,
  functionName: "get",
  address: contract.address,
});
 
console.log(value); // 420n
How it works
  1. We create a memoryClient that runs an Ethereum node entirely in memory
  2. We define a contract and its address
  3. We deploy the contract using setCode (simpler than a full deployment transaction)
  4. We write to the contract using a familiar viem-style interface
  5. We mine the transaction to include it in a block
  6. We read the updated value from the contract

Key Points:

  • Familiar Interface — Tevm uses viem as its primary API, making it instantly familiar to viem users
  • In-Memory Execution — TevmNode runs the Ethereum environment directly in memory rather than using JSON-RPC over HTTP
  • Full Control — Mine blocks on demand, manipulate state, and more

Start Building

You're now ready to build with Tevm!

// Runs in browsers, Node.js, Deno, Bun and beyond
// Zero native dependencies
import { createMemoryClient } from "tevm";
// Optionally import solidity contracts directly into typescript in a typesafe way
// This requires the Tevm Bundler to be set up (see Bundler Quickstart)
import { ComplexSimulation } from "../contracts/ComplexSimulation.s.sol";
 
const client = createMemoryClient();
 
// Use the viem api you already know
console.log(await client.getBlockNumber());
 
// Or use powerful typescript native apis
const {
  data,
  error,
  logs,
  createdAddresses,
  executionGasUsed,
  l1Fee,
  trace,
  accessList,
  txHash,
} = await client.tevmContract({
  deployedBytecode: ComplexSimulation.deployedBytecode,
  ...ComplexSimulation.read.simulate(2n, "arg2"),
  createTrace: true,
  createAccessList: true,
  createTransaction: true,
  throwOnFail: false,
  onStep: (step, next) => {
    console.log(step.opcode);
    next?.();
  },
});

Learning Path

If you're new to Ethereum development, don't worry! Tevm serves as an excellent learning platform for both Ethereum and TypeScript:

Ready to dive in right away?

Viem Quickstart →

Ethers Quickstart →Bundler Quickstart →What is Tevm Node? →