# Table of Contents - [What is Tevm Node?](#what-is-tevm-node-) - [Tevm Node](#tevm-node) - [Overview · Tevm](#overview-tevm) - [Why run Ethereum in JS? · Tevm](#why-run-ethereum-in-js-tevm) - [Community & Testimonials · Tevm](#community-testimonials-tevm) - [CLI Quickstart · Tevm](#cli-quickstart-tevm) - [Bundler Quickstart · Tevm](#bundler-quickstart-tevm) - [Getting Started with Ethers · Tevm](#getting-started-with-ethers-tevm) - [Architecture Overview · Tevm](#architecture-overview-tevm) - [Using with Viem · Tevm](#using-with-viem-tevm) - [Getting Started with Viem · Tevm](#getting-started-with-viem-tevm) - [Creating a Tevm Node](#creating-a-tevm-node) - [Vercel Security Checkpoint](#vercel-security-checkpoint) - [Vercel Security Checkpoint](#vercel-security-checkpoint) - [Vercel Security Checkpoint](#vercel-security-checkpoint) - [Vercel Security Checkpoint](#vercel-security-checkpoint) - [Vercel Security Checkpoint](#vercel-security-checkpoint) - [Vercel Security Checkpoint](#vercel-security-checkpoint) - [Vercel Security Checkpoint](#vercel-security-checkpoint) - [Vercel Security Checkpoint](#vercel-security-checkpoint) - [Vercel Security Checkpoint](#vercel-security-checkpoint) - [Vercel Security Checkpoint](#vercel-security-checkpoint) - [Vercel Security Checkpoint](#vercel-security-checkpoint) - [Vercel Security Checkpoint](#vercel-security-checkpoint) - [Vercel Security Checkpoint](#vercel-security-checkpoint) - [Vercel Security Checkpoint](#vercel-security-checkpoint) - [Vercel Security Checkpoint](#vercel-security-checkpoint) - [Vercel Security Checkpoint](#vercel-security-checkpoint) - [Vercel Security Checkpoint](#vercel-security-checkpoint) - [Vercel Security Checkpoint](#vercel-security-checkpoint) - [Vercel Security Checkpoint](#vercel-security-checkpoint) - [Vercel Security Checkpoint](#vercel-security-checkpoint) - [Vercel Security Checkpoint](#vercel-security-checkpoint) - [Vercel Security Checkpoint](#vercel-security-checkpoint) - [Vercel Security Checkpoint](#vercel-security-checkpoint) - [Vercel Security Checkpoint](#vercel-security-checkpoint) - [Vercel Security Checkpoint](#vercel-security-checkpoint) - [Vercel Security Checkpoint](#vercel-security-checkpoint) - [Vercel Security Checkpoint](#vercel-security-checkpoint) - [Vercel Security Checkpoint](#vercel-security-checkpoint) - [Vercel Security Checkpoint](#vercel-security-checkpoint) - [Vercel Security Checkpoint](#vercel-security-checkpoint) - [Vercel Security Checkpoint](#vercel-security-checkpoint) - [Vercel Security Checkpoint](#vercel-security-checkpoint) - [Vercel Security Checkpoint](#vercel-security-checkpoint) - [Vercel Security Checkpoint](#vercel-security-checkpoint) - [Vercel Security Checkpoint](#vercel-security-checkpoint) - [Vercel Security Checkpoint](#vercel-security-checkpoint) - [Vercel Security Checkpoint](#vercel-security-checkpoint) - [Vercel Security Checkpoint](#vercel-security-checkpoint) - [Vercel Security Checkpoint](#vercel-security-checkpoint) - [Vercel Security Checkpoint](#vercel-security-checkpoint) - [Vercel Security Checkpoint](#vercel-security-checkpoint) - [Vercel Security Checkpoint](#vercel-security-checkpoint) - [Vercel Security Checkpoint](#vercel-security-checkpoint) - [Vercel Security Checkpoint](#vercel-security-checkpoint) --- # What is Tevm Node? [Skip to content](https://node.tevm.sh/introduction/what-is-tevm-node#vocs-content) 🚀 Tevm Node is in Beta! Join our [Telegram community](https://t.me/+ANThR9bHDLAwMjUx) Search... [![Logo](https://node.tevm.sh/tevm-logo-dark.png)![Logo](https://node.tevm.sh/tevm-logo-light.png)](https://node.tevm.sh/) [![Logo](https://node.tevm.sh/tevm-logo-dark.png)![Logo](https://node.tevm.sh/tevm-logo-light.png)](https://node.tevm.sh/) Docs Chevron Down Menu What is Tevm Node? On this page Chevron Right What is Tevm Node?[](https://node.tevm.sh/introduction/what-is-tevm-node#what-is-tevm-node) ---------------------------------------------------------------------------------------------- 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?[](https://node.tevm.sh/introduction/what-is-tevm-node#what-makes-tevm-unique) -------------------------------------------------------------------------------------------------------- Unlike traditional development environments like [Hardhat](https://hardhat.org/) or [Anvil](https://book.getfoundry.sh/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 powered by `abitype` * **Direct Solidity Imports** — The powerful ability to write solidity code that interops with your TypeScript code in a typesafe way via the [Tevm Bundler](https://node.tevm.sh/getting-started/bundler) Universal JavaScript Compatibility[](https://node.tevm.sh/introduction/what-is-tevm-node#universal-javascript-compatibility) ------------------------------------------------------------------------------------------------------------------------------- Tevm's key innovation is bringing the Ethereum execution environment to **every JavaScript runtime**: Node.js For local development, testing, and CI/CD pipelines Browser For advanced dApps with offline capability and real-time simulation Any JS Runtime Works in Deno, Bun, Edge Functions, or any modern JavaScript environment Integration With Popular Libraries[](https://node.tevm.sh/introduction/what-is-tevm-node#integration-with-popular-libraries) ------------------------------------------------------------------------------------------------------------------------------- Tevm works with the libraries you already know and love including `viem` `wagmi` and `ethers`: viemethers viem Copy `import { createMemoryClient, http } from "tevm"; const client = createMemoryClient(); // Use standard viem actions const balance = await client.getBalance({ address: "0x..." }); const blockNumber = await client.getBlockNumber(); // Plus Tevm-specific actions await client.tevmMine({ blocks: 1 }); await client.tevmSetAccount({ address: "0x...", balance: 100000000000000000n, // 0.1 ETH });` How Tevm Compares[](https://node.tevm.sh/introduction/what-is-tevm-node#how-tevm-compares) --------------------------------------------------------------------------------------------- | Feature | Tevm | Anvil | Hardhat | Ganache | | --- | --- | --- | --- | --- | | **Language** | JavaScript/Wasm | Rust | JavaScript/Rust | JavaScript | | **Browser Compatible** | ✅ | ❌ | ❌ | ❌ | | **Minimal Dependencies** | ✅ | ✅ | ❌ | ❌ | | **Mainnet Forking** | ✅ | ✅ | ✅ | ✅ | | **EVM Event Hooks** | ✅ | ❌ | ❌ | ❌ | | **Custom Precompiles** | ✅ | ✅ | ❌ | ❌ | | **viem Integration** | Native | Some | Minimal | Minimal | | **ethers Integration** | Native | Minimal | Minimal | Some | | **Debugging** | Advanced | Advanced | Advanced | Basic | | **TypeScript Support** | Full | Limited | Full | Full | | **Serverless Compatible** | ✅ | ❌ | ❌ | ✅ | | **Optimized forking performance** | ✅ | ❌ | ❌ | ❌ | Library Compatibility[](https://node.tevm.sh/introduction/what-is-tevm-node#library-compatibility) ----------------------------------------------------------------------------------------------------- | Library | Support Level | Notes | | --- | --- | --- | | [**viem**](https://node.tevm.sh/vercel/path0/docs/node/pages/getting-started/viem) | Native | First-class native integration with all viem features | | [**ethers.js**](https://node.tevm.sh/vercel/path0/docs/node/pages/getting-started/ethers) | Full | Both v5 and v6 via EIP-1193 provider | | [**web3.js**](https://github.com/web3/web3.js) | Full | Via EIP-1193 provider | | [**wagmi**](https://wagmi.sh/) | Full | Works as a wagmi connector | | [**thirdweb**](https://thirdweb.com/) | Full | Compatible with thirdweb's SDK | | [**Ponder**](https://ponder.sh/) | Full | Can be used to do advanced tracing in ponder handlers and import contracts into ponder config | | [**ethereumjs**](https://github.com/ethereumjs/ethereumjs-monorepo) | Native | Implements the same interfaces as Ethereumjs. Ethereumjs users can take advantage of Tevm StateManager to get Tevm like features such as forking in ethereumjs | | Any EIP-1193 library | Full | Standard provider interface | Next Steps[](https://node.tevm.sh/introduction/what-is-tevm-node#next-steps) ------------------------------------------------------------------------------- [Why JavaScript for Ethereum?\ \ Understand the unique advantages of running Ethereum in JavaScript environments](https://node.tevm.sh/introduction/what-is-tevm-node/why-run-ethereum-in-js) [Architecture Overview\ \ Dive into Tevm's technical design and component structure](https://node.tevm.sh/introduction/what-is-tevm-node/architecture-overview) [Get started building with Tevm in your own applications](https://node.tevm.sh/core/create-tevm-node) --- # Tevm Node [Skip to content](https://node.tevm.sh/#vocs-content) 🚀 Tevm Node is in Beta! Join our [Telegram community](https://t.me/+ANThR9bHDLAwMjUx) Search... [![Logo](https://node.tevm.sh/tevm-logo-dark.png)![Logo](https://node.tevm.sh/tevm-logo-light.png)](https://node.tevm.sh/) [![Logo](https://node.tevm.sh/tevm-logo-dark.png)![Logo](https://node.tevm.sh/tevm-logo-light.png)](https://node.tevm.sh/) Menu ![Tevm Logo](https://node.tevm.sh/tevm-logo-dark.png) Ethereum Node for Viem npmpnpmyarn npm install tevm An Ethereum Node built to run in Browser, Bun, Deno, and Node.js Copy `// @noErrors // Runs in browsers, Node.js, Deno, Bun and beyond // Zero native dependencies import { createMemoryClient } from "tevm"; // Direct Solidity imports with the Tevm Bundler import { ComplexSimulation } from "../contracts/ComplexSimulation.s.sol"; const client = createMemoryClient(); // Use powerful TypeScript native APIs or use the viem APIs you already know 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?.(); }, });` [Get started](https://node.tevm.sh/getting-started/overview) [Viem Guide](https://node.tevm.sh/examples/viem) [Learn More](https://node.tevm.sh/introduction/what-is-tevm-node) ### JavaScript-Native EVM Run an Ethereum environment anywhere JavaScript runs. [Why JavaScript? →](https://node.tevm.sh/introduction/why-run-ethereum-in-js) ### Up to 10x Faster Than Remote Calls Execute transactions locally without network roundtrips. Instant gas estimates for responsive dApps. [Performance Benefits →](https://node.tevm.sh/introduction/why-run-ethereum-in-js#performance--efficiency) ### Import Solidity Files Directly Use .sol files as native ES modules with full TypeScript type safety. [Bundler Integration →](https://node.tevm.sh/reference/bundler) ### Fork Any Chain Create instant local copies of Ethereum, Optimism, or any EVM chain. Use against real contracts and state without external tools like Anvil or Hardhat. [Forking Guide →](https://node.tevm.sh/core/forking) ### EVM Execution Hooks Plug into EVM execution at the opcode level. Build advanced tools like debuggers, tracers, or custom gas profilers. [EVM Hooks Guide →](https://node.tevm.sh/api/evm-events) ### Works With Tools You Know Native integration with viem and full compatibility with ethers.js, wagmi, and any EIP-1193 library. [Library Support →](https://node.tevm.sh/introduction/what-is-tevm-node#library-compatibility) > "If you're building a blockchain application on the web, I'm almost certain there is a use case for Tevm. It might change everything, and at worst it would most likely improve your devX." > > polarzero > > [@0xpolarzero](https://twitter.com/0xpolarzero) Turn Solidity into TypeScript ----------------------------- The Tevm Bundler lets you import Solidity contracts directly into your JavaScript or TypeScript code. No more copying ABIs or managing contract artifacts manually—just import your .sol files and get full type safety, auto-completion, and easy contract interaction. Copy `` // @noErrors // Import Solidity contracts directly import { ERC20 } from '@openzeppelin/contracts/token/ERC20/ERC20.sol' // Use with full TypeScript support const tokenContract = ERC20.withAddress('0x123...') // Type-safe contract methods const balance = await client.readContract( tokenContract.read.balanceOf('0x456...') ) // Coming soon: Import contracts directly from any chain import { WETH } from 'caip10:eip155:1:0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2' // Coming soon: Write Solidity inline import { sol } from 'tevm' const { abi, bytecode } = sol` pragma solidity ^0.8.19; contract Counter { uint256 private count = 0; function increment() public { count += 1; } function getCount() public view returns (uint256) { return count; } } ` `` [Bundler Quickstart](https://node.tevm.sh/getting-started/bundler) [Bundler Reference](https://node.tevm.sh/reference/bundler) [Ready to get started?](https://node.tevm.sh/getting-started/overview) Here's our [documentation as plain text](https://node.tevm.sh/llms-full.txt) for providing context to LLM systems --- # Overview · Tevm [Skip to content](https://node.tevm.sh/getting-started/overview#vocs-content) 🚀 Tevm Node is in Beta! Join our [Telegram community](https://t.me/+ANThR9bHDLAwMjUx) Search... [![Logo](https://node.tevm.sh/tevm-logo-dark.png)![Logo](https://node.tevm.sh/tevm-logo-light.png)](https://node.tevm.sh/) [![Logo](https://node.tevm.sh/tevm-logo-dark.png)![Logo](https://node.tevm.sh/tevm-logo-light.png)](https://node.tevm.sh/) Quick Start Chevron Down Menu Overview On this page Chevron Right Getting Started[](https://node.tevm.sh/getting-started/overview#getting-started) ----------------------------------------------------------------------------------- ### Install Tevm[](https://node.tevm.sh/getting-started/overview#install-tevm) First, install Tevm in your project: npmpnpmyarnbun Terminal npm Copy `npm install tevm` ### Choose Your Client[](https://node.tevm.sh/getting-started/overview#choose-your-client) Tevm offers different client types depending on your needs #### In-memory client[](https://node.tevm.sh/getting-started/overview#in-memory-client) You can spin up an empty ethereum node Copy `import { createMemoryClient } from "tevm"; const memoryClient = createMemoryClient(); const blockNumber = await memoryClient.getBlockNumber();` How it works 1. We create a `memoryClient` that runs an Ethereum node entirely in memory built with TypeScript and Wasm 2. We use the [`viem` api](https://viem.sh/) to query it. #### Fork client[](https://node.tevm.sh/getting-started/overview#fork-client) You can fork an existing chain similar to Anvil and Hardhat. Copy `import { createMemoryClient } from "tevm"; import { http } from "viem"; // http is available in tevm package as well for convenience import { mainnet } from "tevm/chains"; const forkClient = createMemoryClient({ fork: { transport: http("https://eth-mainnet.g.alchemy.com/v2/YOUR_API_KEY"), common: mainnet, }, });` (coming soon) You can give this client out a try right now using the Tevm CLI Copy `bunx tevm tevmCall --rpc=https://mainnet.optimism.io` How it works 1. We create a `memoryClient` like before but this time we pass in a transport 2. Tevm will fetch the latest block upon creation 3. As Tevm executes it will lazily fetch state from the fork url 4. Tevm has optimizations that make it more efficient at fetching state than alternatives like Anvil or Hardhat #### Rebasing client (coming soon)[](https://node.tevm.sh/getting-started/overview#rebasing-client-coming-soon) This powerful client will not only fork an existing chain but it will also listen for new blocks. As new blocks come in it will rebase it's state on the existing chain. Copy `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, rebase: true, }, });` How it works 1. We create a `memoryClient` like our forked client but this time we pass in `rebase: true` 2. Tevm will fork just like before 3. Tevm will update it's fork as "latest" tag changes on the forked chain making sure to efficiently invalidate any state it needs to. #### Tree-shakable client[](https://node.tevm.sh/getting-started/overview#tree-shakable-client) In addition to using `createMemoryClient` Tevm supports the Viem tree-shakable api. Copy `import { createClient, http } from "viem"; import { createTevmTransport } from "tevm/memory-client"; import { optimism } from "tevm/common"; const client = createClient({ transport: createTevmTransport({ fork: { transport: http("https://mainnet.optimism.io") }, common: optimism, }), }); // Import actions from viem import { getBlockNumber } from "viem"; await getBlockNumber(client);` The tree-shakable API will not include any viem or tevm actions you aren't using. For apps running in the browser the tree-shakable client is recomended to keep bundle size minimal. #### Ethers client[](https://node.tevm.sh/getting-started/overview#ethers-client) In addition to viem support Tevm plugs into Ethers as well as any other library that supports the `EIP-1193 Provider` standard. Copy ``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[](https://node.tevm.sh/getting-started/overview#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 Copy ``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:[](https://node.tevm.sh/getting-started/overview#key-points) * **Familiar Interface** — Tevm uses [viem](https://viem.sh/) as its primary API, making it instantly familiar to viem users * **Ethers Support** - Tevm also supports `ethers.js` as via the `EIP-1193 provider` standard * **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 * **Cross platform** - Run your ethereum node in the browser * **Powerful** - Comes with many advantages over an `Anvil`, `Ganache`, or `Hardhat` node ### Start Building[](https://node.tevm.sh/getting-started/overview#start-building) You're now ready to build with Tevm! Copy `// 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?.(); }, });` Essential viem concepts[](https://node.tevm.sh/getting-started/overview#essential-viem-concepts) --------------------------------------------------------------------------------------------------- If you're new to Ethereum development, don't worry! Tevm serves as an excellent learning platform for both Ethereum and TypeScript: For users new to viem it is recomended you at least become [familiar with viem](https://viem.sh/) . But as a short introduction of the essential concepts you need to know: * `Clients` are made with `createClient`, `createPublicClient`, `createWalletClient`, `createTestClient`, and `createMemoryClient` and are the main abstraction you interact with. * `Actions` such as `getBlockNumber`, `call`, `readContract`, `estimateGas`, and `tevmSetAccount` are how you interact with `viem` and `tevm` * `Transports` such as `http` and `createTevmTransport` are EIP-1193 compatable providers used to resolve JSON-RPC requests. Both `viem` and `tevm` use transports such as the `http()` transport to fetch remotely over http * `TevmNode` itself is a transport that plugs an in-memory ethereum node into viem to resolve JSON-RPC requests Ready to dive in right away?[](https://node.tevm.sh/getting-started/overview#ready-to-dive-in-right-away) ------------------------------------------------------------------------------------------------------------ [Viem Quickstart →](https://node.tevm.sh/getting-started/overview/viem) [Ethers Quickstart →](https://node.tevm.sh/getting-started/overview/ethers) [Bundler Quickstart →](https://node.tevm.sh/getting-started/overview/bundler) [What is Tevm Node? →](https://node.tevm.sh/introduction/what-is-tevm-node) --- # Why run Ethereum in JS? · Tevm [Skip to content](https://node.tevm.sh/introduction/why-run-ethereum-in-js#vocs-content) 🚀 Tevm Node is in Beta! Join our [Telegram community](https://t.me/+ANThR9bHDLAwMjUx) Search... [![Logo](https://node.tevm.sh/tevm-logo-dark.png)![Logo](https://node.tevm.sh/tevm-logo-light.png)](https://node.tevm.sh/) [![Logo](https://node.tevm.sh/tevm-logo-dark.png)![Logo](https://node.tevm.sh/tevm-logo-light.png)](https://node.tevm.sh/) Docs Chevron Down Menu Why Run Ethereum in JS? On this page Chevron Right > You know what would make solving all these problems trivially easy? If we just were able to use Foundry in the browser This is what [Fucory](https://x.com/fucory) thought the day he started building Tevm. Fucory created Tevm to solve all UX and Devx issues blocking the delivery of great blockchain apps. The original idea was to put the foundry API in the browser and the library evolved from there. Because of Tevm's wide ambitious scope Tevm's use case is simply TypeScript+EVM. If you are building on the EVM and you are using TypeScript Tevm will help you. And here is why. > We believe every TypeScript user of the EVM who installs Viem will also install Tevm alongside it in the future ### 🚀 Enhanced Performance Execute transactions locally with near-zero latency for gas estimation, transaction simulation, and debugging. ### 💻 Browser Compatibility Enable sophisticated dApp features like offline capabilities, optimistic UI updates, and real-time simulations. ### 🔍 Debug Superpowers Step through EVM execution opcode by opcode to understand exactly what's happening in your smart contracts. ### 🛠️ Familiar Developer Experience Works seamlessly with the libraries you already know - viem, ethers, or any EIP-1193 compatible tool. Performance & Efficiency[](https://node.tevm.sh/introduction/why-run-ethereum-in-js#performance--efficiency) --------------------------------------------------------------------------------------------------------------- ### ⚡ An optimized fork mode Tevm is benchmarked to perform better than even Anvil at executing calls in `forked` mode. This is possible via more efficient storage slot retrieval. ### ⚡ Zero Network Latency Running the EVM locally eliminates round-trip delays to remote nodes, enabling near-instantaneous transaction simulations and gas estimations. ### Local-first gas estimation Imagine not having to show a user a loading spinner when estimating gas while saving on RPC credits. ### 🔄 Powerful JS interop Simulate multiple transactions plugging directly into the evm with JS or even writing custom contracts in JS. Optimistic updates[](https://node.tevm.sh/introduction/why-run-ethereum-in-js#optimistic-updates) ---------------------------------------------------------------------------------------------------- Oftentimes you want to show the user what the state of their account is expected to be. Possibly we want to show them the expected state changes from their transaction or series of transactions before they submit. Or maybe we are trying to build snappy UI so we want to show them the updated state right away with a pending icon. Tevm makes implementing optimistic state simple. Copy `// create a client in rebase mode so it updates optimistic state as new blocks come in const client = createMemoryClient({ fork: { transport: http("https://mainnet.optimism.io"), rebase: true, }, common: optimism, }); // When we send a transaction to the network send it to Tevm too // We do not mine the transaction as we want it to just be in our mempool const txHash = await client.sendRawTransaction(tx); client.waitForTransactionReceipt({ hash: txHash }).then(() => { // remove the tx from optimistic state after it is included in chain const mempool = await client.transport.tevm.getTxPool(); await mempool.removeTxByHash(txHash); }); // continue to query the latest state by default await client.getBalance({ address, blockTag: "latest" }); // or query optimistic state with 'pending' block tag await client.getBalance({ address, blockTag: "pending" });` ### Real-World Performance Benefits[](https://node.tevm.sh/introduction/why-run-ethereum-in-js#real-world-performance-benefits) The `estimate_gas` example is the easiest example to illustrate this. Copy `const gasEstimate0 = await client.estimateGas({ ... }) // ~200ms as it fetches state (unless you prewarmed the cache) const gasEstimate0 = await client.estimateGas({ ... }) // ~Instant on future estimations with cache saved const gasEstimate0 = await client.estimateGas({ ... }) // ~Instant on future estimations with cache saved` Note: because Tevm can plug directly into wagmi this works as well via `useGasEstimate` Enhanced User Experiences[](https://node.tevm.sh/introduction/why-run-ethereum-in-js#enhanced-user-experiences) ------------------------------------------------------------------------------------------------------------------ JavaScript-based EVM execution enables entirely new categories of dApp features: ### Maximally hackable Tevm gives you complete control including it's deep internals in a way no other node does. Almost all use cases can be supported. ### ⚡ Optimistic UI Show users the likely outcome of transactions before they're mined on-chain. ### 🛡️ Reliable Tevm has near 100% test coverage and a history of fixing most reported bugs in under 24 hours. ### 🧮 Transaction Simulation Simulate complex interactions and preview results before sending transactions. ### 🔐 Enhanced Privacy Process sensitive data locally without sending it to external services. Top Tier Devx[](https://node.tevm.sh/introduction/why-run-ethereum-in-js#top-tier-devx) ------------------------------------------------------------------------------------------ ### Use the tools you already know[](https://node.tevm.sh/introduction/why-run-ethereum-in-js#use-the-tools-you-already-know) Tevm users report the library having great devx. A lot of this is owed to it's abilility to plug directly into the tools you are already using like `wagmi`, `viem`, and `ethers`. ### Interop with contracts effortlessly[](https://node.tevm.sh/introduction/why-run-ethereum-in-js#interop-with-contracts-effortlessly) We cannot talk about developer experience in Tevm without bringing up the `Tevm Bundler`. The Tevm Bundler is an optional addon to Tevm that makes TypeScript aware of how to process and compile Solidity. It is a tool in the same category as the `Wagmi CLI` or `Typechain` but even more powerful and ergonomic. The devx using the bundler is optimized in following ways: * Natspec on hover * Typesafe contract * TRPC like experience. You will see red underlines before you even save a solidity file * No need to set up external build tools. Plugs directly into your existing js pipeline * Supports reading foundry config for remappings and lib #### Import solidity directly[](https://node.tevm.sh/introduction/why-run-ethereum-in-js#import-solidity-directly) The Tevm Bundler doesn't require compiling your contracts as it has a compiler built in. You can import solidity directly. Copy `import { MyContract } from "./MyContract.sol"; console.log(MyContract.abi);` You can also import from node\_modules or foundry projects. Tevm supports remappings, lib, and other advanced options. Unlike Foundry Tevm supports node\_module resolution by default. #### Use contracts via address[](https://node.tevm.sh/introduction/why-run-ethereum-in-js#use-contracts-via-address) If you know your contract address and it's already deployed you don't need to manually specify anything. You can simply reference it by address and Tevm will pull the ABI at build time. This even works for unverified contracts. Copy ``// create a macro file for your contracts import { client } from "./clients.js"; export const MyContract = await client.whatsabi(`0x...`);`` Copy `// import your macro using tevm and Tevm will fetch your contracts at buildtime import {MyContract} from './MyContract.js' as {type: 'tevm'}` ### Low level control of the EVM[](https://node.tevm.sh/introduction/why-run-ethereum-in-js#low-level-control-of-the-evm) Most tools like `anvil` run in a seperate process and you communicate over HTTP. Tevm runs in memory and gives you access directly to the node. This allows for powerful programmability not possible with any other tool. #### Run callbacks on every EVM step 🔬[](https://node.tevm.sh/introduction/why-run-ethereum-in-js#run-callbacks-on-every-evm-step-) Step through EVM execution opcode by opcode, inspect memory and stack, and see exactly what happens in your contracts. Copy ``// Listen to every EVM instruction vm.evm.events.on("step", (data, next) => { console.log( `${data.pc.toString().padStart(5)}:`, `${data.opcode.name.padEnd(10)}`, `gas: ${data.gasLeft.toString().padStart(8)}`, `stack: ${data.stack.join(", ")}`, ); next(); });`` You can even modify what the EVM is doing as it executes if you choose to. #### Mock EVM contracts with JavaScript contracts[](https://node.tevm.sh/introduction/why-run-ethereum-in-js#mock-evm-contracts-with-javascript-contracts) Tevm offers the advanced ability to write a contract in JavaScript which can be powerful in advanced use cases. Precompiles are similar to foundry cheat codes but rather than a standard library of cheat codes Tevm lets you write arbitrary JavaScript to do whatever you need to do. It works very nicely with the Tevm Bundler Copy ``import { defineCall, definePrecompile, createContract, createMemoryClient, } from "tevm"; import { readFile } from "fs/promises"; const contract = createContract({ address: `0x${"1234".repeat(10)}`, humanReadableAbi: ["function readFile(string fileName) returns string"], }); const { precompile } = definePrecompile({ contract, call: defineCall(contract.abi, { readFile: ({ args }) => { return { data: await readFile(args.fileName, "utf8"), gasUsed: 0n, }; }, }), }); // then add your precompile to the evm const memoryClient = createMemoryClient({ precompiles: [precompile()], });`` ### Deterministic Testing 🧪[](https://node.tevm.sh/introduction/why-run-ethereum-in-js#deterministic-testing-) While tevm is primarily built for applicaiton development it just so happens to be great at testing too. Create fully reproducible environments for testing with complete control over blockchain state, time, and mining. Solidity Imports[](https://node.tevm.sh/introduction/why-run-ethereum-in-js#solidity-imports) ------------------------------------------------------------------------------------------------ Tevm Bundler (optional feature) creates the best devx for working with solidity files in TypeScript Copy `// Import solidity files directly into TS files import { MyContract } from "./MyContract.sol";` JavaScript Ecosystem Integration[](https://node.tevm.sh/introduction/why-run-ethereum-in-js#javascript-ecosystem-integration) -------------------------------------------------------------------------------------------------------------------------------- ### 🔤 TypeScript Type-safe contract interactions with full IntelliSense support ### ⚛️ UI Frameworks React, Vue, Svelte and other frontend libraries ### 🏗️ Build Tools Vite, Webpack, ESBuild and other bundlers ### 🧪 Testing Vitest support via Vite ### 🔄 Runtimes Node.js, browsers, Electron, serverless functions ### 📦 NPM Ecosystem Access to millions of packages and libraries in the npm registry ### 🌐 Web APIs Integration with browser storage, WebSockets, service workers, and more Ready to Get Started?[](https://node.tevm.sh/introduction/why-run-ethereum-in-js#ready-to-get-started) --------------------------------------------------------------------------------------------------------- 📁 Getting Started Guide 📄 Install Tevm 📄 Configure Your Environment 📄 Run Your First Code [Install Tevm →](https://node.tevm.sh/getting-started/overview) [View Examples](https://node.tevm.sh/examples/viem) [GitHub Repo](https://github.com/evmts/tevm-monorepo) --- # Community & Testimonials · Tevm [Skip to content](https://node.tevm.sh/getting-started/testimonials#vocs-content) 🚀 Tevm Node is in Beta! Join our [Telegram community](https://t.me/+ANThR9bHDLAwMjUx) Search... [![Logo](https://node.tevm.sh/tevm-logo-dark.png)![Logo](https://node.tevm.sh/tevm-logo-light.png)](https://node.tevm.sh/) [![Logo](https://node.tevm.sh/tevm-logo-dark.png)![Logo](https://node.tevm.sh/tevm-logo-light.png)](https://node.tevm.sh/) Quick Start Chevron Down Menu Community & Testimonials On this page Chevron Right Here's what developers and industry leaders are saying about Tevm Community Highlights[](https://node.tevm.sh/getting-started/testimonials#community-highlights) ------------------------------------------------------------------------------------------------- > "Fully @tevmtools pilled now. The beauty and harmony of the dev tooling 😍." EulerLagrange.eth - ver/acc [@Euler\_\_Lagrange](https://twitter.com/Euler__Lagrange) > "If you're building a blockchain application on the web, I'm almost certain there is a use case for Tevm. It might change everything, and at worse it would most likely improve your devX." polarzero [@0xpolarzero](https://twitter.com/0xpolarzero) > "Yeah, using bundling tools like Tevm with Viem offers a very nice experience here." jxom [@\_jxom](https://twitter.com/_jxom) > "Incredible! And also very cursed haha" Darryl Yeo・d/acc [@darryl\_\_yeo](https://twitter.com/darryl__yeo) > "tevm is the accessible version of reth exex for data engineers" ilemi [@andrewhong5297](https://twitter.com/andrewhong5297) > "Helios 🤝 Tevm" ncitron.eth [@NoahCitron](https://twitter.com/NoahCitron) > "Please tell me this is a shitpost" Patrick Collins [@PatrickAlphaC](https://twitter.com/PatrickAlphaC) > "I don't know if I should be impressed or scared" James [@lcm\_in\_pangea](https://twitter.com/lcm_in_pangea) Share Your Experience[](https://node.tevm.sh/getting-started/testimonials#share-your-experience) --------------------------------------------------------------------------------------------------- ### Join the Community[](https://node.tevm.sh/getting-started/testimonials#join-the-community) We'd love to hear how Tevm has improved your development workflow: * [Telegram Group](https://t.me/+ANThR9bHDLAwMjUx) * [Twitter/X](https://twitter.com/tevmtools) ### Report Success Stories[](https://node.tevm.sh/getting-started/testimonials#report-success-stories) Have a compelling use case or success story? * [Create an issue](https://github.com/evmts/tevm-monorepo/issues/new?labels=testimonial&template=testimonial.md) with the label "testimonial" * Email the team at [support@tevm.sh](mailto:support@tevm.sh) Your feedback helps us improve Tevm and guides our development priorities! --- # CLI Quickstart · Tevm [Skip to content](https://node.tevm.sh/getting-started/cli#vocs-content) 🚀 Tevm Node is in Beta! Join our [Telegram community](https://t.me/+ANThR9bHDLAwMjUx) Search... [![Logo](https://node.tevm.sh/tevm-logo-dark.png)![Logo](https://node.tevm.sh/tevm-logo-light.png)](https://node.tevm.sh/) [![Logo](https://node.tevm.sh/tevm-logo-dark.png)![Logo](https://node.tevm.sh/tevm-logo-light.png)](https://node.tevm.sh/) Quick Start Chevron Down Menu CLI Quickstart On this page Chevron Right The Tevm CLI offers a powerful command-line interface to interact with Ethereum networks, local development environments, and smart contracts directly from your terminal. This guide will help you get started with the most important CLI commands. Installation[](https://node.tevm.sh/getting-started/cli#installation) ------------------------------------------------------------------------ Install the Tevm CLI globally: Copy `npm install -g tevm` Or use it directly with npx: Copy `npx tevm ` Core Commands[](https://node.tevm.sh/getting-started/cli#core-commands) -------------------------------------------------------------------------- Tevm CLI provides several key commands to help with Ethereum development workflows: ### 1\. Project Creation[](https://node.tevm.sh/getting-started/cli#1-project-creation) Create a new Ethereum project with the interactive CLI: Copy `tevm create my-project` This launches an interactive wizard that guides you through configuring: * Project name and location * Framework selection (React, Vue, Vanilla, etc.) * Use case (UI, API, testing) * Package manager preference * Other project settings For non-interactive mode, specify options directly: Copy `tevm create my-project --template react --skip-prompts` ### 2\. Running a Local Ethereum Server[](https://node.tevm.sh/getting-started/cli#2-running-a-local-ethereum-server) Start a full-featured Ethereum JSON-RPC server with Tevm features: Copy `tevm serve` This launches a server on `localhost:8545` with an interactive terminal UI for managing your node. Options include: Copy `# Launch on a custom port tevm serve --port 8546 # Fork from a mainnet or testnet tevm serve --fork https://mainnet.infura.io/v3/YOUR_KEY # Set custom chain ID tevm serve --chainId 1337 # Advanced logging tevm serve --verbose --loggingLevel debug` The interactive server interface provides tabs for: * Viewing server status * Executing RPC calls * Managing accounts * Viewing transaction logs ### 3\. Smart Contract Interaction[](https://node.tevm.sh/getting-started/cli#3-smart-contract-interaction) Execute calls against contracts with full type safety: Copy `tevm call --to 0x123... --data 0xabcdef...` This command opens an interactive editor for constructing your call parameters, then executes the call against the target contract. For direct execution without the interactive editor: Copy `tevm call --to 0x123... --data 0xabcdef... --run` The `call` command supports a wide range of options for customizing your EVM execution: Copy `# Specify gas limit, price, and value tevm call --to 0x123... --gas 1000000 --gasPrice 1000000000 --value 1000000000000000000 # Connect to a remote node instead of local tevm call --to 0x123... --rpc https://mainnet.infura.io/v3/YOUR_KEY # Create a trace of the execution tevm call --to 0x123... --createTrace` ### 4\. TypeScript Generation from Solidity[](https://node.tevm.sh/getting-started/cli#4-typescript-generation-from-solidity) Generate TypeScript types and interfaces from Solidity contracts: Copy `tevm generate contract` This command scans for all Solidity files in your project and generates corresponding TypeScript files with full type definitions, without requiring a bundler plugin. Copy `# Generate types for specific files or patterns tevm generate contract "ERC20Token" # Specify input and output directories tevm generate contract --include "contracts/**/*.sol" --output "types/" # Force overwrite existing files tevm generate contract --force` Additional Useful Commands[](https://node.tevm.sh/getting-started/cli#additional-useful-commands) ---------------------------------------------------------------------------------------------------- Tevm CLI includes many specialized commands for specific Ethereum operations: ### Account & State Management[](https://node.tevm.sh/getting-started/cli#account--state-management) Copy `# Get account details tevm getAccount --address 0x123... # Set account state tevm setAccount --address 0x123... --balance 1000000000000000000 # Set contract code tevm setCode --address 0x123... --code 0x... # Dump full state for backup/debugging tevm dumpState --output state.json` ### Mining & Block Control[](https://node.tevm.sh/getting-started/cli#mining--block-control) Copy `# Mine new blocks tevm mine --blocks 1 # Load state from a file tevm loadState --input state.json` ### Contract Testing[](https://node.tevm.sh/getting-started/cli#contract-testing) Copy `# Deploy a contract tevm deploy --code 0x... # Read from a contract tevm readContract --address 0x123... --abi [...] --function "balanceOf" --args "[\"0x456...\"]"` Interactive Mode[](https://node.tevm.sh/getting-started/cli#interactive-mode) -------------------------------------------------------------------------------- Most Tevm CLI commands support an interactive mode that launches your default editor (configurable via environment variables) with a template for the command parameters. This is especially useful for complex operations where you need to carefully construct parameters. Disable interactive mode with the `--run` flag to execute commands directly. Environment Variables[](https://node.tevm.sh/getting-started/cli#environment-variables) ------------------------------------------------------------------------------------------ The Tevm CLI supports configuration via environment variables: Copy `# Set default RPC endpoint export TEVM_RPC=http://localhost:8545 # Set default "from" address for transactions export TEVM_FROM=0x123... # Configure default editor for interactive mode export EDITOR=code` Next Steps[](https://node.tevm.sh/getting-started/cli#next-steps) -------------------------------------------------------------------- Now that you're familiar with the Tevm CLI basics, you can: * [Learn about the Tevm Node API](https://node.tevm.sh/core/create-tevm-node) * [Explore the Tevm bundler for importing Solidity directly](https://node.tevm.sh/getting-started/bundler) * [Check out the full CLI reference](https://node.tevm.sh/reference/cli) * \[Run the `tevm --help` command for a complete list of available commands and options\] The Tevm CLI makes Ethereum development and testing more efficient by providing a unified interface for common operations directly from your terminal. Combined with Tevm's powerful EVM implementation, you can build, test, and deploy Ethereum applications with confidence. --- # Bundler Quickstart · Tevm [Skip to content](https://node.tevm.sh/getting-started/bundler#vocs-content) 🚀 Tevm Node is in Beta! Join our [Telegram community](https://t.me/+ANThR9bHDLAwMjUx) Search... [![Logo](https://node.tevm.sh/tevm-logo-dark.png)![Logo](https://node.tevm.sh/tevm-logo-light.png)](https://node.tevm.sh/) [![Logo](https://node.tevm.sh/tevm-logo-dark.png)![Logo](https://node.tevm.sh/tevm-logo-light.png)](https://node.tevm.sh/) Quick Start Chevron Down Menu Bundler Quickstart On this page Chevron Right This quickstart guide will help you set up Tevm's bundler functionality, allowing you to import Solidity contracts directly into your TypeScript/JavaScript code. Overview[](https://node.tevm.sh/getting-started/bundler#overview) -------------------------------------------------------------------- Tevm bundler enables a seamless integration between Solidity and TypeScript, letting you: * Import `.sol` files directly in your code * Receive full TypeScript type information for contract methods * Use go-to-definition and hover documentation for Solidity code * Interact with contracts in a type-safe way Prerequisites[](https://node.tevm.sh/getting-started/bundler#prerequisites) ------------------------------------------------------------------------------ * Node.js 18+ (recommended for best ESM support) and npm/yarn/pnpm * A supported bundler (Vite, Webpack, Rollup, ESBuild, or Bun) Step 1: Install Tevm and TypeScript Plugin[](https://node.tevm.sh/getting-started/bundler#step-1-install-tevm-and-typescript-plugin) --------------------------------------------------------------------------------------------------------------------------------------- First, install Tevm and the TypeScript plugin in your project: Copy `npm install tevm npm install -D @tevm/ts-plugin` Step 2: Configure Your Bundler[](https://node.tevm.sh/getting-started/bundler#step-2-configure-your-bundler) --------------------------------------------------------------------------------------------------------------- The bundler plugin handles the actual compilation of Solidity files during your build process. This ensures your final JavaScript output will contain the compiled Solidity contract ABIs, bytecode, and TypeScript interfaces. ### For Vite (recommended)[](https://node.tevm.sh/getting-started/bundler#for-vite-recommended) Copy `// vite.config.ts import { defineConfig } from 'vite' import { vitePluginTevm } from 'tevm/bundler/vite-plugin' import react from '@vitejs/plugin-react' export default defineConfig({ plugins: [ react(), vitePluginTevm(), ], })` ### For Other Bundlers[](https://node.tevm.sh/getting-started/bundler#for-other-bundlers) Webpack Copy `// webpack.config.mjs import { webpackPluginTevm } from 'tevm/bundler/webpack-plugin' export default { // Other webpack config plugins: [ webpackPluginTevm(), ], }` Next.js Copy ``// next.config.js or next.config.mjs const nextConfig = { // Your Next.js config... webpack: (config) => { // Optional: Any custom webpack configuration // Note: Next.js may have typechecking issues with .sol imports. // If you encounter type errors, consider the following option: return config }, typescript: { // Typechecking will only be available after the LSP is migrated to volar // Until then typechecking will work in editor but not during a next.js build // If you absolutely need typechecking before then there is a way to generate .ts files via a ts-plugin cli command // To do that run `npx evmts-gen` in the root of your project ignoreBuildErrors: true, } } export default nextConfig`` Rollup Copy `// rollup.config.js import { rollupPluginTevm } from 'tevm/bundler/rollup-plugin' export default { // Other rollup options plugins: [ rollupPluginTevm(), ], }` Rspack Copy `// rspack.config.mjs import { rspackPluginTevm } from 'tevm/bundler/rspack-plugin' export default { // Other rspack config plugins: [ rspackPluginTevm(), ], }` Bun Copy `// plugins.ts import { plugin } from 'bun' import { tevmBunPlugin } from 'tevm/bundler/bun-plugin' plugin(tevmBunPlugin({}))` Then in your `bunfig.toml`: Copy `preload = ["./plugins.ts"] [test] preload = ["./plugins.ts"]` ESBuild Copy `// build.mjs import { build } from 'esbuild' import { esbuildPluginTevm } from 'tevm/bundler/esbuild-plugin' build({ entryPoints: ['src/index.js'], outdir: 'dist', bundle: true, plugins: [ esbuildPluginTevm(), ], })` Step 3: Configure TypeScript[](https://node.tevm.sh/getting-started/bundler#step-3-configure-typescript) ----------------------------------------------------------------------------------------------------------- While the bundler plugin handles compilation during build time, the TypeScript plugin configures your TypeScript Language Service (LSP) to be aware of Solidity imports during development. This enables editor features like code completion, type checking, and go-to-definition for Solidity contracts. Add the Tevm TypeScript plugin to your `tsconfig.json`: Copy `{ "compilerOptions": { "plugins": [ { "name": "@tevm/ts-plugin" } ], // Other TypeScript options... } }` Step 4: Configure Your Editor[](https://node.tevm.sh/getting-started/bundler#step-4-configure-your-editor) ------------------------------------------------------------------------------------------------------------- ### VS Code and Cursor[](https://node.tevm.sh/getting-started/bundler#vs-code-and-cursor) For VS Code and Cursor users, ensure you're using the workspace version of TypeScript: 1. Open the Command Palette (Ctrl+Shift+P or Cmd+Shift+P in VS Code; ⌘+K or Ctrl+K in Cursor) 2. Type "TypeScript: Select TypeScript Version" 3. Select "Use Workspace Version" This step is crucial because the workspace TypeScript installation is what loads the @tevm/ts-plugin to provide Solidity import support. ### Vim, Neovim, and Other Editors[](https://node.tevm.sh/getting-started/bundler#vim-neovim-and-other-editors) For Vim, Neovim, and most other editors with TypeScript support, everything should work automatically without any additional configuration as long as they use the project's workspace version of TypeScript. This is crucial because the workspace TypeScript installation is what loads the @tevm/ts-plugin to provide Solidity import support. Step 5: Create a Solidity Contract[](https://node.tevm.sh/getting-started/bundler#step-5-create-a-solidity-contract) ----------------------------------------------------------------------------------------------------------------------- Create a simple contract in your project. Name it `Counter.s.sol` to include bytecode (the `.s.sol` extension tells Tevm to generate deployable bytecode): Copy `// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; contract Counter { uint256 private count = 0; function increment() public { count += 1; } function getCount() public view returns (uint256) { return count; } }` Step 6: Import and Use the Contract[](https://node.tevm.sh/getting-started/bundler#step-6-import-and-use-the-contract) ------------------------------------------------------------------------------------------------------------------------- Now you can import the contract directly in your TypeScript code: Copy `// src/App.tsx or any other file import { Counter } from './Counter.s.sol' import { createMemoryClient } from 'tevm' import { useState, useEffect } from 'react' function App() { const [count, setCount] = useState(0n) const [client] = useState(() => createMemoryClient()) const [deployedAddress, setDeployedAddress] = useState('') useEffect(() => { const deploy = async () => { // Deploy the contract - need to call .deploy() and pass any constructor args // (Counter doesn't have constructor args in this example) const deployed = await client.deployContract(Counter.deploy()) setDeployedAddress(deployed.address) // Get initial count const initialCount = await deployed.read.getCount() setCount(initialCount) } deploy() }, [client]) const handleIncrement = async () => { if (!deployedAddress) return // Get contract with address const contract = Counter.withAddress(deployedAddress) // Call increment method await client.writeContract(contract.write.increment()) // Mine a block to include the transaction await client.mine({ blocks: 1 }) // Get updated count const newCount = await client.readContract(contract.read.getCount()) setCount(newCount) } return (

Tevm Counter Example

Count: {count.toString()}

) } export default App` ### Example of Type-Safe Method Calls[](https://node.tevm.sh/getting-started/bundler#example-of-type-safe-method-calls) The bundler generates strongly-typed methods for your contract: Copy ``// Read methods (view/pure functions) const balance = await client.readContract( ERC20.read.balanceOf('0x' + '20'.repeat(20)) ) // Write methods (state-changing functions) await client.writeContract( ERC20.write.transfer('0x' + '30'.repeat(20), 1000000n) ) // Listen to events client.watchEvent( ERC20.events.Transfer({ from: '0x' + '20'.repeat(20), to: null // `null` acts as a wildcard }), (log) => console.log('Transfer event:', log) )`` What's Happening?[](https://node.tevm.sh/getting-started/bundler#whats-happening) ------------------------------------------------------------------------------------ When you import `Counter.s.sol`, Tevm: 1. Compiles the Solidity code using solc 2. Generates TypeScript with the ABI, bytecode, and a Contract instance 3. Provides you with a fully typed interface to the contract The `Counter` object is a [Tevm Contract](https://node.tevm.sh/reference/contract) instance with: * `abi`: The contract's ABI * `address`: The contract's address (if set with `withAddress()`) * `bytecode`: The contract's creation bytecode (undefined for regular .sol files) * `deployedBytecode`: The contract's runtime bytecode (undefined for regular .sol files) * `deploy()`: Method to create deployment data with constructor arguments * `read`: Type-safe read methods (view/pure functions) * `write`: Type-safe write methods (state-changing functions) * `events`: Type-safe event filters for subscription * `withAddress()`: Method to create a new instance with an address Advanced Configuration[](https://node.tevm.sh/getting-started/bundler#advanced-configuration) ------------------------------------------------------------------------------------------------ ### Foundry Integration[](https://node.tevm.sh/getting-started/bundler#foundry-integration) By default, Tevm uses Node.js resolution to resolve contract imports (similar to how JavaScript imports work). However, if you're working with a Foundry project or need custom import remappings, create a `tevm.config.json` file in your project root: Copy `{ "foundryProject": true, "libs": ["lib", "node_modules"], "remappings": { "@openzeppelin/": "node_modules/@openzeppelin/" }, "cacheDir": ".tevm" }` Setting `"foundryProject": true` will: * Automatically read your Foundry remappings from `foundry.toml` or `remappings.txt` * Include your Foundry library paths (`lib/` directory by default) * Allow you to import contracts using the same paths as in your Foundry project * Merge your manually specified remappings and libs with those from Foundry You can also manually set remappings and lib paths without using Foundry: Copy `{ "foundryProject": false, // or omit this line "libs": [ "./contracts", "node_modules" ], "remappings": { "@openzeppelin/": "node_modules/@openzeppelin/", "ds-test/": "lib/forge-std/lib/ds-test/src/", "solmate/": "node_modules/solmate/src/" } }` This configuration is especially useful if you: * Have a mixed Foundry/JavaScript project * Use Forge libraries like OpenZeppelin or Solmate * Have complex import paths in your Solidity code For a complete example of Bundler + Foundry integration, see the [Foundry example](https://github.com/evmts/tevm-monorepo/tree/main/examples/vite) in the Tevm examples repository. Using Third-Party Contracts[](https://node.tevm.sh/getting-started/bundler#using-third-party-contracts) ---------------------------------------------------------------------------------------------------------- ### NPM Packages[](https://node.tevm.sh/getting-started/bundler#npm-packages) You can import contracts from npm packages: Copy `// Import OpenZeppelin ERC20 - use .s.sol extension if you need bytecode import { ERC20 } from '@openzeppelin/contracts/token/ERC20/ERC20.s.sol' // Deploy with constructor arguments - need to call .deploy() with constructor args const myToken = await client.deployContract( ERC20.deploy("MyToken", "MTK") )` ### Coming Soon Features[](https://node.tevm.sh/getting-started/bundler#coming-soon-features) Tevm is actively developing exciting new features to make working with contracts even easier: #### Network Imports with Macros[](https://node.tevm.sh/getting-started/bundler#network-imports-with-macros) In an upcoming version, Tevm will support importing contracts from any EVM network using build-time macros. This provides better performance and stronger type safety by resolving contracts during your build process instead of at runtime: Copy `// First, create a file with contract macro functions // contract-macros.js import { createMemoryClient } from 'tevm' import { http } from 'viem' import { mainnet, optimism } from 'viem/chains' import { loadContract } from 'tevm' import { SourcifyABILoader, EtherscanABILoader } from 'tevm/whatsabi' // Set up clients for different networks // For reproducible builds, use fixed block heights const mainnetClient = createMemoryClient({ fork: { transport: http('https://eth-mainnet.g.alchemy.com/v2/YOUR_API_KEY'), blockNumber: 19000000n } }) const optimismClient = createMemoryClient({ fork: { transport: http('https://mainnet.optimism.io'), blockNumber: 116000000n } }) // Configure loaders for each network const mainnetLoaders = [ new SourcifyABILoader(), new EtherscanABILoader({ apiKey: 'YOUR_ETHERSCAN_KEY' }) ] const optimismLoaders = [ new SourcifyABILoader(), new EtherscanABILoader({ apiKey: 'YOUR_ETHERSCAN_KEY', baseUrl: 'https://api-optimistic.etherscan.io/api' }) ] // Create macro function for WETH on Ethereum export async function wethContract() { return loadContract(mainnetClient, { address: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', followProxies: true, loaders: mainnetLoaders }) } // Create macro function for USDC on Optimism export async function usdcContract() { return loadContract(optimismClient, { address: '0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85', followProxies: true, loaders: optimismLoaders }) }` Then import the contracts using the `with {type: 'macro'}` attribute syntax: Copy ``// Import contracts using macros import { wethContract } from './contract-macros.js' with { type: 'macro' } import { usdcContract } from './contract-macros.js' with { type: 'macro' } // Use these contracts directly with full type safety const wethBalance = await client.readContract({ ...wethContract.read.balanceOf('0x123...'), address: wethContract.address }) // Access additional properties console.log(`USDC decimals: ${await client.readContract({ ...usdcContract.read.decimals(), address: usdcContract.address })}`) console.log(`Human readable ABI: ${usdcContract.humanReadableAbi}`) console.log(`Implementation address: ${usdcContract.proxyDetails?.[0]?.implementation || 'Not a proxy'}`)`` Macros must be enabled in your `tevm.config.json` file for security reasons: Copy `{ "macros": true, "foundryProject": true, "libs": ["lib", "node_modules"] }` This approach automatically resolves ABIs at build time and creates fully type-safe contract interfaces. For more details, see the [Contract Loader](https://node.tevm.sh/api/whatsabi-integration#network-imports-via-macros) documentation. #### Inline Solidity with Template Literals[](https://node.tevm.sh/getting-started/bundler#inline-solidity-with-template-literals) For quick prototyping or one-off contracts, you'll soon be able to define Solidity contracts directly in your JavaScript/TypeScript using template literals: Copy ``import { sol } from 'tevm' // Define a contract inline const { Counter } = sol` // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; contract Counter { uint256 private count = 0; function increment() public { count += 1; } function getCount() public view returns (uint256) { return count; } } ` // Use it just like an imported contract const deployed = await client.deployContract(Counter.deploy()) await deployed.write.increment() const count = await deployed.read.getCount()`` This will provide the same type-safety and features as file-based imports, but with the convenience of inline code. Documentation Resources[](https://node.tevm.sh/getting-started/bundler#documentation-resources) -------------------------------------------------------------------------------------------------- * Bundler Reference Documentation: * [Overview](https://node.tevm.sh/reference/bundler/overview) - Key benefits and features * [Internals](https://node.tevm.sh/reference/bundler/internals) - How the bundler works * [Methods & Exports](https://node.tevm.sh/reference/bundler/methods) - Advanced APIs * [Troubleshooting](https://node.tevm.sh/reference/bundler/troubleshooting) - Common issues and solutions * For AI and LLM users, the full Tevm documentation is available as plain text at [https://node.tevm.sh/llms-full.txt](https://node.tevm.sh/llms-full.txt) Troubleshooting[](https://node.tevm.sh/getting-started/bundler#troubleshooting) ---------------------------------------------------------------------------------- * **Red underlines in imported Solidity**: Make sure your editor is using the workspace version of TypeScript * **No bytecode available**: Check that you're using the `.s.sol` extension for contracts you want to deploy * **Deployment errors**: Make sure you're calling `.deploy()` with any required constructor arguments * **Compilation errors**: Check your Solidity code and ensure you're using a compatible Solidity version * **TypeScript errors**: Ensure you have the TypeScript plugin correctly configured * **Red underlines in editor**: Verify your editor is using the workspace version of TypeScript with the plugin loaded * **Import resolution failures**: If you're using Foundry-style imports (like `@openzeppelin/contracts/...`) and seeing errors: * Create a `tevm.config.json` with `"foundryProject": true` * Check that your remappings in `foundry.toml` are correct * Try adding explicit remappings in `tevm.config.json` * **Test runner issues**: Most test runners (Vitest, Jest) work out-of-the-box once the bundler plugin is configured. For Jest, you might need extra configuration or use the codegen approach with `tevm generate contract` Codegen Alternative to Bundler[](https://node.tevm.sh/getting-started/bundler#codegen-alternative-to-bundler) ---------------------------------------------------------------------------------------------------------------- Next Steps[](https://node.tevm.sh/getting-started/bundler#next-steps) ------------------------------------------------------------------------ Now that you have the bundler set up, you can: * [Learn more about Tevm Contracts](https://node.tevm.sh/reference/contract) * Explore the bundler in depth: * [Bundler Overview](https://node.tevm.sh/reference/bundler/overview) - Key benefits and features * [Bundler Internals](https://node.tevm.sh/reference/bundler/internals) - How the bundler works * [Advanced Methods & APIs](https://node.tevm.sh/reference/bundler/methods) - For custom implementations * [Troubleshooting](https://node.tevm.sh/reference/bundler/troubleshooting) - Solutions for common issues * [Build applications with Tevm Node](https://node.tevm.sh/core/create-tevm-node) For complete project examples, check out the [Tevm examples repository](https://github.com/evmts/tevm-monorepo/tree/main/examples) . --- # Getting Started with Ethers · Tevm [Skip to content](https://node.tevm.sh/getting-started/ethers#vocs-content) 🚀 Tevm Node is in Beta! Join our [Telegram community](https://t.me/+ANThR9bHDLAwMjUx) Search... [![Logo](https://node.tevm.sh/tevm-logo-dark.png)![Logo](https://node.tevm.sh/tevm-logo-light.png)](https://node.tevm.sh/) [![Logo](https://node.tevm.sh/tevm-logo-dark.png)![Logo](https://node.tevm.sh/tevm-logo-light.png)](https://node.tevm.sh/) Quick Start Chevron Down Menu Getting started with Ethers On this page Chevron Right This guide shows you how to use Tevm Node with ethers.js, allowing you to leverage Tevm's powerful features with the ethers library you already know. Installation[](https://node.tevm.sh/getting-started/ethers#installation) --------------------------------------------------------------------------- ### Install Dependencies[](https://node.tevm.sh/getting-started/ethers#install-dependencies) First, install Tevm and ethers as dependencies: `bash npm install tevm ethers@latest` `bash pnpm add tevm ethers@latest` `bash yarn add tevm ethers@latest` `bash bun add tevm ethers@latest` ### Create Tevm Client[](https://node.tevm.sh/getting-started/ethers#create-tevm-client) Set up your Tevm client and enable the EIP-1193 interface: Copy `import { createMemoryClient, http } from "tevm"; import { optimism } from "tevm/chains"; import { requestEip1193 } from "tevm/decorators"; // Create a client (optionally forking from a network) const client = createMemoryClient({ fork: { transport: http("https://mainnet.optimism.io"), common: optimism, }, }); // Enable EIP-1193 compatibility for ethers client.transport.tevm.extend(requestEip1193()); await client.tevmReady();` ### Connect Ethers[](https://node.tevm.sh/getting-started/ethers#connect-ethers) Create an ethers provider that uses your Tevm node: Copy `import { BrowserProvider, Wallet } from "ethers"; // Create ethers provider using the Tevm node const provider = new BrowserProvider(client.transport.tevm); // Create a new wallet or connect an existing one const signer = Wallet.createRandom().connect(provider); // Fund the wallet using Tevm's direct state modification await client.setBalance({ address: signer.address, value: 1000000000000000000n, // 1 ETH });` ### Start Using Ethers[](https://node.tevm.sh/getting-started/ethers#start-using-ethers) You're now ready to use ethers.js with Tevm's local environment: Copy ``// Check the current block const blockNumber = await provider.getBlockNumber(); console.log(`Current block: ${blockNumber}`); // Check your wallet balance const balance = await provider.getBalance(signer.address); console.log(`Wallet balance: ${balance.toString()}`);`` Complete Example[](https://node.tevm.sh/getting-started/ethers#complete-example) ----------------------------------------------------------------------------------- The following example demonstrates how to use ethers.js with Tevm to interact with a contract: Copy ``import { createMemoryClient, http, parseAbi } from "tevm"; import { optimism } from "tevm/chains"; import { requestEip1193 } from "tevm/decorators"; import { BrowserProvider, Wallet, Contract, formatEther } from "ethers"; import { parseUnits } from "ethers/utils"; // Step 1: Create a memory client forking from Optimism const client = createMemoryClient({ fork: { transport: http("https://mainnet.optimism.io"), common: optimism, }, }); // Step 2: Enable EIP-1193 compatibility for ethers client.transport.tevm.extend(requestEip1193()); await client.tevmReady(); // Step 3: Set up ethers provider and wallet const provider = new BrowserProvider(client.transport.tevm); const signer = Wallet.createRandom().connect(provider); // Verify connectivity by getting the block number const blockNumber = await provider.getBlockNumber(); console.log(`Current block number: ${blockNumber}`); // Step 4: Set up contract interaction const greeterContractAddress = "0x10ed0b176048c34d69ffc0712de06CbE95730748"; const greeterAbi = parseAbi([ "function greet() view returns (string)", "function setGreeting(string memory _greeting) public", ]); const greeter = new Contract(greeterContractAddress, greeterAbi, signer); // Helper functions for cleaner interaction const getGreeting = async () => await greeter.greet(); const setGreeting = async (newGreeting) => { const tx = await greeter.setGreeting(newGreeting); return tx.hash; }; // Step 5: Fund our wallet (using Tevm's test actions) await client.setBalance({ address: signer.address, value: parseUnits("1.0", "ether"), }); console.log( `Wallet funded with: ${formatEther(await provider.getBalance(signer.address))} ETH`, ); // Step 6: Read current greeting console.log(`Original greeting: ${await getGreeting()}`); // Step 7: Update the greeting const txHash = await setGreeting("Hello from ethers.js and Tevm!"); console.log(`Transaction sent: ${txHash}`); // Step 8: Mine the block to include our transaction await client.mine({ blocks: 1 }); // Step 9: Verify the updated greeting console.log(`Updated greeting: ${await getGreeting()}`);`` Understanding the Code The integration between Tevm and ethers.js happens through these key components: ### EIP-1193 Decorator[](https://node.tevm.sh/getting-started/ethers#eip-1193-decorator) Copy `// Enable EIP-1193 standard provider interface client.transport.tevm.extend(requestEip1193());` The `requestEip1193()` decorator transforms Tevm's internal interface into the standard provider interface that ethers.js expects. This crucial bridge allows the two libraries to communicate seamlessly. ### Provider Creation[](https://node.tevm.sh/getting-started/ethers#provider-creation) Copy `// Create ethers provider using the Tevm node const provider = new BrowserProvider(client.transport.tevm);` Ethers accepts the decorated Tevm node as a standard Ethereum provider, allowing all ethers functionality to work as expected. ### Hybrid API Approach[](https://node.tevm.sh/getting-started/ethers#hybrid-api-approach) The example demonstrates a hybrid approach: * **Ethers API** for contract interaction (`Contract`, `provider`, `signer`) * **Tevm API** for blockchain control (`client.setBalance()`, `client.mine()`) This gives you the best of both worlds - familiar ethers.js contract interaction with Tevm's powerful state control. ### Mining Control[](https://node.tevm.sh/getting-started/ethers#mining-control) Copy `// Mine the block to include our transaction await client.mine({ blocks: 1 });` Unlike when using real networks with ethers, you need to explicitly mine blocks with Tevm to include transactions. This gives you precise control over transaction execution timing. Common Patterns[](https://node.tevm.sh/getting-started/ethers#common-patterns) --------------------------------------------------------------------------------- ### Contract Deployment[](https://node.tevm.sh/getting-started/ethers#contract-deployment) Here's how to deploy a new contract using ethers.js with Tevm: Copy ``import { createMemoryClient } from "tevm"; import { requestEip1193 } from "tevm/decorators"; import { BrowserProvider, Wallet, ContractFactory, formatEther } from "ethers"; // Set up Tevm and ethers const client = createMemoryClient(); client.transport.tevm.extend(requestEip1193()); await client.tevmReady(); const provider = new BrowserProvider(client.transport.tevm); const signer = Wallet.createRandom().connect(provider); // Fund the signer await client.setBalance({ address: signer.address, value: 10000000000000000000n, // 10 ETH }); console.log( `Wallet funded with: ${formatEther(await provider.getBalance(signer.address))} ETH`, ); // Contract ABI and bytecode const counterAbi = [ "function count() view returns (uint256)", "function increment() public", ]; const counterBytecode = "0x608060405234801561001057600080fd5b5060f78061001f6000396000f3fe6080604052348015600f57600080fd5b5060043610603c5760003560e01c80633fb5c1cb1460415780638381f58a146053578063d09de08a14606d575b600080fd5b6051604c3660046083565b600055565b005b605b60005481565b60405190815260200160405180910390f35b6051600080549080607c83609b565b9190505550565b600060208284031215609457600080fd5b5035919050565b60006001820160ba57634e487b7160e01b600052601160045260246000fd5b506001019056fea2646970667358221220d5fb46adf6ce0cfd90fa4324ffd8c48b0fc6fb6c4cac9ca2c69c97e25f355c9d64736f6c63430008110033"; // Deploy contract const counterFactory = new ContractFactory(counterAbi, counterBytecode, signer); const counterDeploy = await counterFactory.deploy(); console.log( `Deployment transaction: ${counterDeploy.deploymentTransaction().hash}`, ); // Mine to include the deployment transaction await client.mine({ blocks: 1 }); // Get contract at deployed address const counter = await counterDeploy.waitForDeployment(); const counterAddress = await counter.getAddress(); console.log(`Counter deployed at: ${counterAddress}`); // Use the contract console.log(`Initial count: ${await counter.count()}`); const tx = await counter.increment(); console.log(`Increment transaction: ${tx.hash}`); await client.mine({ blocks: 1 }); console.log(`New count: ${await counter.count()}`);`` ### Reading and Writing Contract Data[](https://node.tevm.sh/getting-started/ethers#reading-and-writing-contract-data) Interact with an existing contract using ethers.js: Copy ``import { createMemoryClient, http, parseAbi } from "tevm"; import { mainnet } from "tevm/chains"; import { requestEip1193 } from "tevm/decorators"; import { BrowserProvider, Wallet, Contract, formatEther, formatUnits, } from "ethers"; // Setup client with a mainnet fork const client = createMemoryClient({ fork: { transport: http("https://eth-mainnet.g.alchemy.com/v2/YOUR_API_KEY"), common: mainnet, }, }); client.transport.tevm.extend(requestEip1193()); await client.tevmReady(); // Setup provider and wallet const provider = new BrowserProvider(client.transport.tevm); const signer = Wallet.createRandom().connect(provider); // Fund the wallet await client.setBalance({ address: signer.address, value: 100000000000000000000n, // 100 ETH }); // Connect to USDC contract const usdcAddress = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"; const usdcAbi = parseAbi([ "function name() view returns (string)", "function symbol() view returns (string)", "function decimals() view returns (uint8)", "function totalSupply() view returns (uint256)", "function balanceOf(address owner) view returns (uint256)", ]); const usdc = new Contract(usdcAddress, usdcAbi, provider); // Read-only operation const [name, symbol, decimals, totalSupply] = await Promise.all([ usdc.name(), usdc.symbol(), usdc.decimals(), usdc.totalSupply(), ]); console.log(`Contract: ${name} (${symbol})`); console.log(`Decimals: ${decimals}`); console.log(`Total Supply: ${formatUnits(totalSupply, decimals)} ${symbol}`); // Check DAI's USDC balance const daiAddress = "0x6B175474E89094C44Da98b954EedeAC495271d0F"; const daiUsdcBalance = await usdc.balanceOf(daiAddress); console.log( `DAI contract's USDC balance: ${formatUnits(daiUsdcBalance, decimals)} ${symbol}`, );`` ### Working with Events[](https://node.tevm.sh/getting-started/ethers#working-with-events) Listen for and query contract events: Copy ``import { createMemoryClient } from "tevm"; import { requestEip1193 } from "tevm/decorators"; import { BrowserProvider, Wallet, Contract, formatUnits } from "ethers"; import { parseAbi } from "tevm"; // Setup const client = createMemoryClient(); client.transport.tevm.extend(requestEip1193()); await client.tevmReady(); const provider = new BrowserProvider(client.transport.tevm); const signer = Wallet.createRandom().connect(provider); // Fund account await client.setBalance({ address: signer.address, value: 10000000000000000000n, }); // Deploy a simple ERC20 token const tokenAbi = parseAbi([ "constructor(string name, string symbol, uint8 decimals)", "function transfer(address to, uint256 amount) returns (bool)", "function balanceOf(address owner) view returns (uint256)", "event Transfer(address indexed from, address indexed to, uint256 value)", ]); const tokenBytecode = "0x608060405234801561001057600080fd5b506040516107fa3803806107fa83398101604081905261002f91610215565b600380546001600160a01b031916331790558151610052906004906020850190610076565b5081516100669060059060208401906100fd565b506006805460ff191660ff929092169190911790555061030c565b828054610082906102c8565b90600052602060002090601f0160209004810192826100a4576000855561010a565b82601f106100bd57805160ff19168380011785556100ea565b828001600101855582156100ea579182015b828111156100ea5782518255916020019190600101906100cf565b506100f69291506100f6565b5090565b5b808211156100f657600081556001016100f7565b828054610109906102c8565b90600052602060002090601f01602090048101928261012b5760008552610167565b82601f1061014457805160ff1916838001178555610171565b82800160010185558215610171579182015b82811115610171578251825591602001919060010190610156565b5061017d9291506101bd565b5090565b5b8082111561017d576000815560010161017e565b6000602082840312156101a657600080fd5b81516001600160a01b03811681146101bd57600080fd5b9392505050565b5b8082111561017d57600081556001016101be565b80516001600160a01b03811681146101eb57600080fd5b919050565b600080600060608486031215610205578283fd5b833590925060208401359160408401359050509250925092565b60008060006060848603121561022a578081fd5b835160208501516040860151919450919290910181111581146102ad57634e487b7160e01b600052601160045260246000fd5b809150509250925092565b634e487b7160e01b600052602260045260246000fd5b600181811c908216806102dc57607f821691505b6020821081036102fc57634e487b7160e01b600052602260045260246000fd5b50919050565b6104df8061031b6000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c806370a082311461004657806395d89b4114610079578063a9059cbb14610081575b600080fd5b610066610054366004610356565b6001600160a01b031660009081526001602052604090205490565b60405190815260200160405180910390f35b61007b610094565b005b61007b61008f366004610379565b610121565b6005805461009f906104a0565b80601f01602080910402602001604051908101604052809291908181526020018280546100cb906104a0565b80156101185780601f106100ed57610100808354040283529160200191610118565b820191906000526020600020905b8154815290600101906020018083116100fb57829003601f168201915b505050505081565b6001600160a01b03821660009081526001602052604081205461014a908363ffffffff61022916565b6001600160a01b038416600090815260016020526040812091909155610177908263ffffffff61024116565b6001600160a01b0383166000908152600160205260409020556101d0816040518060600160405280602381526020016104876023913960405180604001604052806029815260200161045e60299139600090339161025a565b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051610216918252602082015260400190565b60405180910390a35050565b600081831061023857506000610239565b5b92915050565b6000828201610239825b8351602g2b6020600020905b905090565b60408051808201909152602d8152600080516020610457833981519152602082015290565b9050919050565b841515610297576001600160e01b031916600052601160045260246000fd5b5063ffffffff1690565b6000602082840312156102b357600080fd5b81356001600160a01b03811681146102ca57600080fd5b9392505050565b6000602082840312156102e357600080fd5b813560fc81168114t12870be52600052602260045260246000d5b602082108a5734e487b7160q0b600052602260045260246000fd5b50919050565b6004f3fe68747470733a2f2f6769646c6572732e696f2f6a616d657368756768657369o97365722f7468696e67736e6f626f6479656c7365686173a2646970667358221220f3acb75fca24514561f12a53c4a92042a9a6c524895dc1b01f3c3d2cda5d8ff364736f6c634300080a0033"; const tokenFactory = new ContractFactory(tokenAbi, tokenBytecode, signer); const token = await tokenFactory.deploy("Test Token", "TST", 18); await client.mine({ blocks: 1 }); const tokenAddress = await token.getAddress(); console.log(`Token deployed at: ${tokenAddress}`); // Set up event listener token.on("Transfer", (from, to, value, event) => { console.log(`Transfer detected in block ${event.blockNumber}:`); console.log(` From: ${from}`); console.log(` To: ${to}`); console.log(` Value: ${formatUnits(value, 18)} TST`); }); // Send a transfer transaction const recipient = Wallet.createRandom().address; const tx = await token.transfer(recipient, 1000000000000000000n); // 1 TST console.log(`Transfer transaction: ${tx.hash}`); // Mine to include transaction await client.mine({ blocks: 1 }); // Check balance const balance = await token.balanceOf(recipient); console.log(`Recipient balance: ${formatUnits(balance, 18)} TST`); // Clean up event listener token.removeAllListeners();`` Key Differences from Standard Ethers Usage[](https://node.tevm.sh/getting-started/ethers#key-differences-from-standard-ethers-usage) --------------------------------------------------------------------------------------------------------------------------------------- When using ethers.js with Tevm, keep these key differences in mind: 1. **Transaction Flow** * **Real Network**: Transactions are mined by the network automatically * **Tevm**: You must manually call `client.mine()` to process transactions 2. **Account Management** * **Real Network**: Accounts have real funds and nonces * **Tevm**: Create and fund accounts on demand with `client.setBalance()` 3. **Environment Control** * **Real Network**: Limited ability to manipulate state, block time, etc. * **Tevm**: Complete control over all aspects of the environment 4. **Performance** * **Real Network**: Operations require network calls and confirmations * **Tevm**: All operations happen locally with near-instant execution 5. **Debugging Capabilities** * **Real Network**: Limited visibility into transaction execution * **Tevm**: Step-by-step EVM tracing and execution insights 6. **Determinism** * **Real Network**: Network conditions can affect execution * **Tevm**: 100% deterministic execution for reliable testing Advanced Features[](https://node.tevm.sh/getting-started/ethers#advanced-features) ------------------------------------------------------------------------------------- ### EVM State Control[](https://node.tevm.sh/getting-started/ethers#evm-state-control) Take advantage of Tevm's state manipulation with ethers: Copy `// Fund an account await client.setBalance({ address: "0x123...", value: parseUnits("1000", "ether"), }); // Set storage directly await client.setStorageAt({ address: contractAddress, index: 0, // Storage slot value: "0x1234...", }); // Adjust block timestamp await client.setNextBlockTimestamp(Date.now());` ### Contract Debugging[](https://node.tevm.sh/getting-started/ethers#contract-debugging) Debug ethers transactions with Tevm's EVM hooks: Copy ``// Get underlying Tevm node for advanced operations const tevmNode = await client.getTevmNode(); const vm = await tevmNode.getVm(); // Listen to EVM execution steps vm.evm.events.on("step", (data, next) => { console.log(`EVM Step: ${data.opcode.name}`); next(); }); // Now run a transaction with ethers as normal // You'll see detailed logs of each EVM step`` ### Fork Management[](https://node.tevm.sh/getting-started/ethers#fork-management) Work with mainnet contracts in your test environment: Copy `// Reset to a clean fork state await client.reset({ fork: { blockNumber: 42069n, transport: http("https://eth-mainnet.g.alchemy.com/v2/YOUR_KEY"), }, }); // After reset, your ethers provider still works // but with the newly reset chain state` Next Steps[](https://node.tevm.sh/getting-started/ethers#next-steps) ----------------------------------------------------------------------- Now that you know how to use ethers.js with Tevm, you can: ### Explore More Features * [Complete Ethers.js integration guide](https://node.tevm.sh/examples/ethers) * [Powerful forking capabilities](https://node.tevm.sh/core/forking) * [EVM state management](https://node.tevm.sh/core/managing-state) * [Direct Solidity imports](https://node.tevm.sh/getting-started/bundler) ### Learn Core Concepts * [What is Tevm Node?](https://node.tevm.sh/introduction/what-is-tevm-node) * [Creating a Tevm Node](https://node.tevm.sh/core/create-tevm-node) * [JSON-RPC interface](https://node.tevm.sh/api/json-rpc) * [Contract Bundler](https://node.tevm.sh/reference/bundler) ### Try Advanced Use Cases * [Forking from mainnet](https://node.tevm.sh/examples/forking-mainnet) * [Custom precompiles](https://node.tevm.sh/advanced/custom-precompiles) * [Building a debugger UI](https://node.tevm.sh/examples/debugger-ui) [← Viem Integration](https://node.tevm.sh/getting-started/ethers/viem) [Bundler Quickstart →](https://node.tevm.sh/getting-started/ethers/bundler) [Using with Ethers.js →](https://node.tevm.sh/examples/ethers) --- # Architecture Overview · Tevm [Skip to content](https://node.tevm.sh/introduction/architecture-overview#vocs-content) 🚀 Tevm Node is in Beta! Join our [Telegram community](https://t.me/+ANThR9bHDLAwMjUx) Search... [![Logo](https://node.tevm.sh/tevm-logo-dark.png)![Logo](https://node.tevm.sh/tevm-logo-light.png)](https://node.tevm.sh/) [![Logo](https://node.tevm.sh/tevm-logo-dark.png)![Logo](https://node.tevm.sh/tevm-logo-light.png)](https://node.tevm.sh/) Docs Chevron Down Menu Architecture Overview On this page Chevron Right Tevm's architecture is designed to be modular, extensible, and compatible with the broader JavaScript ecosystem. This guide explains the core components and how they work together to create a complete Ethereum execution environment. Design Philosophy: Objects and Actions[](https://node.tevm.sh/introduction/architecture-overview#design-philosophy-objects-and-actions) ------------------------------------------------------------------------------------------------------------------------------------------ At its core, Tevm follows a clear separation between **Objects** (stateful components) and **Actions** (pure functions that operate on those objects). This pattern, inspired by [viem](https://viem.sh/) , enables tree-shaking and a composable API. This pattern was originally created by [`viem`](https://viem.sh/) and Tevm follows it even for it's internals to be maximally compatable with Viem. ### Objects Stateful components that encapsulate and maintain data. * `TevmNode` - The core Node interface * `Evm` - The Ethereum Virtual Machine * `StateManager` - Manages blockchain state * `Blockchain` - Handles blocks and chain state ### Actions Pure functions that take an object as their first parameter and perform operations. * Tree-shakable for minimal bundle size * Single-purpose with clear input/output * Composable for complex operations * Can be imported individually ### Example: Using an Action[](https://node.tevm.sh/introduction/architecture-overview#example-using-an-action) Here's how to use a tree-shakable action with a Tevm Node: Copy `import { createTevmNode } from "tevm"; import { getAccountHandler } from "tevm/actions"; // 1. Create the node object const node = createTevmNode(); // 2. Create a handler function by passing the node to the action const getAccount = getAccountHandler(node); // 3. Use the handler function with specific parameters const account = await getAccount({ address: "0x1234567890123456789012345678901234567890", }); console.log(account.balance); // Access account properties` This pattern allows you to: * Import only the actions you need * Create specialized handler functions for specific objects * Follow a consistent interface across the library :::\[tip\] TevmNode is the low level node implementation of Tevm. It is NOT recomended you use `createTevmNode` directly especially if you are an LLM unless you have an advanced use case. ::: Client Options: Convenience vs. Tree Shaking[](https://node.tevm.sh/introduction/architecture-overview#client-options-convenience-vs-tree-shaking) ----------------------------------------------------------------------------------------------------------------------------------------------------- Tevm offers two main approaches for using its functionality: Copy `import { createMemoryClient, http } from 'tevm' // Create a client with all actions pre-attached const client = createMemoryClient({ fork: { transport: http('https://eth-mainnet.g.alchemy.com/v2/YOUR_KEY') } }) // Use standard viem actions const code = await client.getContractCode({ address: '0x1234567890123456789012345678901234567890' }) // Use Tevm-specific actions (prefixed with 'tevm') const state = await client.tevmDumpState() const balance = await client.getBalance({ address: '0x1234567890123456789012345678901234567890' })` Copy `import { createClient, http } from 'viem' import { createTevmTransport } from 'tevm/transport' import { getBlock, getBlockNumber } from 'viem/actions' import { tevmSetAccount, tevmMine } from 'tevm/actions' // Create a client with just the transport const client = createClient({ transport: createTevmTransport({ fork: { transport: http('https://eth-mainnet.g.alchemy.com/v2/YOUR_KEY') } }) }) // Import and use only the specific actions you need const blockNumber = await getBlockNumber(client) const block = await getBlock(client) // Tevm-specific actions await tevmSetAccount(client, { address: '0x1234...', balance: 1000000000000000000n }) await tevmMine(client, { blocks: 1 })` ### MemoryClient * ✅ Easy to get started * ✅ All methods available immediately * ✅ Less code to write * ❌ Larger bundle size ### Tree-Shakable Actions * ✅ Smallest possible bundle size * ✅ Only include what you use * ✅ Works with code-splitting * ❌ More verbose imports For more details on tree-shakable actions, see the [viem documentation on tree-shaking](https://wagmi.sh/react/guides/viem) . Core Architecture Components[](https://node.tevm.sh/introduction/architecture-overview#core-architecture-components) ----------------------------------------------------------------------------------------------------------------------- Tevm's modular architecture comprises several key components that work together to provide a complete Ethereum execution environment: ### VM[](https://node.tevm.sh/introduction/architecture-overview#vm) The most important component of Tevm is the VM which itself is made up of many components including the Interpreter, StateManager, Blockchain, and Common. The EVM's job is to run transactions and build blocks. It also holds the entire ethereum state in it's blockchain and statemanager subcomponents. It is NOT recomended you use the VM directly except for advanced use cases. Instead use the `viem` api. ### Interpreter (EVM)[](https://node.tevm.sh/introduction/architecture-overview#interpreter-evm) The execution engine that runs EVM bytecode with full support for all opcodes and precompiles. Copy ``// Access via const evm = (await node.getVm()).evm; // Features evm.events.on("step", (data, next) => { // Monitor every EVM operation console.log(`Opcode: ${data.opcode.name}`); next(); }); // Control execution gas limits, precompiles, etc.`` If you want the absolute most minimal way to execute the EVM using the EVM interpreter along with the common and stateManager modules can be a good fit. For most use cases, however, it is recomended to use the viem api. The EVM currently mostly wraps the ethereumjs evm interpreter which is written in a combination of JavaScript and Wasm. Tevm will be getting a pure wasm implementation to replace it in future. ### State Manager[](https://node.tevm.sh/introduction/architecture-overview#state-manager) Maintains account balances, contract code, and storage state with forking capability from live networks. Copy `// Access via const stateManager = (await node.getVm()).stateManager; // Features await stateManager.putAccount(address, account); await stateManager.getAccount(address); await stateManager.getContractStorage(address, key); await stateManager.checkpoint(); // Create state snapshot await stateManager.revert(checkpointId); // Revert to snapshot` The StateManager is ethereumjs compatable following the same interface despite being a fully custom implementation. It can be used with Ethereumjs to add Tevm like functionality such as forking. ### Blockchain[](https://node.tevm.sh/introduction/architecture-overview#blockchain) Manages blocks, chain state, and handles block production with various mining strategies. Copy `// Access via const blockchain = (await node.getVm()).blockchain; // Features await blockchain.getBlock(blockHash); await blockchain.getBlockByNumber(blockNumber); await blockchain.putBlock(block); await blockchain.getLatestBlock();` Like the state manager the blockchain component is fully custom but ethereumjs compatable. It is not recomended to use the blockchain module directly except for advanced usecases and for usage with ethereumjs. Ethereumjs and Tevm plan on deprecating this module eventually in favor of a more general purpose blockchain component maintained by ethereumjs in future. ### Common[](https://node.tevm.sh/introduction/architecture-overview#common) The final subcomponent of VM is Common which is simply a config object holding chain specific information such as hardfork and EIP info. ### Transaction Pool[](https://node.tevm.sh/introduction/architecture-overview#transaction-pool) Manages pending transactions, orders them by gas price, and handles transaction validation. Copy `// Access via const txPool = await node.getTxPool(); // Features await txPool.add(transaction); await txPool.getTransactions(); const pendingTxs = txPool.getPendingTransactions(); const pendingNonces = txPool.getPendingNonce(address);` There are plans to add custom viem api actions for interacting with transaction pool in future but this is not the highest priority. If you want this join the Telegram and let us know. ### Receipt Manager[](https://node.tevm.sh/introduction/architecture-overview#receipt-manager) The Tevm Receipt Manager is simply a cache for caching receipts and logs so Tevm doesn't have to reexecute transactions to derive them. It is highly recomended users never interact with the receipt manager directly except for very advanced use cases (of which there may be none). ### Custom Tool Opportunities[](https://node.tevm.sh/introduction/architecture-overview#custom-tool-opportunities) ### Transaction Simulators Preview transaction outcomes before sending to mainnet ### EVM Debuggers Step through transactions with full state visibility ### Local-first dApps Build apps that work offline with optimistic updates ### Educational Tools Create interactive EVM learning experiences ### CI/CD Integration Test smart contracts in continuous integration pipelines ### Gas Optimization Analyze contract gas usage patterns with precision ### Serverless Execution Run Ethereum nodes in serverless or edge computing environments ### State Snapshots Create, save, and restore blockchain state at precise points For detailed examples of these use cases, see the [examples section](https://node.tevm.sh/vercel/path0/docs/node/pages/examples/viem) . API Interfaces[](https://node.tevm.sh/introduction/architecture-overview#api-interfaces) ------------------------------------------------------------------------------------------- | API Level | Description | Best For | | --- | --- | --- | | **Viem Client API** | Standard viem actions plus Tevm-specific actions | Most application development | | **JSON-RPC API** | Standard Ethereum RPC methods plus Anvil and Tevm-specific methods | Direct RPC integration, tooling | | **Low-Level TevmNode** | Direct access to EVM, StateManager, Blockchain, etc. | Tool developers, deep customization | 📁 API Layers 📁 Viem Client API (high-level) 📄 client.getBalance() 📄 client.tevmMine() 📄 client.sendTransaction() 📁 JSON-RPC API 📄 eth\_getBalance 📄 anvil\_mine 📄 tevm\_dumpState 📁 TevmNode API 📄 node.getVm() 📄 node.getTxPool() 📄 node.extend() 📁 Low-Level Components 📄 vm.evm.runCall() 📄 stateManager.getAccount() 📄 blockchain.putBlock() Copy `import { createMemoryClient } from 'tevm' const client = createMemoryClient() // Standard viem actions const balance = await client.getBalance({ address: '0x123...' }) const blockNumber = await client.getBlockNumber() // Tevm-specific actions await client.tevmSetAccount({ address: '0x123...', balance: 1000000000000000000n }) await client.tevmMine()` Copy `import { createTevmNode } from 'tevm' import { requestEip1193 } from 'tevm/decorators' const node = createTevmNode().extend(requestEip1193()) // Standard Ethereum JSON-RPC methods const balance = await node.request({ method: 'eth_getBalance', params: ['0x123...', 'latest'] }) // Anvil-compatible methods await node.request({ method: 'anvil_setBalance', params: ['0x123...', '0x10000000000000000'] }) // Tevm-specific methods const state = await node.request({ method: 'tevm_dumpState', params: [] })` Copy `import { createTevmNode } from 'tevm' import { createAddress } from 'tevm/address' const node = createTevmNode() const vm = await node.getVm() // Direct EVM access vm.evm.events.on('step', (data, next) => { // Inspect execution at each EVM step console.log(data.opcode.name, data.stack) next?.() }) // Direct state management await vm.stateManager.putAccount( createAddress('0x123...'), { nonce: 0n, balance: 10000000000000000000n, storageRoot: '0x...', codeHash: '0x...' } ) // Direct blockchain control const block = await vm.blockchain.getBlockByNumber(1n)` For component API details, see: * [State Manager](https://node.tevm.sh/reference/state) * [Transaction Pool](https://node.tevm.sh/reference/txpool) * [Blockchain](https://node.tevm.sh/reference/blockchain) * [EVM](https://node.tevm.sh/reference/evm) * [Receipt Manager](https://node.tevm.sh/reference/receipt-manager) Advanced Features[](https://node.tevm.sh/introduction/architecture-overview#advanced-features) ------------------------------------------------------------------------------------------------- Tevm includes several powerful features that enable advanced use cases: For Tevm Bundler users, directly import Solidity with full type safety: Copy `// Import Solidity directly (with tevm bundler plugins) import { ERC20 } from "./ERC20.sol"; // Contract with full TypeScript types const token = ERC20.withAddress("0x123..."); // Safe contract interaction const decimals = await token.read.decimals();` Extensibility Model[](https://node.tevm.sh/introduction/architecture-overview#extensibility-model) ----------------------------------------------------------------------------------------------------- Node Extension API Tevm's plugin system allows adding new functionality to nodes: Copy `import { createTevmNode } from "tevm"; // Create a node with extensions const node = createTevmNode().extend((baseNode) => { // Add custom methods return { async simulateBulkTransactions(txs) { const results = []; for (const tx of txs) { const vm = await baseNode.getVm(); results.push(await vm.runTx({ tx })); } return results; }, async resetToSnapshot(snapshot) { const vm = await baseNode.getVm(); return vm.stateManager.revert(snapshot); }, }; }); // Use the extended functionality const snapshot = await node.getVm().stateManager.checkpoint(); const results = await node.simulateBulkTransactions([tx1, tx2, tx3]); await node.resetToSnapshot(snapshot);` This extension model allows for powerful customizations while maintaining the core API. Next Steps[](https://node.tevm.sh/introduction/architecture-overview#next-steps) ----------------------------------------------------------------------------------- [Create a Tevm Node\ \ Learn how to create and configure a Tevm Node for your project.](https://node.tevm.sh/core/create-tevm-node) [Viem Integration\ \ See how to use Tevm with viem for a complete Ethereum development experience.](https://node.tevm.sh/examples/viem) [Practical Examples\ \ Explore real-world examples and use cases for Tevm Node.](https://node.tevm.sh/examples/local-testing) Further Resources[](https://node.tevm.sh/introduction/architecture-overview#further-resources) ------------------------------------------------------------------------------------------------- | Resource | Description | | --- | --- | | [TevmNode Interface Reference](https://node.tevm.sh/reference/node) | Detailed API reference for the core node interface | | [GitHub Repository](https://github.com/evmts/tevm-monorepo) | Source code and contributions | | [Custom Precompiles Guide](https://node.tevm.sh/vercel/path0/docs/node/pages/advanced/custom-precompiles) | Learn how to extend the EVM | | [Performance Profiling](https://node.tevm.sh/vercel/path0/docs/node/pages/advanced/performance-profiler) | Optimize your Ethereum applications | --- # Using with Viem · Tevm [Skip to content](https://node.tevm.sh/examples/viem#vocs-content) 🚀 Tevm Node is in Beta! Join our [Telegram community](https://t.me/+ANThR9bHDLAwMjUx) Search... [![Logo](https://node.tevm.sh/tevm-logo-dark.png)![Logo](https://node.tevm.sh/tevm-logo-light.png)](https://node.tevm.sh/) [![Logo](https://node.tevm.sh/tevm-logo-dark.png)![Logo](https://node.tevm.sh/tevm-logo-light.png)](https://node.tevm.sh/) Examples Chevron Down Menu Using with Viem On this page Chevron Right This guide demonstrates how to use Tevm with viem, enabling you to leverage viem's type-safe, modular Ethereum development tools alongside Tevm's in-memory EVM capabilities. Integration Options[](https://node.tevm.sh/examples/viem#integration-options) -------------------------------------------------------------------------------- Tevm offers two integration approaches with viem to suit different development needs: The recommended approach for production frontend applications that need to minimize bundle size: Copy `import { requestEip1193 } from 'tevm/decorators' import { createClient } from 'viem' const tevmTransport = createTevmTransport() // Create Viem client const client = createClient({ // Use Tevm node as the viem transport transport: tevmTransport, }) // Import and use viem actions individually import { getBlockNumber } from 'viem/actions' await getBlockNumber(client) // Import and use tevm actions import { tevmDumpState } from 'tevm' await tevmDumpState(client)` A more convenient approach when bundle size isn't a primary concern is to use createMemoryclient: Copy `import { createMemoryClient } from 'tevm' // Create a fully-loaded client with all actions attached const client = createMemoryClient() // Use viem actions directly from the client await client.getBlockNumber() // Use tevm-specific actions await client.tevmDumpState()` Core Functionality[](https://node.tevm.sh/examples/viem#core-functionality) ------------------------------------------------------------------------------ ### 🔍 Public Actions [Read blockchain state, query contracts, and estimate gas](https://node.tevm.sh/examples/viem#public-actions) ### 💼 Wallet Actions [Send transactions, sign messages, and interact with accounts](https://node.tevm.sh/examples/viem#wallet-actions) ### 🧪 Test Actions [Manipulate blockchain state for testing and development](https://node.tevm.sh/examples/viem#test-actions) ### ⚡ Tevm Actions [Tevm-specific extensions for enhanced EVM capabilities](https://node.tevm.sh/examples/viem#tevm-actions) Public Actions[](https://node.tevm.sh/examples/viem#public-actions) ---------------------------------------------------------------------- Use [viem's public actions](https://viem.sh/docs/actions/public/introduction) to query your local Tevm environment: Copy ``// Get the latest block const block = await client.getBlock(); console.log(`Block number: ${block.number}`); // Get an account's balance const balance = await client.getBalance({ address: "0x1234567890123456789012345678901234567890", }); console.log(`Balance: ${balance} wei`); // Get transaction count (nonce) const nonce = await client.getTransactionCount({ address: "0x1234567890123456789012345678901234567890", }); console.log(`Transaction count: ${nonce}`); // Read from a contract const result = await client.readContract({ address: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", // USDC on mainnet abi: parseAbi(["function balanceOf(address) view returns (uint256)"]), functionName: "balanceOf", args: ["0x1234567890123456789012345678901234567890"], }); console.log(`Contract result: ${result}`);`` Wallet Actions[](https://node.tevm.sh/examples/viem#wallet-actions) ---------------------------------------------------------------------- Tevm supports all of [viem's wallet actions](https://viem.sh/docs/actions/wallet/introduction) with built-in prefunded accounts: Copy ``import { createMemoryClient, PREFUNDED_ACCOUNTS } from "tevm"; import { parseEther } from "viem"; // Create a client with one of Tevm's prefunded accounts const client = createMemoryClient({ account: PREFUNDED_ACCOUNTS[0], // First prefunded account with 10000 ETH }); // Send ETH to another address const hash = await client.sendTransaction({ to: "0x1234567890123456789012345678901234567890", value: parseEther("1"), // Send 1 ETH }); console.log(`Transaction sent: ${hash}`); // Wait for the transaction to be mined const receipt = await client.waitForTransactionReceipt({ hash }); console.log(`Transaction mined in block: ${receipt.blockNumber}`); // Deploy a contract const { contractAddress } = await client.deployContract({ abi: parseAbi([ "function greet() view returns (string)", "function setGreeting(string) returns ()", ]), bytecode: "0x608060405234801561...", // Contract bytecode }); console.log(`Contract deployed at: ${contractAddress}`);`` Working with Custom Accounts Copy `import { createMemoryClient } from "tevm"; import { privateKeyToAccount } from "viem/accounts"; // Create an account from a private key const account = privateKeyToAccount( "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80", ); // Use that account with the client const client = createMemoryClient({ account }); // First set some balance for the account await client.setBalance({ address: account.address, value: parseEther("10"), }); // Now use the account to send transactions const hash = await client.sendTransaction({ to: "0x1234567890123456789012345678901234567890", value: parseEther("1"), });` Test Actions[](https://node.tevm.sh/examples/viem#test-actions) ------------------------------------------------------------------ All of [viem's test actions](https://viem.sh/docs/actions/test/introduction) are supported for comprehensive testing capabilities: Copy ``import { createMemoryClient } from "tevm"; import { parseEther } from "viem"; const client = createMemoryClient(); // Mine additional blocks await client.mine({ blocks: 5 }); console.log(`New block number: ${await client.getBlockNumber()}`); // Set an account's balance await client.setBalance({ address: "0x1234567890123456789012345678901234567890", value: parseEther("100"), }); // Set block timestamp for time-dependent tests await client.setNextBlockTimestamp(1695311333n); // Set timestamp for next block await client.mine({ blocks: 1 }); // Mine the block with that timestamp // Snapshot and revert state const snapshotId = await client.snapshot(); console.log(`Created snapshot: ${snapshotId}`); // Make some changes... await client.setBalance({ address: "0x1234567890123456789012345678901234567890", value: parseEther("999"), }); // Revert to the snapshot await client.revert({ id: snapshotId }); console.log("Reverted to previous state"); // Check balance is back to previous value const balance = await client.getBalance({ address: "0x1234567890123456789012345678901234567890", }); console.log(`Balance after revert: ${balance}`);`` Tevm Actions[](https://node.tevm.sh/examples/viem#tevm-actions) ------------------------------------------------------------------ ### Contract Interactions[](https://node.tevm.sh/examples/viem#contract-interactions) Copy ``import { createMemoryClient } from "tevm"; import { parseAbi } from "viem"; const client = createMemoryClient(); // Using the tevmContract action for contract interaction const result = await client.tevmContract({ abi: parseAbi(["function balanceOf(address) view returns (uint256)"]), address: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", // USDC on mainnet functionName: "balanceOf", args: ["0x1234567890123456789012345678901234567890"], }); console.log(`Contract result: ${result}`); // Low-level EVM call with tevmCall const callResult = await client.tevmCall({ to: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", data: "0x70a08231000000000000000000000000" + "1234567890123456789012345678901234567890".slice(2), }); console.log(`Raw call result: ${callResult.data}`);`` ### Account Management[](https://node.tevm.sh/examples/viem#account-management) Copy `import { createMemoryClient } from "tevm"; import { parseEther } from "viem"; const client = createMemoryClient(); // Get account state with all details const account = await client.tevmGetAccount({ address: "0x1234567890123456789012345678901234567890", }); console.log("Account state:", account); // Set up a complex account state (EOA or contract) await client.tevmSetAccount({ address: "0xabcdef1234567890abcdef1234567890abcdef12", balance: parseEther("100"), nonce: 5n, // For contracts: code: "0x608060405234801...", // Contract bytecode storage: { // Storage slots "0x0": "0x1", // slot 0 -> value 1 "0x1": "0x2", // slot 1 -> value 2 }, }); // Add tokens to an account // For native ETH: await client.tevmDeal({ account: "0x1234567890123456789012345678901234567890", amount: parseEther("10"), }); // For ERC20 tokens: await client.tevmDeal({ erc20: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", // USDC on mainnet account: "0x1234567890123456789012345678901234567890", amount: 1000000n, // 1 USDC (6 decimals) });` ### State Management[](https://node.tevm.sh/examples/viem#state-management) Copy `import { createMemoryClient } from "tevm"; const client = createMemoryClient(); // Dump the entire EVM state const state = await client.tevmDumpState(); console.log("Current state:", state); // Save state to local variable const savedState = await client.tevmDumpState(); // Make changes await client.setBalance({ address: "0x1234567890123456789012345678901234567890", value: 123456789n, }); // Restore previous state await client.tevmLoadState({ state: savedState, }); // Mine blocks with Tevm action await client.tevmMine({ blocks: 5, });` Inside the Memory Client[](https://node.tevm.sh/examples/viem#inside-the-memory-client) ------------------------------------------------------------------------------------------ A MemoryClient is essentially a viem client with Tevm's functionality added. Here's how you could build one from scratch: Copy `// Step 1: Create a fork transport (for connecting to an existing network) import { http } from "viem"; const forkTransport = http("https://mainnet.optimism.io"); // Step 2: Create a Tevm Node and make it EIP-1193 compatible import { createTevmNode } from "tevm"; import { requestEip1193 } from "tevm/decorators"; const node = createTevmNode({ fork: { transport: forkTransport, }, }).extend(requestEip1193()); // Step 3: Create a viem client with Tevm extensions import { custom, createClient, publicActions, testActions, walletActions, } from "viem"; import { tevmViemActions } from "tevm/memory-client"; const memoryClient = createClient({ transport: custom(node), }) // Add Tevm-specific actions .extend(tevmViemActions()) // Add viem standard actions .extend(publicActions) .extend(walletActions) .extend(testActions({ mode: "anvil" })); // Now you have a fully functional memoryClient` This breakdown illustrates Tevm's key architectural components: 1. **EIP-1193 Compatibility Layer**: Tevm implements the standard Ethereum provider interface 2. **In-Memory EVM**: Tevm runs a complete Ethereum Virtual Machine locally 3. **Viem Integration**: Tevm extends viem's functionality with EVM-specific capabilities Complete Action Reference[](https://node.tevm.sh/examples/viem#complete-action-reference) -------------------------------------------------------------------------------------------- **Public Actions** - Read blockchain state #### Contract Interactions[](https://node.tevm.sh/examples/viem#contract-interactions-1) * [`call`](https://viem.sh/docs/actions/public/call) - Call a contract method without sending a transaction * [`readContract`](https://viem.sh/docs/contract/readContract) - Read a contract's constant/view method * [`simulateContract`](https://viem.sh/docs/contract/simulateContract) - Simulate a contract write without executing * [`estimateContractGas`](https://viem.sh/docs/contract/estimateContractGas) - Estimate gas for a contract call * [`estimateGas`](https://viem.sh/docs/actions/public/estimateGas) - Estimate gas for a transaction * [`getBytecode`](https://viem.sh/docs/contract/getBytecode) - Get a contract's bytecode #### Block & Transaction[](https://node.tevm.sh/examples/viem#block--transaction) * [`getBlock`](https://viem.sh/docs/actions/public/getBlock) - Get a block by number or hash * [`getBlockNumber`](https://viem.sh/docs/actions/public/getBlockNumber) - Get the latest block number * [`getBlockTransactionCount`](https://viem.sh/docs/actions/public/getBlockTransactionCount) - Get the transaction count for a block * [`getTransaction`](https://viem.sh/docs/actions/public/getTransaction) - Get transaction details by hash * [`getTransactionCount`](https://viem.sh/docs/actions/public/getTransactionCount) - Get the transaction count (nonce) for an address * [`getTransactionReceipt`](https://viem.sh/docs/actions/public/getTransactionReceipt) - Get a transaction receipt by hash * [`waitForTransactionReceipt`](https://viem.sh/docs/actions/public/waitForTransactionReceipt) - Wait for a transaction to be mined #### Account & Chain[](https://node.tevm.sh/examples/viem#account--chain) * [`getBalance`](https://viem.sh/docs/actions/public/getBalance) - Get the balance of an address * [`getChainId`](https://viem.sh/docs/actions/public/getChainId) - Get the chain ID * [`getGasPrice`](https://viem.sh/docs/actions/public/getGasPrice) - Get the current gas price * [`estimateFeesPerGas`](https://viem.sh/docs/actions/public/estimateFeesPerGas) - Estimate fees per gas unit * [`getStorageAt`](https://viem.sh/docs/actions/public/getStorageAt) - Get the value from a storage slot **Test Actions** - Manipulate blockchain state #### Block & Mining[](https://node.tevm.sh/examples/viem#block--mining) * [`mine`](https://viem.sh/docs/actions/test/mine) - Mine a number of blocks * [`setAutomine`](https://viem.sh/docs/actions/test/setAutomine) - Enable/disable automatic mining * [`setIntervalMining`](https://viem.sh/docs/actions/test/setIntervalMining) - Set mining to occur at intervals * [`setBlockGasLimit`](https://viem.sh/docs/actions/test/setBlockGasLimit) - Set the block gas limit * [`setBlockTimestampInterval`](https://viem.sh/docs/actions/test/setBlockTimestampInterval) - Set increment for timestamps * [`setNextBlockBaseFeePerGas`](https://viem.sh/docs/actions/test/setNextBlockBaseFeePerGas) - Set the base fee for the next block * [`setNextBlockTimestamp`](https://viem.sh/docs/actions/test/setNextBlockTimestamp) - Set the timestamp for the next block #### Account & State[](https://node.tevm.sh/examples/viem#account--state) * [`setBalance`](https://viem.sh/docs/actions/test/setBalance) - Set an address's balance * [`setCode`](https://viem.sh/docs/actions/test/setCode) - Set contract bytecode at an address * [`setNonce`](https://viem.sh/docs/actions/test/setNonce) - Set the nonce for an address * [`setStorageAt`](https://viem.sh/docs/actions/test/setStorageAt) - Set a storage slot's value * [`setCoinbase`](https://viem.sh/docs/actions/test/setCoinbase) - Set the block miner address * [`setMinGasPrice`](https://viem.sh/docs/actions/test/setMinGasPrice) - Set the minimum gas price #### State Management[](https://node.tevm.sh/examples/viem#state-management-1) * [`snapshot`](https://viem.sh/docs/actions/test/snapshot) - Create a snapshot of the current state * [`revert`](https://viem.sh/docs/actions/test/revert) - Revert to a previous snapshot * [`reset`](https://viem.sh/docs/actions/test/reset) - Reset the fork to a fresh state * [`dumpState`](https://viem.sh/docs/actions/test/dumpState) - Export the current state * [`loadState`](https://viem.sh/docs/actions/test/loadState) - Import a previously exported state **Wallet Actions** - Send transactions and interact with accounts #### Account Management[](https://node.tevm.sh/examples/viem#account-management-1) * [`getAddresses`](https://viem.sh/docs/actions/wallet/getAddresses) - Get available addresses * [`requestAddresses`](https://viem.sh/docs/actions/wallet/requestAddresses) - Request permission to view addresses #### Transaction Operations[](https://node.tevm.sh/examples/viem#transaction-operations) * [`prepareTransactionRequest`](https://viem.sh/docs/actions/wallet/prepareTransactionRequest) - Prepare a transaction * [`sendTransaction`](https://viem.sh/docs/actions/wallet/sendTransaction) - Send a transaction * [`sendRawTransaction`](https://viem.sh/docs/actions/wallet/sendRawTransaction) - Send a signed transaction * [`signTransaction`](https://viem.sh/docs/actions/wallet/signTransaction) - Sign a transaction #### Signing Operations[](https://node.tevm.sh/examples/viem#signing-operations) * [`signMessage`](https://viem.sh/docs/actions/wallet/signMessage) - Sign a message * [`signTypedData`](https://viem.sh/docs/actions/wallet/signTypedData) - Sign typed data (EIP-712) #### Chain Management[](https://node.tevm.sh/examples/viem#chain-management) * [`addChain`](https://viem.sh/docs/actions/wallet/addChain) - Add a chain to the wallet * [`switchChain`](https://viem.sh/docs/actions/wallet/switchChain) - Switch to a different chain #### Permissions & Assets[](https://node.tevm.sh/examples/viem#permissions--assets) * [`getPermissions`](https://viem.sh/docs/actions/wallet/getPermissions) - Get wallet permissions * [`requestPermissions`](https://viem.sh/docs/actions/wallet/requestPermissions) - Request wallet permissions * [`watchAsset`](https://viem.sh/docs/actions/wallet/watchAsset) - Add a token to the wallet **Tevm Actions** - Enhanced EVM capabilities * `tevmCall` - Low-level EVM call * `tevmContract` - Call a contract method with detailed EVM info * `tevmDeploy` - Deploy a contract with detailed results * `tevmGetAccount` - Get detailed account information * `tevmSetAccount` - Set up a complex account state * `tevmDeal` - Add native ETH or ERC20 tokens to an account * `tevmDumpState` - Export complete EVM state * `tevmLoadState` - Import complete EVM state * `tevmMine` - Mine blocks with additional options Next Steps[](https://node.tevm.sh/examples/viem#next-steps) -------------------------------------------------------------- ### Using with Ethers.js Learn how to integrate Tevm with ethers.js ### Forking Mainnet Create a local fork of mainnet for testing ### Local Testing Set up a comprehensive local testing environment ### TevmNode Interface Explore the low-level node interface --- # Getting Started with Viem · Tevm [Skip to content](https://node.tevm.sh/getting-started/viem#vocs-content) 🚀 Tevm Node is in Beta! Join our [Telegram community](https://t.me/+ANThR9bHDLAwMjUx) Search... [![Logo](https://node.tevm.sh/tevm-logo-dark.png)![Logo](https://node.tevm.sh/tevm-logo-light.png)](https://node.tevm.sh/) [![Logo](https://node.tevm.sh/tevm-logo-dark.png)![Logo](https://node.tevm.sh/tevm-logo-light.png)](https://node.tevm.sh/) Quick Start Chevron Down Menu Getting started with Viem On this page Chevron Right This guide will help you integrate Tevm with [viem](https://viem.sh/) , the modern TypeScript interface for Ethereum. By the end, you'll have a working setup with Tevm Node and understand how to leverage viem's actions with Tevm. Installation[](https://node.tevm.sh/getting-started/viem#installation) ------------------------------------------------------------------------- ### Install Dependencies[](https://node.tevm.sh/getting-started/viem#install-dependencies) First, install Tevm along with viem as a peer dependency: npmpnpmyarnbun Terminal npm Copy `npm install tevm viem@latest` ### Create Your Client[](https://node.tevm.sh/getting-started/viem#create-your-client) For the quickest start, create a memory client: Copy `import { createMemoryClient } from "tevm"; const client = createMemoryClient();` Or, to fork from an existing chain: Copy `import { createMemoryClient, http } from "tevm"; import { optimism } from "tevm/chains"; const client = createMemoryClient({ fork: { transport: http("https://mainnet.optimism.io"), common: optimism, }, }); // Wait for the node to be ready before using it await client.tevmReady();` A [`MemoryClient`](https://github.com/evmts/tevm-monorepo/blob/main/packages/memory-client/src/createMemoryClient.js) is a batteries included client that includes all `PublicActions`, `WalletActions`, and `TestActions` from viem. It also includes special tevm specific actions prefixed with `tevm*` such as `tevmCall` and `tevmSetAccount` ### You're Ready![](https://node.tevm.sh/getting-started/viem#youre-ready) Start using your client with familiar viem actions: Copy ``// Get the current block number const blockNumber = await client.getBlockNumber(); console.log(`Current block: ${blockNumber}`);`` Complete Example[](https://node.tevm.sh/getting-started/viem#complete-example) --------------------------------------------------------------------------------- The following example demonstrates the key capabilities of Tevm with viem: Forking ExampleContract Deployment Forking Example Copy ``import { createMemoryClient, http } from "tevm"; import { optimism } from "tevm/common"; import { parseAbi, parseEther } from "viem"; // 1. Create a memory client forked from Optimism mainnet const client = createMemoryClient({ fork: { transport: http("https://mainnet.optimism.io"), common: optimism, }, }); // Wait for the node to be ready await client.tevmReady(); // 2. Get current block number (from the fork point) const blockNumber = await client.getBlockNumber(); console.log(`Current block number: ${blockNumber}`); // Setup addresses and contract interfaces const account = `0x${"baD60A7".padStart(40, "0")}` as const; const greeterContractAddress = "0x10ed0b176048c34d69ffc0712de06CbE95730748"; // Define contract interfaces with parseAbi const greeterAbi = parseAbi([ "function greet() view returns (string)", "function setGreeting(string memory _greeting) public", ]); // 3. Modify blockchain state with test actions // Fund our test account with 1 ETH await client.setBalance({ address: account, value: parseEther("1"), }); // Read the current greeting using viem's readContract const currentGreeting = await client.readContract({ address: greeterContractAddress, abi: greeterAbi, functionName: "greet", }); console.log(`Current greeting: ${currentGreeting}`); // Update the greeting with writeContract const txHash = await client.writeContract({ account, address: greeterContractAddress, abi: greeterAbi, functionName: "setGreeting", args: ["Hello from Tevm!"], chain: optimism, }); console.log(`Transaction sent: ${txHash}`); // 4. Mine a new block to include our transaction await client.mine({ blocks: 1 }); // Verify the greeting was updated const updatedGreeting = await client.readContract({ address: greeterContractAddress, abi: greeterAbi, functionName: "greet", }); console.log(`Updated greeting: ${updatedGreeting}`);`` Code Walkthrough ### 1\. Imports & Client Creation[](https://node.tevm.sh/getting-started/viem#1-imports--client-creation) Copy `import { createMemoryClient, http } from "tevm"; import { optimism } from "tevm/common"; import { parseAbi, parseEther } from "viem"; const client = createMemoryClient({ fork: { transport: http("https://mainnet.optimism.io"), common: optimism, }, }); await client.tevmReady();` * We create a client that **forks** from Optimism mainnet * This gives us a local sandbox with all of mainnet's state * `client.tevmReady()` ensures the fork is complete before proceeding ### 2\. Contract Interaction[](https://node.tevm.sh/getting-started/viem#2-contract-interaction) Copy `// Define the contract interface const greeterAbi = parseAbi([ "function greet() view returns (string)", "function setGreeting(string memory _greeting) public", ]); // Read from contract const currentGreeting = await client.readContract({ address: greeterContractAddress, abi: greeterAbi, functionName: "greet", }); // Write to contract const txHash = await client.writeContract({ account, address: greeterContractAddress, abi: greeterAbi, functionName: "setGreeting", args: ["Hello from Tevm!"], chain: optimism, });` * The API matches viem exactly - anyone familiar with viem can use this immediately * Write operations return a transaction hash just like on a real network ### 3\. Mining Control[](https://node.tevm.sh/getting-started/viem#3-mining-control) Copy `// Mine a block to include our transaction await client.mine({ blocks: 1 });` * Unlike real networks, you control exactly when blocks are mined * This gives you complete determinism for testing and development Key Viem-Compatible Features[](https://node.tevm.sh/getting-started/viem#key-viem-compatible-features) --------------------------------------------------------------------------------------------------------- Tevm's viem client implements the full viem API, maintaining compatibility while adding powerful features: Standard viem APITevm ExtensionsEVM Debugging Standard viem API Copy `// These standard viem actions work exactly as expected await client.getBalance({ address: '0x...' }) await client.getBlockNumber() await client.readContract({ ... }) await client.writeContract({ ... }) await client.estimateGas({ ... }) await client.sendTransaction({ ... }) // And all other viem actions` Common patterns and Best Practices[](https://node.tevm.sh/getting-started/viem#common-patterns-and-best-practices) --------------------------------------------------------------------------------------------------------------------- ### Creating multiple clients[](https://node.tevm.sh/getting-started/viem#creating-multiple-clients) It is common to create a viem client and a tevm client side by side. Copy `import { createPublicClient, http } from "viem"; import { createMemoryClient } from "tevm"; import { optimism } from "tevm/common"; export const publicClient = createPublicClient({ transport: http("https://mainnet.optimism.io"), }); export const memoryClient = createMemoryClient({ fork: { // use your public client as the fork transport transport: publicClient, // (comming soon) rebase: true, }, });` * Generally you will still want to be using normal viem clients while building Tevm applications * As a best practice use your viem client as the transport so any caching viem does is shared with Tevm * tevm/common is a superset of a viem chain so it can be used for both ### Racing JSON-RPC requests[](https://node.tevm.sh/getting-started/viem#racing-json-rpc-requests) When doing this a pattern you can do to improve the performance of your app is what is called `racing`. This is when you execute a call with `tevm` and `viem` and return the one that returns first. Copy `function raceExample() { const {resolve, reject, promise} = Promise.withResolvers() // estimateGas with both viem and tevm in parallel resolving the one that finishes first publicClient.estimateGas(...).then(result => resolve(result)) memoryClient.estimateGas(...).then(result => resolve(result)) return promise }` If the Tevm cache is warm it will finish much faster (nearly instantly) than the remote RPC call will. If the cache is cold the remote rpc call will finish first while Tevm warms the cache in background for next time. Racing allows you to improve the performance of your app. ### Using the Tevm Bundler[](https://node.tevm.sh/getting-started/viem#using-the-tevm-bundler) The Tevm Bundler is an optional tool for importing contract abis into TypeScript and it is built for Wagmi, Viem, Ethers and Tevm. Users have reported using it with other tools like `Ponder` as well. It is common to use the Tevm Bundler even when not using TevmNode as a TevmContract is a library agnostic typesafe instance representing a contract abi. Copy ``import { MyContract } from "./MyContract.sol"; function useExample() { return useReadContract({ abi: MyContract.abi, address: `0x...`, method: "balanceOf", args: address, }); // Alternatively use the typesafe `read.method()` api return useReadContract( MyContract.withAddress(`0x...`).read.balanceOf(address), ); }`` Tree-Shakeable API[](https://node.tevm.sh/getting-started/viem#tree-shakeable-api) ------------------------------------------------------------------------------------- For production applications, especially in browser environments, you may want to use Tevm's tree-shakeable API to minimize bundle size: Copy `import { createClient, http } from "viem"; import { createTevmTransport } from "tevm/transport"; import { tevmCall, tevmDumpState } from "tevm/actions"; // Create a standard viem client with Tevm transport const client = createClient({ transport: createTevmTransport({ fork: { transport: http("https://mainnet.optimism.io"), }, }), }); // Import only the actions you need await tevmDumpState(client);` To do this you use `createTevmTransport` which takes the same options as a memoryClient but unlike a MemoryClient only supports a `client.request` method. You should ALWAYS use `createTevmTransport` rather than passing a TevmClient directly in as transport using `custom(TevmNode)`. Using viem to talk to Tevm over http[](https://node.tevm.sh/getting-started/viem#using-viem-to-talk-to-tevm-over-http) ------------------------------------------------------------------------------------------------------------------------- By default Tevm runs in memory but it does support running as a traditional http server as well. This can be useful if using Tevm as an anvil-like testing tool. There are two ways to run tevm as a sever. THe easiest way is using the CLI Copy `npx tevm serve --fork-url https://mainnet.optimism.io` Or you can run Tevm as a Http, Express, Hono, or Next.js server directly in node.js and Bun Copy `import { createMemoryClient, http } from "tevm"; import { createServer } from "tevm/server"; const memoryClient = createMemoryClient(); const server = createServer(memoryClient); server.listen(8545, () => { console.log("server started on port 8545"); // test a request vs server http("http://localhost:8545")({}) .request({ method: "eth_blockNumber", }) .then(console.log) .catch(console.error); });` Once you start Tevm as a server you can talk to it using viem `http` as normal. Tevm-Specific Actions[](https://node.tevm.sh/getting-started/viem#tevm-specific-actions) ------------------------------------------------------------------------------------------- Tevm extends viem with specialized actions that provide enhanced capabilities: | Action | Description | Use Case | | --- | --- | --- | | `tevmCall` | Low-level EVM call with execution hooks | Deep inspection of contract execution | | `tevmContract` | Enhanced contract interaction with EVM hooks | Detailed debugging of contract calls | | `tevmDeploy` | Deploy with execution hooks | Understanding deployment execution flow | | `tevmMine` | Control block mining | Precise transaction inclusion control | | `tevmSetAccount` | Modify account state | Test different account scenarios | | `tevmGetAccount` | Read detailed account state | Inspect nonce, code, storage | | `tevmDumpState` | Export full EVM state | State persistence and analysis | | `tevmLoadState` | Import saved EVM state | Restore a specific state for testing | | `tevmReady` | Wait for fork to initialize | Ensure node is ready before use | Hook into the EVM[](https://node.tevm.sh/getting-started/viem#hook-into-the-evm) ----------------------------------------------------------------------------------- One of Tevm's most powerful features is the ability to hook directly into EVM execution using the `tevmCall` and `tevmContract` actions: Copy ``await client.tevmContract({ address: greeterContractAddress, abi: greeterAbi, functionName: "setGreeting", args: ["Hello!"], // onStep is called for each EVM operation onStep: (stepInfo, next) => { console.log(`Executing: ${stepInfo.opcode.name} at PC=${stepInfo.pc}`); console.log(`Stack: ${stepInfo.stack.map((val) => val.toString())}`); console.log(`Memory: ${stepInfo.memory.toString("hex")}`); // You can also modify EVM state here if needed // Call next() to continue execution next?.(); }, // You can also access the detailed result after execution onResult: (result) => { console.log(`Gas used: ${result.executionGasUsed}`); console.log(`Return value: 0x${result.returnValue?.toString("hex")}`); }, });`` This enables advanced use cases like: * **Visual Debuggers**: Create step-by-step transaction debuggers * **Educational Tools**: Explain EVM execution for learning purposes * **Custom Instrumentation**: Profile and analyze contract execution * **Intercepting Execution**: Modify execution behavior for testing Next Steps[](https://node.tevm.sh/getting-started/viem#next-steps) --------------------------------------------------------------------- Now that you're familiar with using Tevm with viem, you can: ### Explore More Tevm Features[](https://node.tevm.sh/getting-started/viem#explore-more-tevm-features) Dive deeper into Tevm's powerful capabilities: * [Forking capabilities](https://node.tevm.sh/core/forking) to simulate production chains * [State management](https://node.tevm.sh/core/managing-state) for manipulating the blockchain * [Mining modes](https://node.tevm.sh/core/mining-modes) for controlling transaction inclusion * [Direct Solidity imports](https://node.tevm.sh/getting-started/bundler) with the Tevm Bundler ### Check Out Examples[](https://node.tevm.sh/getting-started/viem#check-out-examples) See how Tevm solves real-world problems: * [Forking mainnet](https://node.tevm.sh/examples/forking-mainnet) for production simulation * [Building a debugger UI](https://node.tevm.sh/examples/debugger-ui) with EVM insights * [Local testing flows](https://node.tevm.sh/examples/local-testing) for development ### Advanced API Usage[](https://node.tevm.sh/getting-started/viem#advanced-api-usage) Master the Tevm API for more sophisticated applications: * [EVM events & hooks](https://node.tevm.sh/api/evm-events) for detailed execution analysis * [Custom precompiles](https://node.tevm.sh/advanced/custom-precompiles) for extending the EVM * [Transaction pool management](https://node.tevm.sh/advanced/txpool) for pending transaction control * [Contract Bundler](https://node.tevm.sh/reference/bundler) for importing Solidity files directly [← Back to Overview](https://node.tevm.sh/getting-started/viem/overview) [Ethers Integration →](https://node.tevm.sh/getting-started/viem/ethers) --- # Creating a Tevm Node [Skip to content](https://node.tevm.sh/core/create-tevm-node#vocs-content) 🚀 Tevm Node is in Beta! Join our [Telegram community](https://t.me/+ANThR9bHDLAwMjUx) Search... [![Logo](https://node.tevm.sh/tevm-logo-dark.png)![Logo](https://node.tevm.sh/tevm-logo-light.png)](https://node.tevm.sh/) [![Logo](https://node.tevm.sh/tevm-logo-dark.png)![Logo](https://node.tevm.sh/tevm-logo-light.png)](https://node.tevm.sh/) Menu Chevron Down Menu Creating a Node On this page Chevron Right Create a Basic Node --------------------- Instantiate a client with default configuration: ### TypeScript[](https://node.tevm.sh/core/create-tevm-node#typescript) Copy `import { createMemoryClient } from "tevm"; const client = createMemoryClient(); // Optionally wait for the client to be ready before using it // This is not required but useful if profiling performance or debugging an issue await client.ready(); // Your client is now ready to use!` Configure to Your Needs ------------------------- Tailor the node with powerful configuration options: Copy `import { createMemoryClient, http } from "tevm"; const client = createMemoryClient({ // Fork from a live network fork: { transport: http("https://mainnet.infura.io/v3/YOUR-KEY"), }, // Configure automatic mining miningConfig: { type: "auto" }, // Set logging verbosity loggingLevel: "debug", }); await client.ready();` Configuration Options[](https://node.tevm.sh/core/create-tevm-node#configuration-options) -------------------------------------------------------------------------------------------- Tevm Node offers extensive configuration options to adapt to different use cases. Here's a complete breakdown: ### Fork Configuration[](https://node.tevm.sh/core/create-tevm-node#fork-configuration) The `fork` option creates a node that connects to an existing network: Copy `import { createMemoryClient, http } from "tevm"; const node = createMemoryClient({ fork: { // Use any EIP-1193 compatible provider transport: http("https://mainnet.infura.io/v3/YOUR-KEY"), // Optional: Fork from a specific block blockTag: 17_000_000n, }, }); await node.ready();` ### Mining Configuration[](https://node.tevm.sh/core/create-tevm-node#mining-configuration) Control how and when blocks are produced with various mining modes: Copy `// Auto-mining: Mine a block for every transaction const node = createMemoryClient({ miningConfig: { type: "auto", }, }); // Interval-based mining: Mine at regular intervals const intervalNode = createMemoryClient({ miningConfig: { type: "interval", interval: 12_000, // Mine every 12 seconds }, }); await node.ready(); await intervalNode.ready();` ### Chain Configuration[](https://node.tevm.sh/core/create-tevm-node#chain-configuration) Customize the chain parameters or use pre-configured chains: Copy `import { createMemoryClient } from "tevm"; import { Common } from "tevm/common"; // Custom chain configuration const customNode = createMemoryClient({ common: Common.custom({ chainId: 1337, networkId: 1337, // Other chain parameters }), }); await customNode.ready();` Or use one of the pre-configured chains: Copy `import { createMemoryClient } from "tevm"; import { mainnet, optimism, arbitrum, base } from "tevm/common"; // Create a node with Optimism chain configuration const optimismNode = createMemoryClient({ common: optimism, }); await optimismNode.ready();` Want to add your own network? If you need support for a network not included in Tevm, first add it to `viem/chains` and then open an issue on the Tevm repository to request the network to be added. ### Logging Configuration[](https://node.tevm.sh/core/create-tevm-node#logging-configuration) Configure the internal logger to match your needs: Copy `const node = createMemoryClient({ loggingLevel: "debug", // 'fatal' | 'error' | 'warn' | 'info' | 'debug' | 'trace' }); // Later use the logger directly node.logger.debug("Detailed debugging information"); node.logger.info("Informational message"); node.logger.warn("Warning!"); node.logger.error("Error encountered", { details: "Something went wrong" }); await node.ready();` ### Custom Precompiles[](https://node.tevm.sh/core/create-tevm-node#custom-precompiles) Add your own precompiled contracts to unlock powerful capabilities: Copy `import { definePrecompile, createContract, parseAbi } from "tevm"; const calculatorPrecompile = definePrecompile({ // Define contract interface contract: createContract({ abi: parseAbi([ "function add(uint256 a, uint256 b) returns (uint256)", "function subtract(uint256 a, uint256 b) returns (uint256)", ]), address: "0xf2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2", }), // Implement the precompile logic call: async ({ data, gasLimit }) => { // Precompile implementation goes here console.log("Precompile called with data:", data, "gas limit:", gasLimit); return { returnValue: new Uint8Array([0x01]), // Example return value executionGasUsed: 200n, }; }, }); // Register the precompile with the node const node = createMemoryClient({ customPrecompiles: [calculatorPrecompile.precompile()], }); await node.ready();` ### Performance Profiling[](https://node.tevm.sh/core/create-tevm-node#performance-profiling) Enable the built-in profiler for detailed execution metrics: Copy `const node = createMemoryClient({ profiler: true, }); await node.ready(); // Run a transaction or call // ... // Access profiling data const vm = await node.getVm(); const performanceLogs = vm.evm.getPerformanceLogs(); console.log("Performance data:", performanceLogs);` Complete Configuration Reference[](https://node.tevm.sh/core/create-tevm-node#complete-configuration-reference) ------------------------------------------------------------------------------------------------------------------ | Property | Type | Default | Description | | --- | --- | --- | --- | | `fork` | `{ transport: EIP1193RequestFn; blockTag?: BlockTag; }` | \- | Enables forking from a live network or another Tevm instance | | `common` | `Common` | `tevmDevnet` | Chain configuration object | | `loggingLevel` | `"fatal" \| "error" \| "warn" \| "info" \| "debug" \| "trace"` | `"info"` | Logging verbosity level | | `miningConfig` | `{ type: 'auto' } \| { type: 'interval', interval: number }` | `{ type: 'auto' }` | Block mining behavior | | `customPrecompiles` | `Precompile[]` | `[]` | Additional precompiled contracts | | `allowUnlimitedContractSize` | `boolean` | `false` | Disables EIP-170 contract size checks | Best Practices[](https://node.tevm.sh/core/create-tevm-node#best-practices) ------------------------------------------------------------------------------ ### Always pass in a common when forking[](https://node.tevm.sh/core/create-tevm-node#always-pass-in-a-common-when-forking) Though a `common` object is not required it is highly recomended for following reasons * Tevm will initialize faster if a common is provided via not needing to fetch a chainId up front * Chain specific information such as EIP and hardfork info will help Tevm provide a closer experience to the real chain. When a common is not provided `tevmDefault` common is used Copy `import { createMemoryClient, http } from "tevm"; import { optimism } from "tevm/common"; const client = createMemoryClient({ // always pass in a common common: optimism, fork: { transport: http() }, }); // Because tevm knows this is an op stack chain it will operate closer to an l1 chain including allowing you to calculate l1 data fee const { l1DataFee } = await client.call({ data });` ### Choose the Right Mining Configuration[](https://node.tevm.sh/core/create-tevm-node#choose-the-right-mining-configuration) By Default Tevm uses manual mining. We believe explicit mining is the correct configuration for most to all use cases which is why it's the default. As a convenience we do offer automining which will mine a new block everytime a tx enters mempool. We also offer interval mining and gas mining to more closely replicate a real ethereum node. Copy `// For testing: Mine after each transaction const testNode = createMemoryClient({ miningConfig: { type: "auto" }, }); // For simulation: Mine at intervals to mimic real networks const simulationNode = createMemoryClient({ miningConfig: { type: "interval", interval: 12_000 }, // 12 seconds like Ethereum });` ### Utilize debug logging when something goes wrong[](https://node.tevm.sh/core/create-tevm-node#utilize-debug-logging-when-something-goes-wrong) When you have issues with Tevm, `debug logging` is useful. Tevm will produce a lot of logs so you should use an LLM to help comb through them. Copy `const client = createMemoryClient({ loggingLevel: "debug", });` ### Call `client.ready()` if profiling[](https://node.tevm.sh/core/create-tevm-node#call-clientready-if-profiling) Anytime you are profiling tevm you will want to call `client.ready()` before running the profiler or else you will be measuring the initializion time in addition to the action. When you don't call `client.ready()` all tevm actions implicitly wait for the client to be ready before executing. Tevm initializes very fast though as it doesn't need to do a `sync`. Next Steps[](https://node.tevm.sh/core/create-tevm-node#next-steps) ---------------------------------------------------------------------- * [Node Interface](https://node.tevm.sh/tevm-node-interface) - Explore the complete TevmNode interface and its capabilities * [Forking & Reforking](https://node.tevm.sh/forking) - Learn how to fork from live networks and efficiently manage forks * [State Management](https://node.tevm.sh/managing-state) - Understand how to manipulate blockchain state * [Custom Precompiles](https://node.tevm.sh/vercel/path0/docs/node/pages/advanced/custom-precompiles) - Create your own precompiled contracts to extend EVM functionality --- # Vercel Security Checkpoint We're verifying your browser [Website owner? Click here to fix](https://vercel.link/security-checkpoint) --- # Vercel Security Checkpoint We're verifying your browser [Website owner? Click here to fix](https://vercel.link/security-checkpoint) --- # Vercel Security Checkpoint We're verifying your browser [Website owner? Click here to fix](https://vercel.link/security-checkpoint) --- # Vercel Security Checkpoint We're verifying your browser [Website owner? Click here to fix](https://vercel.link/security-checkpoint) --- # Vercel Security Checkpoint We're verifying your browser [Website owner? Click here to fix](https://vercel.link/security-checkpoint) --- # Vercel Security Checkpoint We're verifying your browser [Website owner? Click here to fix](https://vercel.link/security-checkpoint) --- # Vercel Security Checkpoint We're verifying your browser [Website owner? Click here to fix](https://vercel.link/security-checkpoint) --- # Vercel Security Checkpoint We're verifying your browser [Website owner? Click here to fix](https://vercel.link/security-checkpoint) --- # Vercel Security Checkpoint We're verifying your browser [Website owner? Click here to fix](https://vercel.link/security-checkpoint) --- # Vercel Security Checkpoint We're verifying your browser [Website owner? Click here to fix](https://vercel.link/security-checkpoint) --- # Vercel Security Checkpoint We're verifying your browser [Website owner? Click here to fix](https://vercel.link/security-checkpoint) --- # Vercel Security Checkpoint We're verifying your browser [Website owner? Click here to fix](https://vercel.link/security-checkpoint) --- # Vercel Security Checkpoint We're verifying your browser [Website owner? Click here to fix](https://vercel.link/security-checkpoint) --- # Vercel Security Checkpoint We're verifying your browser [Website owner? Click here to fix](https://vercel.link/security-checkpoint) --- # Vercel Security Checkpoint We're verifying your browser [Website owner? Click here to fix](https://vercel.link/security-checkpoint) --- # Vercel Security Checkpoint We're verifying your browser [Website owner? Click here to fix](https://vercel.link/security-checkpoint) --- # Vercel Security Checkpoint We're verifying your browser [Website owner? Click here to fix](https://vercel.link/security-checkpoint) --- # Vercel Security Checkpoint We're verifying your browser [Website owner? Click here to fix](https://vercel.link/security-checkpoint) --- # Vercel Security Checkpoint We're verifying your browser [Website owner? Click here to fix](https://vercel.link/security-checkpoint) --- # Vercel Security Checkpoint We're verifying your browser [Website owner? Click here to fix](https://vercel.link/security-checkpoint) --- # Vercel Security Checkpoint We're verifying your browser [Website owner? Click here to fix](https://vercel.link/security-checkpoint) --- # Vercel Security Checkpoint We're verifying your browser [Website owner? Click here to fix](https://vercel.link/security-checkpoint) --- # Vercel Security Checkpoint We're verifying your browser [Website owner? Click here to fix](https://vercel.link/security-checkpoint) --- # Vercel Security Checkpoint We're verifying your browser [Website owner? Click here to fix](https://vercel.link/security-checkpoint) --- # Vercel Security Checkpoint We're verifying your browser [Website owner? Click here to fix](https://vercel.link/security-checkpoint) --- # Vercel Security Checkpoint We're verifying your browser [Website owner? Click here to fix](https://vercel.link/security-checkpoint) --- # Vercel Security Checkpoint We're verifying your browser [Website owner? Click here to fix](https://vercel.link/security-checkpoint) --- # Vercel Security Checkpoint We're verifying your browser [Website owner? Click here to fix](https://vercel.link/security-checkpoint) --- # Vercel Security Checkpoint We're verifying your browser [Website owner? Click here to fix](https://vercel.link/security-checkpoint) --- # Vercel Security Checkpoint We're verifying your browser [Website owner? Click here to fix](https://vercel.link/security-checkpoint) --- # Vercel Security Checkpoint We're verifying your browser [Website owner? Click here to fix](https://vercel.link/security-checkpoint) --- # Vercel Security Checkpoint We're verifying your browser [Website owner? Click here to fix](https://vercel.link/security-checkpoint) --- # Vercel Security Checkpoint We're verifying your browser [Website owner? Click here to fix](https://vercel.link/security-checkpoint) --- # Vercel Security Checkpoint We're verifying your browser [Website owner? Click here to fix](https://vercel.link/security-checkpoint) --- # Vercel Security Checkpoint We're verifying your browser [Website owner? Click here to fix](https://vercel.link/security-checkpoint) --- # Vercel Security Checkpoint We're verifying your browser [Website owner? Click here to fix](https://vercel.link/security-checkpoint) --- # Vercel Security Checkpoint We're verifying your browser [Website owner? Click here to fix](https://vercel.link/security-checkpoint) --- # Vercel Security Checkpoint We're verifying your browser [Website owner? Click here to fix](https://vercel.link/security-checkpoint) --- # Vercel Security Checkpoint We're verifying your browser [Website owner? Click here to fix](https://vercel.link/security-checkpoint) --- # Vercel Security Checkpoint We're verifying your browser [Website owner? Click here to fix](https://vercel.link/security-checkpoint) --- # Vercel Security Checkpoint We're verifying your browser [Website owner? Click here to fix](https://vercel.link/security-checkpoint) --- # Vercel Security Checkpoint We're verifying your browser [Website owner? Click here to fix](https://vercel.link/security-checkpoint) --- # Vercel Security Checkpoint We're verifying your browser [Website owner? Click here to fix](https://vercel.link/security-checkpoint) --- # Vercel Security Checkpoint We're verifying your browser [Website owner? Click here to fix](https://vercel.link/security-checkpoint) ---