# Tevm Node > A lightweight, unopinionated, powerful EVM node that runs in the browser ## @tevm/actions Action handlers for the Tevm client, covering standard Ethereum JSON-RPC, Anvil-compatible test methods, debug/tracing, and Tevm-specific calls. Full API: [packages/actions/docs](https://github.com/evmts/tevm/tree/main/packages/actions/docs). ### Installation ```bash npm install @tevm/actions@1.0.0-rc.151 viem ``` ### API Reference #### Error Classes * [BlobGasLimitExceededError](https://github.com/evmts/tevm/tree/main/packages/actions/docs/classes/BlobGasLimitExceededError.md) * [MissingAccountError](https://github.com/evmts/tevm/tree/main/packages/actions/docs/classes/MissingAccountError.md) * [NoForkUrlSetError](https://github.com/evmts/tevm/tree/main/packages/actions/docs/classes/NoForkUrlSetError.md) #### Core Types * [Address](https://github.com/evmts/tevm/tree/main/packages/actions/docs/type-aliases/Address.md) * [Abi](https://github.com/evmts/tevm/tree/main/packages/actions/docs/type-aliases/Abi.md) * [Block](https://github.com/evmts/tevm/tree/main/packages/actions/docs/type-aliases/Block.md) * [BlockTag](https://github.com/evmts/tevm/tree/main/packages/actions/docs/type-aliases/BlockTag.md) #### Base Actions ##### Call Actions * [CallHandler](https://github.com/evmts/tevm/tree/main/packages/actions/docs/type-aliases/CallHandler.md) * [CallParams](https://github.com/evmts/tevm/tree/main/packages/actions/docs/type-aliases/CallParams.md) * [CallResult](https://github.com/evmts/tevm/tree/main/packages/actions/docs/type-aliases/CallResult.md) * [BaseCallParams](https://github.com/evmts/tevm/tree/main/packages/actions/docs/type-aliases/BaseCallParams.md) ##### Contract Actions * [ContractHandler](https://github.com/evmts/tevm/tree/main/packages/actions/docs/type-aliases/ContractHandler.md) * [ContractParams](https://github.com/evmts/tevm/tree/main/packages/actions/docs/type-aliases/ContractParams.md) * [ContractResult](https://github.com/evmts/tevm/tree/main/packages/actions/docs/type-aliases/ContractResult.md) ##### Deploy Actions * [DeployHandler](https://github.com/evmts/tevm/tree/main/packages/actions/docs/type-aliases/DeployHandler.md) * [DeployParams](https://github.com/evmts/tevm/tree/main/packages/actions/docs/type-aliases/DeployParams.md) * [DeployResult](https://github.com/evmts/tevm/tree/main/packages/actions/docs/type-aliases/DeployResult.md) #### Validation Functions * [validateBaseCallParams](https://github.com/evmts/tevm/tree/main/packages/actions/docs/functions/validateBaseCallParams.md) * [validateCallParams](https://github.com/evmts/tevm/tree/main/packages/actions/docs/functions/validateCallParams.md) * [validateContractParams](https://github.com/evmts/tevm/tree/main/packages/actions/docs/functions/validateContractParams.md) * [validateGetAccountParams](https://github.com/evmts/tevm/tree/main/packages/actions/docs/functions/validateGetAccountParams.md) * [validateLoadStateParams](https://github.com/evmts/tevm/tree/main/packages/actions/docs/functions/validateLoadStateParams.md) * [validateMineParams](https://github.com/evmts/tevm/tree/main/packages/actions/docs/functions/validateMineParams.md) * [validateSetAccountParams](https://github.com/evmts/tevm/tree/main/packages/actions/docs/functions/validateSetAccountParams.md) #### JSON-RPC Procedures * [anvilImpersonateAccountJsonRpcProcedure](https://github.com/evmts/tevm/tree/main/packages/actions/docs/functions/anvilImpersonateAccountJsonRpcProcedure.md) * [callProcedure](https://github.com/evmts/tevm/tree/main/packages/actions/docs/functions/callProcedure.md) * [getAccountProcedure](https://github.com/evmts/tevm/tree/main/packages/actions/docs/functions/getAccountProcedure.md) * [mineProcedure](https://github.com/evmts/tevm/tree/main/packages/actions/docs/functions/mineProcedure.md) * [requestProcedure](https://github.com/evmts/tevm/tree/main/packages/actions/docs/functions/requestProcedure.md) * [requestBulkProcedure](https://github.com/evmts/tevm/tree/main/packages/actions/docs/functions/requestBulkProcedure.md) #### Internal Utilities * [forkAndCacheBlock](https://github.com/evmts/tevm/tree/main/packages/actions/docs/functions/forkAndCacheBlock.md) * [handlePendingTransactionsWarning](https://github.com/evmts/tevm/tree/main/packages/actions/docs/functions/handlePendingTransactionsWarning.md) * [shouldCreateTransaction](https://github.com/evmts/tevm/tree/main/packages/actions/docs/functions/shouldCreateTransaction.md) #### Ethereum JSON-RPC Actions ##### Account & Network * [EthAccountsHandler](https://github.com/evmts/tevm/tree/main/packages/actions/docs/type-aliases/EthAccountsHandler.md) * [EthChainIdHandler](https://github.com/evmts/tevm/tree/main/packages/actions/docs/type-aliases/EthChainIdHandler.md) * [EthCoinbaseHandler](https://github.com/evmts/tevm/tree/main/packages/actions/docs/type-aliases/EthCoinbaseHandler.md) * [EthGasPriceHandler](https://github.com/evmts/tevm/tree/main/packages/actions/docs/type-aliases/EthGasPriceHandler.md) * [EthBlockNumberHandler](https://github.com/evmts/tevm/tree/main/packages/actions/docs/type-aliases/EthBlockNumberHandler.md) ##### State Reading * [EthGetBalanceHandler](https://github.com/evmts/tevm/tree/main/packages/actions/docs/type-aliases/EthGetBalanceHandler.md) * [EthGetCodeHandler](https://github.com/evmts/tevm/tree/main/packages/actions/docs/type-aliases/EthGetCodeHandler.md) * [EthGetStorageAtHandler](https://github.com/evmts/tevm/tree/main/packages/actions/docs/type-aliases/EthGetStorageAtHandler.md) * [EthCallHandler](https://github.com/evmts/tevm/tree/main/packages/actions/docs/type-aliases/EthCallHandler.md) ##### Block Operations * [EthGetBlockByHashHandler](https://github.com/evmts/tevm/tree/main/packages/actions/docs/type-aliases/EthGetBlockByHashHandler.md) * [EthGetBlockByNumberHandler](https://github.com/evmts/tevm/tree/main/packages/actions/docs/type-aliases/EthGetBlockByNumberHandler.md) #### Anvil (Testing & Development) Actions ##### State Manipulation * [AnvilSetBalanceHandler](https://github.com/evmts/tevm/tree/main/packages/actions/docs/type-aliases/AnvilSetBalanceHandler.md) * [AnvilSetCodeHandler](https://github.com/evmts/tevm/tree/main/packages/actions/docs/type-aliases/AnvilSetCodeHandler.md) * [AnvilSetNonceHandler](https://github.com/evmts/tevm/tree/main/packages/actions/docs/type-aliases/AnvilSetNonceHandler.md) * [AnvilSetStorageAtHandler](https://github.com/evmts/tevm/tree/main/packages/actions/docs/type-aliases/AnvilSetStorageAtHandler.md) ##### Mining & Chain Control * [AnvilMineHandler](https://github.com/evmts/tevm/tree/main/packages/actions/docs/type-aliases/AnvilMineHandler.md) * [AnvilSetChainIdHandler](https://github.com/evmts/tevm/tree/main/packages/actions/docs/type-aliases/AnvilSetChainIdHandler.md) * [AnvilResetHandler](https://github.com/evmts/tevm/tree/main/packages/actions/docs/type-aliases/AnvilResetHandler.md) #### Debug Actions * [DebugTraceCallHandler](https://github.com/evmts/tevm/tree/main/packages/actions/docs/type-aliases/DebugTraceCallHandler.md) * [DebugTraceTransactionHandler](https://github.com/evmts/tevm/tree/main/packages/actions/docs/type-aliases/DebugTraceTransactionHandler.md) ### Usage Examples ```typescript import { createTevmNode } from 'tevm' import { callHandler, ethCallHandler } from 'tevm/actions' const client = createTevmNode() const call = await callHandler(client)({ to: '0x1234567890123456789012345678901234567890', data: '0x', value: 1000n, }) const ethCall = await ethCallHandler(client)({ to: '0x1234567890123456789012345678901234567890', data: '0x', }) ``` All actions accept `throwOnFail: false` to return errors in the result instead of throwing. ```typescript const invalidCall = await callHandler(client)({ to: '0x123', data: '0x', throwOnFail: false, }) if (invalidCall.errors) { console.error(invalidCall.errors) } ``` ### See Also * [Ethereum JSON-RPC Specification](https://ethereum.org/en/developers/docs/apis/json-rpc/) * [Anvil Documentation](https://book.getfoundry.sh/reference/anvil/) * [Full API Reference](https://github.com/evmts/tevm/tree/main/packages/actions/docs/globals.md) ## @tevm/address Utilities for Ethereum addresses. Wraps the ZEVM-compatible `EthjsAddress` primitive with a Tevm-style API and returns EIP-55 checksummed strings. ### Installation ```bash npm install @tevm/address@1.0.0-rc.151 viem ``` ### API Reference #### `Address` Extends ZEVM's `EthjsAddress` (re-exported from `@tevm/utils`). Methods: * `toString()` - checksummed hex string * `toBytes()` - `Uint8Array` * `equals(address)` - equality check * `isZero()` - zero-address check * `isPrecompileOrSystemAddress()` - precompile/system check #### `createAddress(input): Address` Accepts hex string, unprefixed hex string, number, bigint, `Uint8Array`, or `Address`. ```typescript import { createAddress } from '@tevm/address' createAddress(`0x${'00'.repeat(20)}`) createAddress(0n) createAddress(new Uint8Array(20)) createAddress('55'.repeat(20)) ``` Throws `InvalidAddressError` on invalid input. #### `createContractAddress(from: Address, nonce: bigint): Address` CREATE address. Throws `InvalidAddressError` if `from` is invalid. ```typescript import { createAddress, createContractAddress } from '@tevm/address' const contractAddress = createContractAddress(createAddress('0x1234...'), 0n) ``` #### `create2ContractAddress(from: Address, salt: string, code: string): Address` CREATE2 address ([EIP-1014](https://eips.ethereum.org/EIPS/eip-1014)). `salt` must be 32 bytes hex. ```typescript import { createAddress, create2ContractAddress } from '@tevm/address' const create2Address = create2ContractAddress( createAddress('0x1234...'), `0x${'00'.repeat(32)}`, '0x...', // creation code ) ``` Throws `InvalidSaltError` or `InvalidAddressError`. Union: `Create2ContractAddressError`. ### See Also * [EIP-55 Address Format](https://eips.ethereum.org/EIPS/eip-55) * [EIP-1014 CREATE2](https://eips.ethereum.org/EIPS/eip-1014) * [@tevm/utils](https://tevm.sh/reference/tevm/utils/) ## @tevm/block Block, block-header, and RLP/JSON-RPC serialization utilities. Includes Verkle/EIP-6800 payload types only; Tevm does not execute Verkle witnesses. Full API: [packages/block/docs](https://github.com/evmts/tevm/tree/main/packages/block/docs). ### Installation ```bash npm install @tevm/block@1.0.0-rc.151 viem ``` ### API Reference #### Core Classes * [Block](https://github.com/evmts/tevm/tree/main/packages/block/docs/classes/Block.md) * [BlockHeader](https://github.com/evmts/tevm/tree/main/packages/block/docs/classes/BlockHeader.md) * [ClRequest](https://github.com/evmts/tevm/tree/main/packages/block/docs/classes/ClRequest.md) #### Interfaces * [BlockData](https://github.com/evmts/tevm/tree/main/packages/block/docs/interfaces/BlockData.md) * [BlockOptions](https://github.com/evmts/tevm/tree/main/packages/block/docs/interfaces/BlockOptions.md) * [HeaderData](https://github.com/evmts/tevm/tree/main/packages/block/docs/interfaces/HeaderData.md) * [JsonBlock](https://github.com/evmts/tevm/tree/main/packages/block/docs/interfaces/JsonBlock.md) * [JsonHeader](https://github.com/evmts/tevm/tree/main/packages/block/docs/interfaces/JsonHeader.md) * [JsonRpcBlock](https://github.com/evmts/tevm/tree/main/packages/block/docs/interfaces/JsonRpcBlock.md) #### Verkle Payload Types Payload shapes only; Tevm does not execute Verkle/EIP-6800 state-witness blocks. * [VerkleExecutionWitness](https://github.com/evmts/tevm/tree/main/packages/block/docs/interfaces/VerkleExecutionWitness.md) * [VerkleProof](https://github.com/evmts/tevm/tree/main/packages/block/docs/interfaces/VerkleProof.md) * [VerkleStateDiff](https://github.com/evmts/tevm/tree/main/packages/block/docs/interfaces/VerkleStateDiff.md) #### Block Types * [BlockBodyBytes](https://github.com/evmts/tevm/tree/main/packages/block/docs/type-aliases/BlockBodyBytes.md) * [BlockBytes](https://github.com/evmts/tevm/tree/main/packages/block/docs/type-aliases/BlockBytes.md) * [BlockHeaderBytes](https://github.com/evmts/tevm/tree/main/packages/block/docs/type-aliases/BlockHeaderBytes.md) * [ExecutionPayload](https://github.com/evmts/tevm/tree/main/packages/block/docs/type-aliases/ExecutionPayload.md) * [BeaconPayloadJson](https://github.com/evmts/tevm/tree/main/packages/block/docs/type-aliases/BeaconPayloadJson.md) #### Utility Functions * [blockFromRpc](https://github.com/evmts/tevm/tree/main/packages/block/docs/functions/blockFromRpc.md) * [executionPayloadFromBeaconPayload](https://github.com/evmts/tevm/tree/main/packages/block/docs/functions/executionPayloadFromBeaconPayload.md) * [getDifficulty](https://github.com/evmts/tevm/tree/main/packages/block/docs/functions/getDifficulty.md) * [valuesArrayToHeaderData](https://github.com/evmts/tevm/tree/main/packages/block/docs/functions/valuesArrayToHeaderData.md) ### Usage Examples ```typescript import { Block } from '@tevm/block' import { createCommon } from '@tevm/common' import { mainnet } from 'viem/chains' import { EthjsAddress } from '@tevm/utils' const common = createCommon({ ...mainnet }) const block = new Block({ common }) const fromData = Block.fromBlockData({ header: { parentHash: '0x0000000000000000000000000000000000000000000000000000000000000000', uncleHash: '0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347', coinbase: EthjsAddress.fromString('0x0000000000000000000000000000000000000000'), stateRoot: '0x0000000000000000000000000000000000000000000000000000000000000000', transactionsTrie: '0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421', receiptTrie: '0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421', difficulty: 0n, number: 0n, gasLimit: 30000000n, gasUsed: 0n, timestamp: BigInt(Math.floor(Date.now() / 1000)), baseFeePerGas: 1000000000n, }, }, { common }) const hash = block.hash() const serialized = block.serialize() const json = block.toJSON() const fromRlp = Block.fromRLPSerializedBlock(serialized, { common }) const fromValues = Block.fromValuesArray(block.raw(), { common }) ``` ### See Also * [Ethereum JSON-RPC Specification](https://ethereum.org/en/developers/docs/apis/json-rpc/) * [Block Structure](https://ethereum.org/en/developers/docs/blocks/) * [Full API Reference](https://github.com/evmts/tevm/tree/main/packages/block/docs/globals.md) ## @tevm/blockchain Tevm's block and chain-state implementation. Manages local blocks, fork-backed lookup, canonical heads, iterator heads, and chain validation using Tevm block types and ZEVM-compatible primitives. Full API: [packages/blockchain/docs](https://github.com/evmts/tevm/tree/main/packages/blockchain/docs). ### Installation ```bash npm install @tevm/blockchain@1.0.0-rc.151 viem ``` ### API Reference #### `Chain` Main blockchain interface. Methods: * `putBlock(block)` - add a block * `delBlock(blockHash)` - delete a block and its children * `getBlock(blockId)` - lookup by hash or number * `getBlockByTag(blockTag)` - lookup by tag (`latest`, `earliest`, etc.) * `getCanonicalHeadBlock()` - latest block on canonical chain * `validateHeader(header)` - header validation * `iterator(name, onBlock, maxBlocks?)` - iterate blocks * `getIteratorHead(name)` / `setIteratorHead(name, hash)` - iterator head management * `deepCopy()` / `shallowCopy()` - copy helpers for snapshots and simulations #### `ChainOptions` ```typescript type ChainOptions = { common: Common loggingLevel?: LogLevel genesisBlock?: Block genesisStateRoot?: Uint8Array fork?: { transport: { request: EIP1193RequestFn } blockTag?: BlockTag | bigint | `0x${string}` } } ``` #### Functions * `createChain(options): Promise` - create a new chain. * `createBaseChain(options): BaseChain` - internal implementation used by `createChain`. #### Errors `BlockNotFoundError`, `InvalidBlockError`, `InvalidHeaderError`, `InvalidChainError`. ### Usage Examples ```typescript import { createChain } from '@tevm/blockchain' import { createCommon, mainnet } from '@tevm/common' import { http } from 'viem' const chain = await createChain({ common: createCommon({ ...mainnet }), loggingLevel: 'debug', fork: { transport: http('https://mainnet.infura.io/v3/YOUR-KEY')({}), blockTag: 'latest', }, }) await chain.putBlock(block) const head = await chain.getCanonicalHeadBlock() const byNumber = await chain.getBlock(1234n) const latest = await chain.getBlockByTag('latest') await chain.validateHeader(block.header) await chain.delBlock(block.hash()) await chain.iterator('vm', async (block, reorg) => { if (reorg) console.log('reorg') console.log(block.header.number) }, 1000) ``` ### See Also * [VM & Submodules](../api/vm-and-submodules) * [@tevm/block](https://tevm.sh/reference/tevm/block/) * [@tevm/common](https://tevm.sh/reference/tevm/common/) * [Full API Reference](https://github.com/evmts/tevm/tree/main/packages/blockchain/docs/globals.md) ## Bundler Plugins Tevm bundler plugins enable direct Solidity imports in TypeScript/JavaScript, compiling them into type-safe Tevm Contract instances at build time. :::note The bundler is optional. You can also generate contract types with `npx tevm gen` (see [Codegen Approach](#codegen-approach)). ::: ### Available Plugins | Bundler | Plugin Import Path | Repository | | ------- | ----------------------------- | ---------------------------------------------------------------------------------------- | | Vite | `tevm/bundler/vite-plugin` | [@tevm/vite-plugin](https://github.com/evmts/tevm/tree/main/bundler-packages/vite) | | Webpack | `tevm/bundler/webpack-plugin` | [@tevm/webpack-plugin](https://github.com/evmts/tevm/tree/main/bundler-packages/webpack) | | Rollup | `tevm/bundler/rollup-plugin` | [@tevm/rollup-plugin](https://github.com/evmts/tevm/tree/main/bundler-packages/rollup) | | ESBuild | `tevm/bundler/esbuild-plugin` | [@tevm/esbuild-plugin](https://github.com/evmts/tevm/tree/main/bundler-packages/esbuild) | | Bun | `tevm/bundler/bun-plugin` | [@tevm/bun-plugin](https://github.com/evmts/tevm/tree/main/bundler-packages/bun) | | Rspack | `tevm/bundler/rspack-plugin` | [@tevm/rspack-plugin](https://github.com/evmts/tevm/tree/main/bundler-packages/rspack) | All plugins share a configuration interface. ### Prerequisites & Key Points * **Optional**: `npx tevm gen` works without any bundler integration. * **TypeScript**: Add `@tevm/ts-plugin` to `tsconfig.json` for editor support (NatSpec hovers, go-to-definition). * **`.s.sol` for bytecode**: regular `.sol` produces ABI only; `.s.sol` includes deployable bytecode. * **Cache**: artifacts go in `.tevm/` — add it to `.gitignore`. * **Foundry/remappings**: configure in `tevm.config.json`. * **Next.js**: type-checker conflicts; use [codegen](#codegen-approach) or disable `next.config` typechecks. ### Plugin Configuration Bundler plugins accept a `solc` version string. Global settings (Foundry, libs, remappings) live in `tevm.config.json`. ### Bundler-Specific Setup :::code-group ```ts [vite.config.ts] import { defineConfig } from 'vite' import react from '@vitejs/plugin-react' import { vitePluginTevm } from 'tevm/bundler/vite-plugin' export default defineConfig({ plugins: [react(), vitePluginTevm({ solc: '0.8.20' })], }) ``` ```js [webpack.config.js] const { webpackPluginTevm } = require('tevm/bundler/webpack-plugin') module.exports = { plugins: [webpackPluginTevm({ solc: '0.8.20' })], } ``` ```js [rollup.config.js] import { rollupPluginTevm } from 'tevm/bundler/rollup-plugin' export default { plugins: [rollupPluginTevm({ solc: '0.8.20' })], } ``` ```js [build.js (esbuild)] const { build } = require('esbuild') const { esbuildPluginTevm } = require('tevm/bundler/esbuild-plugin') build({ entryPoints: ['src/index.js'], outdir: 'dist', bundle: true, plugins: [esbuildPluginTevm({ solc: '0.8.20' })], }) ``` ```ts [plugins.ts (bun)] import { plugin } from 'bun' import { bunPluginTevm } from 'tevm/bundler/bun-plugin' plugin(bunPluginTevm({ solc: '0.8.20' })) ``` ```js [rspack.config.js] const { rspackPluginTevm } = require('tevm/bundler/rspack-plugin') module.exports = { plugins: [rspackPluginTevm({ solc: '0.8.20' })], } ``` ::: For Bun, register the plugin in `bunfig.toml`: ```toml preload = ["./plugins.ts"] [test] preload = ["./plugins.ts"] ``` ### TypeScript Plugin ```json { "compilerOptions": { "plugins": [{ "name": "@tevm/ts-plugin" }] } } ``` In VSCode, switch to the workspace TypeScript version. ### How the Bundler Works All Tevm bundler plugins share a unified core (`@tevm/base-bundler`): * **Import detection & resolution**: scans `.sol` imports, merges tsconfig paths, foundry remappings, and `tevm.config.json`. * **Compilation**: runs solc on the dependency graph; `.s.sol` includes bytecode, `.sol` is ABI-only. * **Code generation**: emits a TS module exporting a Tevm Contract (with `.read`, `.write`, abi, optional bytecode). * **Caching**: stores results in `.tevm/`. * **LSP**: `@tevm/ts-plugin` references bundler outputs for IDE features. ### Configuration with tevm.config.json ```json { "foundryProject": true, "libs": ["./lib", "./node_modules"], "remappings": { "foo": "vendored/foo" }, "debug": false, "cacheDir": ".tevm", "jsonAsConst": ["**/*.abi.json"] } ``` | Option | Type | Description | | ---------------- | ------------------------ | ------------------------------------------------- | | `foundryProject` | `boolean \| string` | Enable Foundry (`true`) or path to `foundry.toml` | | `libs` | `string[]` | Library paths for Solidity imports | | `remappings` | `Record` | Custom import remappings | | `debug` | `boolean` | Extra debug logs and files in `.tevm` | | `cacheDir` | `string` | Artifact location (default: `.tevm`) | | `jsonAsConst` | `string \| string[]` | Glob patterns for `as const` JSON imports | ### Codegen Approach ```bash npx tevm gen ``` Generates `.ts` files next to each `.sol`. Use this when a bundler hook is impractical (e.g., Next.js with strict typechecking). ### Troubleshooting * **Red underlines on `.sol` imports**: ensure `@tevm/ts-plugin` is in tsconfig and you're using the workspace TS version. * **Next.js type errors**: disable typechecking or use codegen. * **File not found**: check libs/remappings; set `foundryProject: true` for Foundry projects. * **Stale cache**: delete `.tevm/`. ### Examples and Further Reading * [Examples](https://github.com/evmts/tevm/tree/main/examples) - Vite, Next, Bun, ESBuild * [Tevm Contract Reference](/reference/contract) * [Wagmi + Tevm examples](https://github.com/evmts/tevm/tree/main/examples) * [base-bundler globals](https://github.com/evmts/tevm/tree/main/bundler-packages/base-bundler/docs/globals.md) ## Tevm Contract Bundler Import Solidity files directly into TypeScript with type safety and IDE integration. * **[Overview](/reference/bundler/overview)** - Introduction, key benefits, available plugins * **[Internals](/reference/bundler/internals)** - How the bundler works under the hood * **[Methods & Exports](/reference/bundler/methods)** - Key APIs for advanced usage * **[Troubleshooting](/reference/bundler/troubleshooting)** - Common issues and solutions ### What is the Tevm Bundler? At build time, the bundler reads `.sol` files, runs solc on the dependency graph, extracts ABI and (for `.s.sol`) bytecode, and emits a TypeScript module exporting a [Tevm Contract](/reference/contract) instance. For a quickstart, see [Bundler Quickstart](/getting-started/bundler). The supported surface is direct `.sol` imports through the package-specific plugins described in the overview. The reference does not document unreleased inline-Solidity or chain-address loaders. ## Built-in chain presets `@tevm/common` exports ready-to-use EVM chain configurations with chain IDs, hardfork histories, and RPC metadata. Reach for a preset when creating a Tevm client for a known network instead of assembling `Common` options by hand. ### Working example This complete example was run with `@tevm/common@1.0.0-rc.151` and `viem@2.49.3`. ```ts import assert from 'node:assert/strict' import { anvil, arbitrum, base, mainnet, optimism, sepolia } from '@tevm/common' const chains = [mainnet, sepolia, anvil, arbitrum, optimism, base] assert.deepEqual( chains.map((chain) => [chain.name, chain.id]), [ ['Ethereum', 1], ['Sepolia', 11155111], ['Anvil', 31337], ['Arbitrum One', 42161], ['OP Mainnet', 10], ['Base', 8453], ], ) console.log(chains.map((chain) => `${chain.name}: ${chain.id}`).join('\n')) ``` ```text Ethereum: 1 Sepolia: 11155111 Anvil: 31337 Arbitrum One: 42161 OP Mainnet: 10 Base: 8453 ``` ### Preset exports The generated [`presets/index.ts`](https://github.com/evmts/tevm/blob/main/packages/common/src/presets/index.ts) is the complete export list. These are the primary presets covered by this feature: | Export | Chain ID | Use | | ---------- | -------: | ---------------- | | `mainnet` | 1 | Ethereum mainnet | | `sepolia` | 11155111 | Ethereum Sepolia | | `anvil` | 31337 | Foundry Anvil | | `arbitrum` | 42161 | Arbitrum One | | `optimism` | 10 | OP Mainnet | | `base` | 8453 | Base mainnet | Every preset is a `Common` configuration and can be passed as the `common` option to [`createTevmNode`](/core/create-tevm-node) or [`createMemoryClient`](/reference/memory-client). ### Neighbours [Common reference](/reference/common) · [Create a node](/core/create-tevm-node) · [Forking](/core/forking) ## @tevm/common Chain-specific configuration. Combines viem chain definitions with a ZEVM-backed `Common` instance the VM uses for hardfork, EIP, consensus, and gas-parameter lookups. Includes custom crypto hooks such as KZG for blob transaction testing. Full API: [packages/common/docs](https://github.com/evmts/tevm/tree/main/packages/common/docs). ### Installation ```bash npm install @tevm/common@1.0.0-rc.151 viem ``` ### API Reference #### Enumerations * [ConsensusAlgorithm](https://github.com/evmts/tevm/tree/main/packages/common/docs/enumerations/ConsensusAlgorithm.md) * [ConsensusType](https://github.com/evmts/tevm/tree/main/packages/common/docs/enumerations/ConsensusType.md) #### Interfaces * [CustomCrypto](https://github.com/evmts/tevm/tree/main/packages/common/docs/interfaces/CustomCrypto.md) * [EvmStateManagerInterface](https://github.com/evmts/tevm/tree/main/packages/common/docs/interfaces/EvmStateManagerInterface.md) * [StorageDump](https://github.com/evmts/tevm/tree/main/packages/common/docs/interfaces/StorageDump.md) * [StorageRange](https://github.com/evmts/tevm/tree/main/packages/common/docs/interfaces/StorageRange.md) #### Type Aliases * [AccountFields](https://github.com/evmts/tevm/tree/main/packages/common/docs/type-aliases/AccountFields.md) * [CliqueConfig](https://github.com/evmts/tevm/tree/main/packages/common/docs/type-aliases/CliqueConfig.md) * [Common](https://github.com/evmts/tevm/tree/main/packages/common/docs/type-aliases/Common.md) * [CommonOptions](https://github.com/evmts/tevm/tree/main/packages/common/docs/type-aliases/CommonOptions.md) * [Hardfork](https://github.com/evmts/tevm/tree/main/packages/common/docs/type-aliases/Hardfork.md) * [MockKzg](https://github.com/evmts/tevm/tree/main/packages/common/docs/type-aliases/MockKzg.md) #### Functions * [createCommon](https://github.com/evmts/tevm/tree/main/packages/common/docs/functions/createCommon.md) * [createMockKzg](https://github.com/evmts/tevm/tree/main/packages/common/docs/functions/createMockKzg.md) #### Supported Networks **Layer 1**: [mainnet](https://github.com/evmts/tevm/tree/main/packages/common/docs/variables/mainnet.md), [sepolia](https://github.com/evmts/tevm/tree/main/packages/common/docs/variables/sepolia.md), [goerli](https://github.com/evmts/tevm/tree/main/packages/common/docs/variables/goerli.md), [holesky](https://github.com/evmts/tevm/tree/main/packages/common/docs/variables/holesky.md). **Layer 2**: [arbitrum](https://github.com/evmts/tevm/tree/main/packages/common/docs/variables/arbitrum.md), [optimism](https://github.com/evmts/tevm/tree/main/packages/common/docs/variables/optimism.md), [base](https://github.com/evmts/tevm/tree/main/packages/common/docs/variables/base.md), [zksync](https://github.com/evmts/tevm/tree/main/packages/common/docs/variables/zksync.md), [polygon](https://github.com/evmts/tevm/tree/main/packages/common/docs/variables/polygon.md), [polygonZkEvm](https://github.com/evmts/tevm/tree/main/packages/common/docs/variables/polygonZkEvm.md). **Alternative**: [bsc](https://github.com/evmts/tevm/tree/main/packages/common/docs/variables/bsc.md), [avalanche](https://github.com/evmts/tevm/tree/main/packages/common/docs/variables/avalanche.md), [fantom](https://github.com/evmts/tevm/tree/main/packages/common/docs/variables/fantom.md), [gnosis](https://github.com/evmts/tevm/tree/main/packages/common/docs/variables/gnosis.md). **Dev**: [hardhat](https://github.com/evmts/tevm/tree/main/packages/common/docs/variables/hardhat.md), [foundry](https://github.com/evmts/tevm/tree/main/packages/common/docs/variables/foundry.md), [anvil](https://github.com/evmts/tevm/tree/main/packages/common/docs/variables/anvil.md), [localhost](https://github.com/evmts/tevm/tree/main/packages/common/docs/variables/localhost.md). ### Usage Examples ```typescript import { createCommon, createMockKzg, mainnet, optimism, arbitrum } from '@tevm/common' const common = createCommon({ ...mainnet, hardfork: 'shanghai' }) const custom = createCommon({ name: 'Custom Chain', id: 1337, nativeCurrency: { name: 'Ether', symbol: 'ETH', decimals: 18 }, rpcUrls: { default: { http: ['http://localhost:8545'] } }, hardfork: 'shanghai', }) const withKzg = createCommon({ ...mainnet, customCrypto: { kzg: createMockKzg() }, }) const optimismCommon = createCommon({ ...optimism }) const arbitrumCommon = createCommon({ ...arbitrum }) ``` The returned `Common` is a viem chain object plus: * `ethjsCommon` - ZEVM-backed Common instance used internally by the VM. * `copy()` - isolated copy for a new VM or client. ### See Also * [VM & Submodules](../api/vm-and-submodules) * [Viem Chains](https://viem.sh/docs/chains/introduction.html) * [Full API Reference](https://github.com/evmts/tevm/tree/main/packages/common/docs/globals.md) ## Solidity contract type generator `tevm-gen` compiles matching Solidity files and writes adjacent TypeScript contract modules. Reach for it when build tooling cannot transform `.sol` imports directly or when generated modules must be checked into a package. ### Working example The rc.151 generator must run under Bun. This example was executed with `@tevm/ts-plugin@1.0.0-rc.151`. ```bash npm install --save-dev @tevm/ts-plugin@1.0.0-rc.151 typescript@5.9.3 mkdir -p contracts cat > tevm.json <<'JSON' { "foundryProject": false } JSON cat > contracts/Counter.sol <<'SOLIDITY' // SPDX-License-Identifier: MIT pragma solidity ^0.8.20; contract Counter { uint256 public number; function setNumber(uint256 next) public { number = next; } } SOLIDITY bunx --bun tevm-gen . 'contracts/**/*.sol' test -f contracts/Counter.sol.ts ``` ```text Generating types from contracts... { dir: ".", include: [ "contracts/**/*.sol" ], } No caching for module type ts} implemented yet ``` The generated `contracts/Counter.sol.ts` exports a typed `Counter` contract, its ABI, creation bytecode, deployed bytecode, and compiler artifacts. ### Command API The argument parser in [`tevm-gen.js`](https://github.com/evmts/tevm/blob/main/lsp/ts-plugin/src/bin/tevm-gen.js) exposes: | Position | Name | Default | Meaning | | -------: | -------------- | ----------------- | ------------------------------------------ | | 1 | `cwd` | Current directory | Project root containing `tevm.json` | | 2 | `include` | `src/**/*.sol` | One or more comma-separated Solidity globs | | flag | `-h`, `--help` | false | Print usage | `tevm-gen` writes `.ts` next to each matching Solidity file. ### Neighbours [Bundler overview](/reference/bundler/overview) · [Bundler methods](/reference/bundler/methods) · [Contract reference](/reference/contract) ## @tevm/contract Type-safe contract interactions, deployments, events, and pre-built ERC20/ERC721 contracts. Full API: [packages/contract/docs](https://github.com/evmts/tevm/tree/main/packages/contract/docs). ### Installation ```bash npm install @tevm/contract@1.0.0-rc.151 viem ``` ### API Reference #### Type Aliases * [Contract](https://github.com/evmts/tevm/tree/main/packages/contract/docs/type-aliases/Contract.md) * [CreateContractFn](https://github.com/evmts/tevm/tree/main/packages/contract/docs/type-aliases/CreateContractFn.md) * [CreateContractParams](https://github.com/evmts/tevm/tree/main/packages/contract/docs/type-aliases/CreateContractParams.md) * [EventActionCreator](https://github.com/evmts/tevm/tree/main/packages/contract/docs/type-aliases/EventActionCreator.md) * [MaybeExtractEventArgsFromAbi](https://github.com/evmts/tevm/tree/main/packages/contract/docs/type-aliases/MaybeExtractEventArgsFromAbi.md) * [ReadActionCreator](https://github.com/evmts/tevm/tree/main/packages/contract/docs/type-aliases/ReadActionCreator.md) * [ValueOf](https://github.com/evmts/tevm/tree/main/packages/contract/docs/type-aliases/ValueOf.md) * [WriteActionCreator](https://github.com/evmts/tevm/tree/main/packages/contract/docs/type-aliases/WriteActionCreator.md) #### Functions * [createContract](https://github.com/evmts/tevm/tree/main/packages/contract/docs/functions/createContract.md) #### Pre-built Contracts * [ERC20](https://github.com/evmts/tevm/tree/main/packages/contract/docs/variables/ERC20.md) * [ERC721](https://github.com/evmts/tevm/tree/main/packages/contract/docs/variables/ERC721.md) * [SimpleContract](https://github.com/evmts/tevm/tree/main/packages/contract/docs/variables/SimpleContract.md) ### Usage Examples ```typescript import { createContract, ERC20, ERC721 } from '@tevm/contract' const contract = createContract({ humanReadableAbi: [ 'function balanceOf(address) view returns (uint256)', 'function transfer(address to, uint256 amount) returns (bool)', 'event Transfer(address indexed from, address indexed to, uint256 value)', ] as const, name: 'MyToken', }) const readAction = contract.read.balanceOf('0x...') const writeAction = contract.write.transfer('0x...', 1000n) const token = contract.withAddress('0x1234...') const balance = token.read.balanceOf('0x...') const erc20 = ERC20.withAddress('0x...') const nameAction = erc20.read.name() const transferAction = erc20.write.transfer('0x...', 1000n) const nft = ERC721.withAddress('0x...') const ownerAction = nft.read.ownerOf(1n) ``` #### Event Filters ```typescript const filter = contract.events.Transfer({ fromBlock: 'latest' }) client.watchEvent(filter, (event) => { console.log(event.args.from, event.args.to, event.args.value) }) ``` ### Best Practices Use `as const` with ABIs for full type inference: ```typescript const abi = ['function example(uint256 value) returns (bool)'] as const const contract = createContract({ humanReadableAbi: abi, name: 'Example' }) ``` Set explicit gas for writes that need it: ```typescript const tx = contract.write.complexOperation('0x...', { gas: 500000n, maxFeePerGas: 30000000000n, }) ``` ### Exported Types ```typescript import type { CreateContractFn, CreateContractParams, EventActionCreator, ReadActionCreator, WriteActionCreator, } from '@tevm/contract' ``` ### See Also * [ERC-20](https://ethereum.org/en/developers/docs/standards/tokens/erc-20/) * [ERC-721](https://ethereum.org/en/developers/docs/standards/tokens/erc-721/) * [OpenZeppelin Contracts](https://docs.openzeppelin.com/contracts/) * [Full API Reference](https://github.com/evmts/tevm/tree/main/packages/contract/docs/globals.md) ## @tevm/decorators Action decorators for extending Tevm clients: EIP-1193 providers, Ethereum JSON-RPC methods, and Tevm-specific actions. Full API: [packages/decorators/docs](https://github.com/evmts/tevm/tree/main/packages/decorators/docs). ### Installation ```bash npm install @tevm/decorators@1.0.0-rc.151 @tevm/node@1.0.0-rc.151 viem ``` ### API Reference #### Core Functions * [`ethActions()`](https://github.com/evmts/tevm/blob/main/packages/decorators/docs/functions/ethActions.md) - standard Ethereum JSON-RPC methods. * [`requestEip1193()`](https://github.com/evmts/tevm/blob/main/packages/decorators/docs/functions/requestEip1193.md) - EIP-1193 provider extension. * [`tevmActions()`](https://github.com/evmts/tevm/blob/main/packages/decorators/docs/functions/tevmActions.md) - Tevm-specific actions. * [`tevmSend()`](https://github.com/evmts/tevm/blob/main/packages/decorators/docs/functions/tevmSend.md) - send Tevm JSON-RPC requests. #### Provider Types * [`Eip1193RequestProvider`](https://github.com/evmts/tevm/tree/main/packages/decorators/docs/type-aliases/Eip1193RequestProvider.md) * [`EIP1193Parameters`](https://github.com/evmts/tevm/tree/main/packages/decorators/docs/type-aliases/EIP1193Parameters.md) * [`EIP1193RequestFn`](https://github.com/evmts/tevm/tree/main/packages/decorators/docs/type-aliases/EIP1193RequestFn.md) * [`EIP1193RequestOptions`](https://github.com/evmts/tevm/tree/main/packages/decorators/docs/type-aliases/EIP1193RequestOptions.md) #### Action Types * [`EthActionsApi`](https://github.com/evmts/tevm/blob/main/packages/decorators/docs/type-aliases/EthActionsApi.md) * [`TevmActionsApi`](https://github.com/evmts/tevm/blob/main/packages/decorators/docs/type-aliases/TevmActionsApi.md) * [`TevmSendApi`](https://github.com/evmts/tevm/blob/main/packages/decorators/docs/type-aliases/TevmSendApi.md) #### RPC Schema Types * [`RpcSchema`](https://github.com/evmts/tevm/blob/main/packages/decorators/docs/type-aliases/RpcSchema.md) * [`RpcSchemaOverride`](https://github.com/evmts/tevm/blob/main/packages/decorators/docs/type-aliases/RpcSchemaOverride.md) * [`DerivedRpcSchema`](https://github.com/evmts/tevm/blob/main/packages/decorators/docs/type-aliases/DerivedRpcSchema.md) * [`JsonRpcSchemaPublic`](https://github.com/evmts/tevm/blob/main/packages/decorators/docs/type-aliases/JsonRpcSchemaPublic.md) * [`JsonRpcSchemaTevm`](https://github.com/evmts/tevm/blob/main/packages/decorators/docs/type-aliases/JsonRpcSchemaTevm.md) * [`JsonRpcSchemaWallet`](https://github.com/evmts/tevm/blob/main/packages/decorators/docs/type-aliases/JsonRpcSchemaWallet.md) * [`TestRpcSchema`](https://github.com/evmts/tevm/blob/main/packages/decorators/docs/type-aliases/TestRpcSchema.md) #### Ethereum Types * [`AddEthereumChainParameter`](https://github.com/evmts/tevm/blob/main/packages/decorators/docs/type-aliases/AddEthereumChainParameter.md) * [`WatchAssetParams`](https://github.com/evmts/tevm/blob/main/packages/decorators/docs/type-aliases/WatchAssetParams.md) * [`WalletPermission`](https://github.com/evmts/tevm/blob/main/packages/decorators/docs/type-aliases/WalletPermission.md) * [`WalletPermissionCaveat`](https://github.com/evmts/tevm/blob/main/packages/decorators/docs/type-aliases/WalletPermissionCaveat.md) #### Utility Types * [`Hash`](https://github.com/evmts/tevm/blob/main/packages/decorators/docs/type-aliases/Hash.md) * [`LogTopic`](https://github.com/evmts/tevm/blob/main/packages/decorators/docs/type-aliases/LogTopic.md) * [`NetworkSync`](https://github.com/evmts/tevm/blob/main/packages/decorators/docs/type-aliases/NetworkSync.md) * [`Quantity`](https://github.com/evmts/tevm/blob/main/packages/decorators/docs/type-aliases/Quantity.md) ### Usage Examples ```typescript import { createTevmNode } from '@tevm/node' import { requestEip1193, ethActions, tevmActions } from '@tevm/decorators' const node = createTevmNode() const eip1193Node = node.extend(requestEip1193()) const chainId = await eip1193Node.request({ method: 'eth_chainId' }) const ethNode = node.extend(ethActions()) const balance = await ethNode.eth.getBalance({ address: '0x1111111111111111111111111111111111111111', }) const tevmNode = node.extend(tevmActions()) await tevmNode.setAccount({ address: '0x1111111111111111111111111111111111111111', balance: 1n, }) const account = await tevmNode.getAccount({ address: '0x1111111111111111111111111111111111111111', }) console.log(chainId, balance, account.balance) ``` #### Error Codes ```typescript try { await client.request({ method: 'eth_call', params: [{ to: '0x...', data: '0x...' }] }) } catch (error) { if (error.code === 4001) { // user rejected } else if (error.code === -32000) { // execution error } } ``` #### Chain Parameters ```typescript const chainParams: AddEthereumChainParameter = { chainId: '0x1', chainName: 'Ethereum Mainnet', nativeCurrency: { name: 'Ether', symbol: 'ETH', decimals: 18 }, rpcUrls: ['https://...'], } ``` ### See Also * [JSON-RPC API](/api/json-rpc) * [Actions Guide](/reference/actions) * [EIP-1193](https://eips.ethereum.org/EIPS/eip-1193) * [Ethereum JSON-RPC](https://ethereum.org/en/developers/docs/apis/json-rpc/) ## @tevm/evm Tevm's low-level EVM facade. Backed by `@evmts/zevm/evm` and wrapped with Tevm-specific defaults for state, blockchain, precompiles, predeploys, logging, profiling, and unlimited-contract-size testing. Most apps should use `createMemoryClient`, viem actions, or JSON-RPC. Use `@tevm/evm` directly when building Tevm extensions, debuggers, or profilers. Full API: [packages/evm/docs](https://github.com/evmts/tevm/tree/main/packages/evm/docs). ### Installation ```bash npm install @tevm/evm@1.0.0-rc.151 viem ``` ### API Reference * [Evm](https://github.com/evmts/tevm/tree/main/packages/evm/docs/classes/Evm.md) - EVM facade. * [createEvm](https://github.com/evmts/tevm/tree/main/packages/evm/docs/functions/createEvm.md) - creates an EVM for a Tevm VM. * [CreateEvmOptions](https://github.com/evmts/tevm/tree/main/packages/evm/docs/type-aliases/CreateEvmOptions.md) * [CustomPrecompile](https://github.com/evmts/tevm/tree/main/packages/evm/docs/type-aliases/CustomPrecompile.md) * [EVMOpts](https://github.com/evmts/tevm/tree/main/packages/evm/docs/type-aliases/EVMOpts.md) - ZEVM EVM options exposed through Tevm. * Re-exported ZEVM EVM types: `EvmError`, `EVMError`, `EvmResult`, `EvmRunCallOpts`, `ExecResult`, `InterpreterStep`, `Log`, `EthjsMessage`, `PrecompileInput`. ### Usage Examples ```typescript import { createChain } from '@tevm/blockchain' import { mainnet } from '@tevm/common' import { createEvm } from '@tevm/evm' import { createStateManager } from '@tevm/state' import { createAddress } from '@tevm/address' const common = mainnet.copy() const stateManager = createStateManager({}) const blockchain = await createChain({ common }) const evm = await createEvm({ common, stateManager, blockchain, profiler: false, loggingLevel: 'warn', }) const result = await evm.runCall({ to: createAddress('0x1234567890123456789012345678901234567890'), caller: createAddress('0x5678901234567890123456789012345678901234'), data: new Uint8Array(), value: 1000n, gasLimit: 100000n, }) evm.events?.on('step', (step) => { console.log({ pc: step.pc, opcode: step.opcode.name, gasLeft: step.gasLeft, depth: step.depth }) }) ``` #### Custom Precompiles ```typescript import { createContract, createMemoryClient, defineCall, definePrecompile, parseAbi } from 'tevm' const Calculator = createContract({ name: 'Calculator', address: '0x0000000000000000000000000000000000000a11', abi: parseAbi(['function addTwo(uint256 value) returns (uint256)']), }) const calculatorPrecompile = definePrecompile({ contract: Calculator, call: defineCall(Calculator.abi, { addTwo: async ({ args }) => ({ returnValue: args[0] + 2n, executionGasUsed: 0n }), }), }) const client = createMemoryClient({ customPrecompiles: [calculatorPrecompile.precompile()], }) ``` ### See Also * [VM & Submodules](../api/vm-and-submodules) * [EVM Events](../api/evm-events) * [Custom Precompiles](../advanced/custom-precompiles) * [@tevm/state](https://tevm.sh/reference/tevm/state/) * [Full API Reference](https://github.com/evmts/tevm/tree/main/packages/evm/docs/globals.md) ## Package Reference Documentation * [@tevm/actions](/reference/actions) - Core action handlers for interacting with the EVM * [@tevm/address](/reference/address) - Ethereum address utilities * [@tevm/block](/reference/block) - Block creation and manipulation * [@tevm/blockchain](/reference/blockchain) - Blockchain data structures and utilities * [@tevm/common](/reference/common) - Shared utilities and constants * [@tevm/contract](/reference/contract) - Library for using contracts in typesafe way * [Contract Bundler](/reference/bundler) - Import Solidity files directly in TypeScript * [@tevm/decorators](/reference/decorators) - Extension decorators * [@tevm/evm](/reference/evm) - Core EVM implementation * [@tevm/memory-client](/reference/memory-client) - Batteries included viem client along with tree shakable actions * [@tevm/receipt-manager](/reference/receipt-manager) - Transaction receipt handling * [@tevm/state](/reference/state) - State management utilities * [@tevm/tx](/reference/tx) - Transaction handling utilities * [@tevm/txpool](/reference/txpool) - Transaction pool management * [@tevm/utils](/reference/utils) - General utility functions * [@tevm/vm](/reference/vm) - Virtual Machine implementation ## Memory Client Install the rc.151 client through the main package: ```bash npm install tevm@1.0.0-rc.151 viem ``` `createMemoryClient` returns synchronously and combines a Tevm transport with viem public, wallet, test, and Tevm actions. ### Create a Client ```ts import { createMemoryClient } from 'tevm' const client = createMemoryClient({ miningConfig: { type: 'manual' }, }) await client.tevmReady() console.log(await client.getBlockNumber()) ``` `tevmReady()` is optional for local clients and useful for eagerly initializing a fork. ### Action Groups * **Public:** `getBalance`, `getBlock`, `getTransaction`, `getTransactionReceipt`, `getLogs`, `readContract` * **Wallet:** `sendTransaction`, `writeContract`, `deployContract`, signing actions * **Test:** `setBalance`, `setCode`, `setStorageAt`, `mine`, `snapshot`, `revert` * **Tevm:** `tevmCall`, `tevmContract`, `tevmDeploy`, `tevmGetAccount`, `tevmSetAccount`, `tevmMine`, `tevmDumpState`, `tevmLoadState` ### State and Mining ```ts import { createMemoryClient, PREFUNDED_ACCOUNTS } from 'tevm' const client = createMemoryClient({ miningConfig: { type: 'manual' }, }) const recipient = '0x1111111111111111111111111111111111111111' await client.tevmSetAccount({ address: recipient, balance: 10n, }) const account = await client.tevmGetAccount({ address: recipient }) const { txHash } = await client.tevmCall({ from: PREFUNDED_ACCOUNTS[0].address, to: recipient, value: 1n, addToMempool: true, }) if (!txHash) throw new Error('transaction was not added to the txpool') await client.tevmMine({ blockCount: 1 }) const receipt = await client.getTransactionReceipt({ hash: txHash }) console.log(account.balance, receipt.status) ``` Use `client.mine({ blocks: 1 })` for the viem test action and `client.tevmMine({ blockCount: 1 })` for the Tevm action. ### Forking ```ts import { createMemoryClient, http } from 'tevm' import { mainnet } from 'tevm/common' const client = createMemoryClient({ common: mainnet, fork: { transport: http('https://ethereum-rpc.publicnode.com')({}), blockTag: 20_000_000n, }, }) await client.tevmReady() console.log(await client.getBlockNumber()) ``` ### Persistence `createSyncStoragePersister` is exported from `tevm` and `tevm/sync-storage-persister`. Pass the persister through client options when an application needs state hydration and synchronous persistence. ### Low-Level Node The underlying node is available as `client.transport.tevm`. This is an advanced escape hatch: ```ts import { createMemoryClient } from 'tevm' const client = createMemoryClient() const node = client.transport.tevm const vm = await node.getVm() console.log((await vm.blockchain.getCanonicalHeadBlock()).header.number) ``` Prefer the client actions unless direct VM, txpool, or receipt-manager access is required. ## @tevm/node API Reference Full API on GitHub: [packages/node/docs/globals.md](https://github.com/evmts/tevm/tree/main/packages/node/docs/globals.md). * [Type Aliases](https://github.com/evmts/tevm/tree/main/packages/node/docs/type-aliases) * [Classes](https://github.com/evmts/tevm/tree/main/packages/node/docs/classes) * [Functions](https://github.com/evmts/tevm/tree/main/packages/node/docs/functions) * [Variables](https://github.com/evmts/tevm/tree/main/packages/node/docs/variables) ## @tevm/receipt-manager ZEVM-backed transaction receipt storage and lookup. Powers Tevm's `eth_getTransactionReceipt`, `eth_getBlockReceipts`, `eth_getLogs`, filter, and subscription flows. ### Installation ```bash npm install @tevm/receipt-manager@1.0.0-rc.151 viem ``` ### API #### ReceiptsManager ```typescript import { ReceiptsManager } from '@tevm/receipt-manager' const receiptsManager = new ReceiptsManager(mapDb, chain) ``` Methods: * `saveReceipts(block, receipts)` * `getReceipts(blockHash)` * `getReceiptByTxHash(txHash)` * `getLogs(from, to, addresses?, topics?)` * `deleteReceipts(block)` #### Receipt Types ```typescript interface BaseTxReceipt { cumulativeBlockGasUsed: bigint bitvector: Uint8Array logs: Log[] } interface PreByzantiumTxReceipt extends BaseTxReceipt { stateRoot: Uint8Array } interface PostByzantiumTxReceipt extends BaseTxReceipt { status: 0 | 1 } interface EIP4844BlobTxReceipt extends PostByzantiumTxReceipt { blobGasUsed: bigint blobGasPrice: bigint } type TxReceipt = PreByzantiumTxReceipt | PostByzantiumTxReceipt | EIP4844BlobTxReceipt ``` #### MapDb ```typescript import { createMapDb } from '@tevm/receipt-manager' const mapDb = createMapDb({ cache: new Map() }) ``` ```typescript interface MetaDBManagerOptions { cache: Map<`0x${string}`, Uint8Array> } ``` #### Limits ```typescript GET_LOGS_LIMIT = 10000 GET_LOGS_LIMIT_MEGABYTES = 150 GET_LOGS_BLOCK_RANGE_LIMIT = 2500 ``` ### Usage Examples ```typescript await receiptsManager.saveReceipts(block, receipts) const blockReceipts = await receiptsManager.getReceipts(blockHash) const receipt = await receiptsManager.getReceiptByTxHash(txHash) const logs = await receiptsManager.getLogs(fromBlock, toBlock, addresses, topics) ``` #### DbType ```typescript type DbType = 'Receipts' | 'TxHash' | 'SkeletonBlock' | 'SkeletonBlockHashToNumber' | 'SkeletonStatus' | 'SkeletonUnfinalizedBlockByHash' | 'Preimage' ``` ## @tevm/rlp API Reference ZEVM-backed Recursive Length Prefix encoding utilities through Tevm's package namespace. Full API on GitHub: [packages/rlp/docs/globals.md](https://github.com/evmts/tevm/tree/main/packages/rlp/docs/globals.md). * [Type Aliases](https://github.com/evmts/tevm/tree/main/packages/rlp/docs/type-aliases) * [Classes](https://github.com/evmts/tevm/tree/main/packages/rlp/docs/classes) * [Functions](https://github.com/evmts/tevm/tree/main/packages/rlp/docs/functions) * [Variables](https://github.com/evmts/tevm/tree/main/packages/rlp/docs/variables) ## @tevm/state State management for Tevm. Handles account state (balance, nonce, code, storage), state transitions/checkpoints, caching, persistence, and forked chain state. ### Installation ```bash npm install @tevm/state@1.0.0-rc.151 viem ``` ### API Reference #### Enumerations * [CacheType](https://github.com/evmts/tevm/tree/main/packages/state/docs/enumerations/CacheType.md) #### State Management * [StateManager](https://github.com/evmts/tevm/tree/main/packages/state/docs/interfaces/StateManager.md) * [BaseState](https://github.com/evmts/tevm/tree/main/packages/state/docs/type-aliases/BaseState.md) * [TevmState](https://github.com/evmts/tevm/tree/main/packages/state/docs/type-aliases/TevmState.md) * [StateAction](https://github.com/evmts/tevm/tree/main/packages/state/docs/type-aliases/StateAction.md) * [StateOptions](https://github.com/evmts/tevm/tree/main/packages/state/docs/type-aliases/StateOptions.md) * [StateRoots](https://github.com/evmts/tevm/tree/main/packages/state/docs/type-aliases/StateRoots.md) * [ParameterizedTevmState](https://github.com/evmts/tevm/tree/main/packages/state/docs/type-aliases/ParameterizedTevmState.md) #### Storage Types * [AccountStorage](https://github.com/evmts/tevm/tree/main/packages/state/docs/interfaces/AccountStorage.md) * [ParameterizedAccountStorage](https://github.com/evmts/tevm/tree/main/packages/state/docs/interfaces/ParameterizedAccountStorage.md) * [SerializableTevmState](https://github.com/evmts/tevm/tree/main/packages/state/docs/type-aliases/SerializableTevmState.md) * [ForkOptions](https://github.com/evmts/tevm/tree/main/packages/state/docs/interfaces/ForkOptions.md) #### Caching * [StateCache](https://github.com/evmts/tevm/tree/main/packages/state/docs/type-aliases/StateCache.md) * [AccountCache](https://github.com/evmts/tevm/tree/main/packages/state/docs/classes/AccountCache.md) * [ContractCache](https://github.com/evmts/tevm/tree/main/packages/state/docs/classes/ContractCache.md) * [StorageCache](https://github.com/evmts/tevm/tree/main/packages/state/docs/classes/StorageCache.md) #### State Creation and Management * [createStateManager](https://github.com/evmts/tevm/tree/main/packages/state/docs/functions/createStateManager.md) * [createBaseState](https://github.com/evmts/tevm/tree/main/packages/state/docs/functions/createBaseState.md) * [deepCopy](https://github.com/evmts/tevm/tree/main/packages/state/docs/functions/deepCopy.md) * [shallowCopy](https://github.com/evmts/tevm/tree/main/packages/state/docs/functions/shallowCopy.md) #### State Operations * [getAccount](https://github.com/evmts/tevm/tree/main/packages/state/docs/functions/getAccount.md) * [putAccount](https://github.com/evmts/tevm/tree/main/packages/state/docs/functions/putAccount.md) * [deleteAccount](https://github.com/evmts/tevm/tree/main/packages/state/docs/functions/deleteAccount.md) * `getCode` ([getContractCode](https://github.com/evmts/tevm/tree/main/packages/state/docs/functions/getContractCode.md)) * `putCode` ([putContractCode](https://github.com/evmts/tevm/tree/main/packages/state/docs/functions/putContractCode.md)) * `getStorage` ([getContractStorage](https://github.com/evmts/tevm/tree/main/packages/state/docs/functions/getContractStorage.md)) * `putStorage` ([putContractStorage](https://github.com/evmts/tevm/tree/main/packages/state/docs/functions/putContractStorage.md)) * `clearStorage` * [getAccountAddresses](https://github.com/evmts/tevm/tree/main/packages/state/docs/functions/getAccountAddresses.md) * [getAppliedKey](https://github.com/evmts/tevm/tree/main/packages/state/docs/functions/getAppliedKey.md) * [modifyAccountFields](https://github.com/evmts/tevm/tree/main/packages/state/docs/functions/modifyAccountFields.md) #### State Root Management * [getStateRoot](https://github.com/evmts/tevm/tree/main/packages/state/docs/functions/getStateRoot.md) * [setStateRoot](https://github.com/evmts/tevm/tree/main/packages/state/docs/functions/setStateRoot.md) * [hasStateRoot](https://github.com/evmts/tevm/tree/main/packages/state/docs/functions/hasStateRoot.md) #### Checkpointing * [checkpoint](https://github.com/evmts/tevm/tree/main/packages/state/docs/functions/checkpoint.md) * [commit](https://github.com/evmts/tevm/tree/main/packages/state/docs/functions/commit.md) * [revert](https://github.com/evmts/tevm/tree/main/packages/state/docs/functions/revert.md) #### Cache Management * [clearCaches](https://github.com/evmts/tevm/tree/main/packages/state/docs/functions/clearCaches.md) * [originalStorageCache](https://github.com/evmts/tevm/tree/main/packages/state/docs/functions/originalStorageCache.md) #### Genesis and Forking * [dumpCanonicalGenesis](https://github.com/evmts/tevm/tree/main/packages/state/docs/functions/dumpCanonicalGenesis.md) * [generateCanonicalGenesis](https://github.com/evmts/tevm/tree/main/packages/state/docs/functions/generateCanonicalGenesis.md) * [getForkBlockTag](https://github.com/evmts/tevm/tree/main/packages/state/docs/functions/getForkBlockTag.md) * [getForkClient](https://github.com/evmts/tevm/tree/main/packages/state/docs/functions/getForkClient.md) #### Storage Operations * [dumpStorage](https://github.com/evmts/tevm/tree/main/packages/state/docs/functions/dumpStorage.md) * [dumpStorageRange](https://github.com/evmts/tevm/tree/main/packages/state/docs/functions/dumpStorageRange.md) * [getProof](https://github.com/evmts/tevm/tree/main/packages/state/docs/functions/getProof.md) `getProof` requires fork mode because local state managers do not merkleize state. ### Usage Examples ```ts import { createAddress } from 'tevm/address' import { createStateManager } from 'tevm/state' import { createAccount, hexToBytes } from 'tevm/utils' const stateManager = createStateManager({ loggingLevel: 'info' }) await stateManager.ready() const address = createAddress('0x1234567890123456789012345678901234567890') await stateManager.putAccount(address, createAccount({ nonce: 0n, balance: 100n })) await stateManager.modifyAccountFields(address, { nonce: 1n, balance: 200n }) const account = await stateManager.getAccount(address) const key = hexToBytes('0x0000000000000000000000000000000000000000000000000000000000000001') await stateManager.putCode(address, new Uint8Array([1, 2, 3])) const code = await stateManager.getCode(address) await stateManager.putStorage(address, key, new Uint8Array([2])) const value = await stateManager.getStorage(address, key) await stateManager.clearStorage(address) ``` ## Reusable EVM test fixtures `@tevm/test-utils` packages compiled test contracts and shared fork transports used throughout the Tevm test suite. Reach for it when a test needs deterministic bytecode and ABI fixtures without maintaining another Solidity compilation step. ### Working example This example was run with `@tevm/test-utils@1.0.0-rc.151` and `viem@2.49.3`. ```ts import assert from 'node:assert/strict' import { AdvancedContract, BlockReader, ErrorContract, SimpleContract, TestERC20, TestERC721, transports, } from '@tevm/test-utils' const fixtures = [AdvancedContract, BlockReader, ErrorContract, SimpleContract, TestERC20, TestERC721] for (const fixture of fixtures) { assert.ok(Array.isArray(fixture.abi)) assert.match(fixture.bytecode, /^0x[0-9a-f]+$/i) } assert.equal(typeof transports.optimism, 'object') console.log(`contracts=${fixtures.length}`) console.log(`simpleFunctions=${SimpleContract.abi.filter((item) => item.type === 'function').length}`) console.log(`transports=${Object.keys(transports).sort().join(',')}`) ``` ```text contracts=6 simpleFunctions=2 transports=mainnet,optimism ``` ### Exports The package entry point in [`test/test-utils/src/index.ts`](https://github.com/evmts/tevm/blob/main/test/test-utils/src/index.ts) exposes: | Export | Kind | Purpose | | ------------------ | ----------------- | ------------------------------------------ | | `AdvancedContract` | Compiled contract | Advanced call and state behavior | | `BlockReader` | Compiled contract | Block environment reads | | `ErrorContract` | Compiled contract | Revert and error paths | | `SimpleContract` | Compiled contract | Basic reads and writes | | `TestERC20` | Compiled contract | ERC-20 behavior | | `TestERC721` | Compiled contract | ERC-721 behavior | | `MUDTestSystem` | Compiled contract | MUD integration tests | | `transports` | Object | Shared `mainnet` and `optimism` transports | | `getAlchemyUrl` | Function | Resolve the configured Alchemy endpoint | ### Neighbours [Local testing](/examples/local-testing) · [Memory client](/reference/memory-client) · [Contract reference](/reference/contract) ## @tevm/trie API Reference ZEVM-backed Merkle Patricia Trie utilities through Tevm's package namespace. Full API on GitHub: [packages/trie/docs/globals.md](https://github.com/evmts/tevm/tree/main/packages/trie/docs/globals.md). * [Type Aliases](https://github.com/evmts/tevm/tree/main/packages/trie/docs/type-aliases) * [Classes](https://github.com/evmts/tevm/tree/main/packages/trie/docs/classes) * [Functions](https://github.com/evmts/tevm/tree/main/packages/trie/docs/functions) * [Variables](https://github.com/evmts/tevm/tree/main/packages/trie/docs/variables) ## @tevm/tx Tevm's transaction facade backed by `@evmts/zevm/tx`. Exports typed Ethereum transaction constructors, helpers, type guards, and Tevm's impersonated transaction helper. Full API: [packages/tx/docs](https://github.com/evmts/tevm/tree/main/packages/tx/docs). ### Installation ```bash npm install @tevm/tx@1.0.0-rc.151 viem ``` ### API Reference #### Transaction Types * [LegacyTransaction](https://github.com/evmts/tevm/tree/main/packages/tx/docs/classes/LegacyTransaction.md) * [AccessListEIP2930Transaction](https://github.com/evmts/tevm/tree/main/packages/tx/docs/classes/AccessListEIP2930Transaction.md) * [FeeMarketEIP1559Transaction](https://github.com/evmts/tevm/tree/main/packages/tx/docs/classes/FeeMarketEIP1559Transaction.md) * [BlobEIP4844Transaction](https://github.com/evmts/tevm/tree/main/packages/tx/docs/classes/BlobEIP4844Transaction.md) * `EOACodeEIP7702Transaction` - EIP-7702 EOA code transactions. * [ImpersonatedTx](https://github.com/evmts/tevm/tree/main/packages/tx/docs/interfaces/ImpersonatedTx.md) - Tevm-specific tx that executes as an address without a private key. #### Helpers * `TransactionFactory` - alias for ZEVM's `createTx`. * `createTxFromRLP` - decode a serialized transaction. * `createTxFromBlockBodyData` - create from block body data. * `createImpersonatedTx` - unsigned EIP-1559-shaped tx that executes as `impersonatedAddress`. * `createEOACodeEIP7702Tx`, `createEOACodeEIP7702TxFromBytesArray`, `createEOACodeEIP7702TxFromRLP`. * Type guards: `isLegacyTx`, `isAccessListEIP2930Tx`, `isFeeMarketEIP1559Tx`, `isBlobEIP4844Tx`, `isEOACodeEIP7702Tx`. ### Creating Transactions ```typescript import { TransactionFactory, createImpersonatedTx, createTxFromRLP, isBlobEIP4844Tx, isEOACodeEIP7702Tx, } from '@tevm/tx' import { createAddress } from '@tevm/address' const tx = TransactionFactory({ nonce: 0n, gasLimit: 21000n, maxFeePerGas: 20_000_000_000n, maxPriorityFeePerGas: 2_000_000_000n, to: createAddress('0x1234567890123456789012345678901234567890'), value: 1_000_000_000_000_000_000n, }) const decoded = createTxFromRLP(tx.serialize()) if (isBlobEIP4844Tx(decoded) || isEOACodeEIP7702Tx(decoded)) { // typed transaction fields } ``` ### Impersonated Transactions Lets the VM execute as an address without a signature. For app-level impersonation, prefer JSON-RPC or MemoryClient helpers (`anvil_impersonateAccount`, `tevm_impersonateAccount`, `setImpersonatedAccount`). ```typescript import { createImpersonatedTx } from '@tevm/tx' import { createAddress } from '@tevm/address' const tx = createImpersonatedTx({ impersonatedAddress: createAddress('0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266'), to: createAddress('0x70997970c51812dc3a010c7d01b50e0d17dc79c8'), value: 1_000_000_000_000_000_000n, gasLimit: 21_000n, maxFeePerGas: 20_000_000_000n, maxPriorityFeePerGas: 2_000_000_000n, nonce: 0n, }) const vm = await node.getVm() const result = await vm.runTx({ tx, skipBalance: true, skipNonce: true }) ``` ### Transaction Coverage Legacy, EIP-2930, EIP-1559, EIP-4844, EIP-7702, and Tevm impersonated transactions. ### Common Methods `hash()`, `getBaseFee()`, `getDataFee()`, `getUpfrontCost()`, `isSigned()`, `serialize()`, `toJSON()`. ### See Also * [Transaction Pool](../advanced/txpool) * [VM & Submodules](../api/vm-and-submodules) * [EIP-2718](https://eips.ethereum.org/EIPS/eip-2718), [EIP-2930](https://eips.ethereum.org/EIPS/eip-2930), [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559), [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844), [EIP-7702](https://eips.ethereum.org/EIPS/eip-7702) ## @tevm/txpool Transaction pool facade backed by `@evmts/zevm/txpool`. Adds Tevm-specific fee classification for fee-market-shaped transactions, including EIP-7702 and impersonated transactions. Normally managed by `TevmNode`, `MemoryClient`, and the JSON-RPC layer. Use directly when building custom VM tooling or low-level pending-tx control. ### Installation ```bash npm install @tevm/txpool@1.0.0-rc.151 viem ``` ### API #### TxPool [`TxPool`](https://github.com/evmts/tevm/blob/main/packages/txpool/src/TxPool.ts) extends the ZEVM txpool. ```ts import { TxPool, type TxPoolOptions } from '@tevm/txpool' const txPool = new TxPool({ vm, maxSize: 5000, maxPerSender: 100, } satisfies TxPoolOptions) ``` #### Options ```ts type TxPoolOptions = { vm: TxPoolVm maxSize?: number maxPerSender?: number } ``` * `vm` - VM facade with `blockchain`, `stateManager`, and `deepCopy()`. * `maxSize` - max transactions in the pool. * `maxPerSender` - max transactions per sender. #### Methods * `open()` / `close()` - open or clear the pool. * `start()` / `stop()` - background cleanup. * `add(tx, requireSignature?, skipBalance?)` - validate and add. * `addUnverified(tx)` - add without validation. * `getByHash(hashOrHashes)` - look up by hex hash, or many by byte hashes. * `removeByHash(hash)` - remove from all indexes. * `txsByPriceAndNonce({ baseFee, allowedBlobs })` - ordered for block building. * `cleanup()` - drop stale txs and sync indexes. * `deepCopy(options)` - copy with another VM/options. ### JSON-RPC Exposed via: * `txpool_content` * `txpool_contentFrom` * `txpool_inspect` * `txpool_status` Dev methods (`anvil_impersonateAccount`, `tevm_impersonateAccount`, `evm_mine`) interact with the same pending state. ### Transaction Support Legacy, EIP-2930, EIP-1559, EIP-4844, EIP-7702, and Tevm impersonated EIP-1559-shaped transactions. ### Related Packages * [@tevm/vm](./vm) - VM execution facade * [@tevm/tx](./tx) - transaction constructors and helpers * [@tevm/common](./common) - chain and hardfork configuration * [JSON-RPC](../api/json-rpc) ## Utilities & Addresses Lightweight utility functions and classes built on [`tevm/utils`](https://github.com/evmts/tevm/tree/main/packages/utils), [`@evmts/zevm`](https://github.com/evmts/zevm), and [`viem`](https://viem.sh). ### createAddress Create an Ethereum address from various inputs. ```ts import { createAddress } from 'tevm/address' createAddress(`0x${'00'.repeat(20)}`) createAddress(420n) createAddress(new Uint8Array(20)) ``` #### Signature ```ts declare function createAddress( address: number | bigint | string | Uint8Array | EthjsAddress ): Address ``` Accepts `0x`-prefixed hex, unprefixed hex, numbers, bigints, `Uint8Array`s, or `EthjsAddress`. Throws `InvalidAddressError` on invalid input. ### Address Class Thin wrapper around `EthjsAddress`. ```ts import { Address } from 'tevm/address' const a = new Address(Uint8Array.from([ /* 20 bytes */ ])) a.bytes // raw 20-byte address a.toString() // '0x...' ``` ### createContractAddress CREATE address per [EIP-1014](https://eips.ethereum.org/EIPS/eip-1014): ```ts import { createContractAddress } from 'tevm/address' const contractAddr = createContractAddress(createAddress('0x1111...1111'), 1n) ``` Computes `keccak256(rlp([senderAddress, nonce]))[-20..]`. Throws `InvalidAddressError` if `from` is invalid. ### Common Errors * `InvalidAddressError` - bytes/string can't parse as a 20-byte address. * `UnreachableCodeError` - unexpected code path; usually wrapped into a more descriptive error. ### Other Re-exports Lower-level helpers from [`tevm/utils`](https://github.com/evmts/tevm/tree/main/packages/utils), ZEVM, or [`viem`](https://viem.sh): * `hexToBytes(hex)` - hex to raw bytes (with optional size checks). * `keccak256(data, 'bytes' | 'hex')` - keccak256 hasher. * `encodeFunctionData(...)`, `toRlp(...)` - ABI/RLP encoders. * EIP-7702 helpers: `eoaCode7702SignAuthorization`, `eoaCode7702RecoverAuthority`, and authorization-list encoders. :::tip Prefer [`viem`](https://viem.sh) utilities for bytes conversion, hashing, and ABIs in browser/Node code. Tevm re-exports many for convenience. ::: ## @tevm/utils Full API: [packages/utils/docs](https://github.com/evmts/tevm/tree/main/packages/utils/docs). Combines ZEVM primitives, viem utilities, and Tevm helpers. ### Installation ```bash npm install @tevm/utils@1.0.0-rc.151 viem ``` ### Main Components #### Hex and Bytes Conversion ```typescript import { bytesToHex, hexToBytes, bytesToBigInt, bytesToNumber, hexToBigInt, hexToNumber, numberToHex, stringToHex, hexToString, } from '@tevm/utils' bytesToHex(new Uint8Array([1, 164])) // '0x01a4' hexToBytes('0x01a4') // Uint8Array([1, 164]) hexToNumber('0x01a4') // 420 numberToHex(420) // '0x1a4' hexToString('0x48656c6c6f') // 'Hello' stringToHex('Hello') // '0x48656c6c6f' ``` #### Type Checking ```typescript import { isHex, isBytes, isAddress } from '@tevm/utils' isHex('0x123') isBytes(new Uint8Array()) isAddress('0x123...') ``` #### Unit Conversion ```typescript import { formatEther, parseEther, formatGwei, parseGwei } from '@tevm/utils' formatEther(1000000000000000000n) // '1' parseEther('1.0') // 1000000000000000000n formatGwei(1000000000n) // '1' parseGwei('1.0') // 1000000000n ``` #### Cryptography ```typescript import { keccak256, ecrecover, randomBytes } from '@tevm/utils' const hash = keccak256('0x1234') const address = ecrecover(messageHash, v, r, s) const random = randomBytes(32) ``` #### ABI Encoding/Decoding ```typescript import { parseAbi, encodeFunctionData, decodeFunctionData, encodeEventTopics, } from '@tevm/utils' const abi = parseAbi([ 'function transfer(address to, uint256 amount) returns (bool)', 'event Transfer(address indexed from, address indexed to, uint256 amount)', ]) const from = '0x1111111111111111111111111111111111111111' const to = '0x2222222222222222222222222222222222222222' const data = encodeFunctionData({ abi, functionName: 'transfer', args: [to, 1n], }) const decoded = decodeFunctionData({ abi, data }) const topics = encodeEventTopics({ abi, eventName: 'Transfer', args: { from, to }, }) ``` #### RLP ```typescript import { toRlp, fromRlp } from '@tevm/utils' const rlp = toRlp(['0x123', '0x456']) const decoded = fromRlp(rlp) ``` #### Memory Database ```typescript import { createMemoryDb } from '@tevm/utils' const db = createMemoryDb() const db2 = createMemoryDb(new Map()) ``` ### Types #### Basic ```typescript import type { Address, Hex, BlockTag, BlockNumber, BytesLike, BigIntLike } from '@tevm/utils' const address: Address = '0x...' const hex: Hex = '0x...' const blockTag: BlockTag = 'latest' ``` #### ABI ```typescript import type { Abi, AbiFunction, AbiEvent, AbiConstructor, ParseAbi, FormatAbi } from '@tevm/utils' type ParsedAbi = ParseAbi type FormattedAbi = FormatAbi ``` #### Contract ```typescript import type { ContractFunctionName, ContractConstructorArgs, ExtractAbiFunction, ExtractAbiEvent, } from '@tevm/utils' type TransferFunction = ExtractAbiFunction type TransferEvent = ExtractAbiEvent ``` ### Constants ```typescript import { GWEI_TO_WEI, KECCAK256_RLP, KECCAK256_RLP_ARRAY } from '@tevm/utils' GWEI_TO_WEI // 1000000000n ``` ### Error Handling ```typescript import { invariant } from '@tevm/utils' invariant(condition, new Error('Error message')) ``` ### See Also * [Viem](https://viem.sh/docs/utilities/fromBytes) * [ZEVM](https://github.com/evmts/zevm) * [ABI Specification](https://docs.soliditylang.org/en/latest/abi-spec.html) ## Virtual Machine `@tevm/vm` coordinates the EVM, state manager, blockchain, block building, and transaction execution. Most applications should use `createMemoryClient`; direct VM access is intended for runtime integrations. ### Access the Configured VM ```ts import { createTevmNode } from 'tevm' import { createAddress } from 'tevm/address' import { createImpersonatedTx } from 'tevm/tx' const node = createTevmNode() const vm = await node.getVm() const tx = createImpersonatedTx({ impersonatedAddress: createAddress( '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', ), to: createAddress('0x1111111111111111111111111111111111111111'), value: 1n, gasLimit: 21_000n, maxFeePerGas: 10n, maxPriorityFeePerGas: 1n, }) const result = await vm.runTx({ tx }) console.log(result.totalGasSpent, result.execResult.returnValue) ``` The node constructs compatible `common`, `stateManager`, `blockchain`, `evm`, txpool, and receipt components. Prefer this over assembling a partial VM unless you are implementing a custom runtime. ### Important VM Methods * `runTx` executes a typed transaction. * `runBlock` executes and validates a block. * `buildBlock` creates a block builder. * `deepCopy` creates an isolated runtime copy. * `stateManager`, `blockchain`, and `evm` expose the configured subcomponents. Direct execution follows checkpoint and hardfork rules. For simulations with Tevm error handling, tracing, overrides, and ABI decoding, use `client.tevmCall` or `client.tevmContract`. ### Related [TevmNode Interface](../core/tevm-node-interface) · [EVM](./evm) · [State](./state) · [Blockchain](./blockchain) ## tevm call `tevm call` runs this operation: Execute a raw EVM call against a contract or address. Reach for it when you need the operation from a terminal, CI job, or shell script. ### Working example The commands below were run with `@tevm/cli@1.0.0-rc.151`. They create their own local prerequisites or use the named public endpoint, so no hidden process is required. ```bash npm install --global @tevm/cli@1.0.0-rc.151 tevm session docs --local --json mkdir -p src cat > src/Counter.sol <<'SOLIDITY' // SPDX-License-Identifier: MIT pragma solidity ^0.8.20; contract Counter { uint256 public number; event NumberChanged(uint256 number); function setNumber(uint256 next) public { number = next; emit NumberChanged(next); } } SOLIDITY tevm compile --json jq '.abi' artifacts/Counter.json > artifacts/Counter.abi.json tevm set-account --address 0x1000000000000000000000000000000000000001 --balance 1000000000000000000 --session docs --run --json tevm set-code --address 0x1000000000000000000000000000000000000001 --bytecode "$(jq -r '.deployedBytecode' artifacts/Counter.json)" --session docs --run --json tevm set-storage-at --address 0x1000000000000000000000000000000000000001 --index 0x0 --value 0x2a --session docs --run --json tevm call --to 0x1000000000000000000000000000000000000001 --data 0x8381f58a --session docs --run --json ``` Output captured from the final command: ```json { "ok": true, "command": "call", "result": { "rawData": "0x000000000000000000000000000000000000000000000000000000000000002a", "executionGasUsed": "2281", "totalGasSpent": "23345", "amountSpent": "163415", "selfdestruct": [], "gas": "29976655", "logs": [], "createdAddresses": [] }, "session": "docs" } ``` ### Arguments and flags The command schema in [`cli/src/commands/call.tsx`](https://github.com/evmts/tevm/blob/main/cli/src/commands/call.tsx) exposes: | Kind | Syntax | Description | | ---- | ----------------------------------------- | ------------------------------------------------------------------------------------------------------------ | | Flag | `--to [to]` | Contract address to call (env: TEVM\_TO) (default: 0x0000000000000000000000000000000000000000) | | Flag | `--data [data]` | Transaction data (hex encoded) (env: TEVM\_DATA) | | Flag | `--from [from]` | Address to send the transaction from (env: TEVM\_FROM) (default: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266) | | Flag | `--value [value]` | ETH value to send in wei (env: TEVM\_VALUE) | | Flag | `--code [code]` | The encoded code to deploy (with constructor args) (env: TEVM\_CODE) | | Flag | `--deployed-bytecode [deployed-bytecode]` | Deployed bytecode to put in state before call (env: TEVM\_DEPLOYED\_BYTECODE) | | Flag | `--gas [gas]` | Gas limit for the transaction (env: TEVM\_GAS) | | Flag | `--gas-price [gas-price]` | Gas price in wei (env: TEVM\_GAS\_PRICE) | | Flag | `--block-tag [block-tag]` | Block tag (latest, pending, etc.) or number (env: TEVM\_BLOCK\_TAG) | | Flag | `--trace` | Render a readable call tree with gas per frame (env: TEVM\_TRACE) (default: false) | | Flag | `--abi [abi]` | ABI JSON or file used to decode traced calls (env: TEVM\_ABI) | | Flag | `-r, --run` | Run directly without interactive parameter editing (env: TEVM\_RUN) (default: false) | | Flag | `--rpc [rpc]` | RPC endpoint (env: TEVM\_RPC) (default: [http://localhost:8545](http://localhost:8545)) | | Flag | `--json` | Emit the stable machine-readable JSON envelope (env: TEVM\_JSON) (default: false) | | Flag | `--session [session]` | Load and persist a named local fork session (env: TEVM\_SESSION) | | Flag | `-h, --help` | Show help | `--json` and `--session ` are global options accepted before routing. See the [CLI overview](/reference/cli#global-options) for their environment-variable forms and execution model. ### Neighbours [CLI overview](/reference/cli) · [`tevm compile`](/reference/cli/compile) ## tevm compile `tevm compile` runs this operation: Compile Solidity smart contracts to bytecode and ABI. Reach for it when you need the operation from a terminal, CI job, or shell script. ### Working example The commands below were run with `@tevm/cli@1.0.0-rc.151`. They create their own local prerequisites or use the named public endpoint, so no hidden process is required. ```bash npm install --global @tevm/cli@1.0.0-rc.151 mkdir -p src cat > src/Counter.sol <<'SOLIDITY' // SPDX-License-Identifier: MIT pragma solidity ^0.8.20; contract Counter { uint256 public number; } SOLIDITY tevm compile --json ``` Output captured from the final command: ```json { "ok": true, "command": "compile", "result": { "artifacts": [ "artifacts/Counter.json" ] } } ``` ### Arguments and flags The command schema in [`cli/src/commands/compile.tsx`](https://github.com/evmts/tevm/blob/main/cli/src/commands/compile.tsx) exposes: | Kind | Syntax | Description | | ---- | ------------------- | --------------------------------------------------------------------------- | | Flag | `-w, --watch` | Watch for changes (default: false) | | Flag | `--no-optimize` | Enable optimizations | | Flag | `--target [target]` | Compilation target (choices: "es2015", "es2020", "esnext", default: es2020) | | Flag | `-h, --help` | Show help | `--json` and `--session ` are global options accepted before routing. See the [CLI overview](/reference/cli#global-options) for their environment-variable forms and execution model. ### Neighbours [CLI overview](/reference/cli) · [`tevm call`](/reference/cli/call) · [`tevm contract`](/reference/cli/contract) ## tevm contract `tevm contract` runs this operation: Call a contract function with ABI and arguments. Reach for it when you need the operation from a terminal, CI job, or shell script. ### Working example The commands below were run with `@tevm/cli@1.0.0-rc.151`. They create their own local prerequisites or use the named public endpoint, so no hidden process is required. ```bash npm install --global @tevm/cli@1.0.0-rc.151 tevm session docs --local --json mkdir -p src cat > src/Counter.sol <<'SOLIDITY' // SPDX-License-Identifier: MIT pragma solidity ^0.8.20; contract Counter { uint256 public number; event NumberChanged(uint256 number); function setNumber(uint256 next) public { number = next; emit NumberChanged(next); } } SOLIDITY tevm compile --json jq '.abi' artifacts/Counter.json > artifacts/Counter.abi.json tevm set-account --address 0x1000000000000000000000000000000000000001 --balance 1000000000000000000 --session docs --run --json tevm set-code --address 0x1000000000000000000000000000000000000001 --bytecode "$(jq -r '.deployedBytecode' artifacts/Counter.json)" --session docs --run --json tevm set-storage-at --address 0x1000000000000000000000000000000000000001 --index 0x0 --value 0x2a --session docs --run --json tevm contract --to 0x1000000000000000000000000000000000000001 --abi artifacts/Counter.abi.json --function-name number --session docs --run --json ``` Output captured from the final command: ```json { "ok": true, "command": "contract", "result": { "rawData": "0x000000000000000000000000000000000000000000000000000000000000002a", "executionGasUsed": "2281", "totalGasSpent": "23345", "minerValue": "23345000000000", "amountSpent": "23345000163415", "selfdestruct": [], "gas": "29976655", "logs": [], "createdAddresses": [], "data": "42" }, "session": "docs" } ``` ### Arguments and flags The command schema in [`cli/src/commands/contract.tsx`](https://github.com/evmts/tevm/blob/main/cli/src/commands/contract.tsx) exposes: | Kind | Syntax | Description | | ---- | ------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | | Flag | `--to [to]` | Contract address to call (env: TEVM\_TO) | | Flag | `-r, --run` | Run directly without interactive parameter editing (env: TEVM\_RUN) (default: false) | | Flag | `--rpc [rpc]` | RPC endpoint (env: TEVM\_RPC) (default: [http://localhost:8545](http://localhost:8545)) | | Flag | `--abi ` | Contract ABI (JSON string or path to file) (env: TEVM\_ABI) | | Flag | `--function-name ` | Function name to call (env: TEVM\_FUNCTION\_NAME) | | Flag | `--args [args]` | Arguments for the function call (JSON string array) (env: TEVM\_ARGS) | | Flag | `--from [from]` | Address to send the transaction from (env: TEVM\_FROM) (default: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266) | | Flag | `--value [value]` | ETH value to send in wei (env: TEVM\_VALUE) | | Flag | `--deployed-bytecode [deployed-bytecode]` | Deployed bytecode to put in state before call (env: TEVM\_DEPLOYED\_BYTECODE) | | Flag | `--code [code]` | Alias for deployedBytecode (env: TEVM\_CODE) | | Flag | `--gas [gas]` | Gas limit for the transaction (env: TEVM\_GAS) | | Flag | `--gas-price [gas-price]` | Gas price in wei (env: TEVM\_GAS\_PRICE) | | Flag | `--max-fee-per-gas [max-fee-per-gas]` | Maximum fee per gas (EIP-1559) (env: TEVM\_MAX\_FEE\_PER\_GAS) | | Flag | `--max-priority-fee-per-gas [max-priority-fee-per-gas]` | Maximum priority fee per gas (EIP-1559) (env: TEVM\_MAX\_PRIORITY\_FEE\_PER\_GAS) | | Flag | `--gas-refund [gas-refund]` | Gas refund counter (env: TEVM\_GAS\_REFUND) | | Flag | `--block-tag [block-tag]` | Block tag (latest, pending, etc.) or number (env: TEVM\_BLOCK\_TAG) | | Flag | `--caller [caller]` | Address that ran this code (msg.sender) (env: TEVM\_CALLER) | | Flag | `--origin [origin]` | Address where the call originated from (env: TEVM\_ORIGIN) | | Flag | `--depth [depth]` | Depth of EVM call stack (env: TEVM\_DEPTH) | | Flag | `--skip-balance` | Skip balance check (env: TEVM\_SKIP\_BALANCE) (default: false) | | Flag | `--create-trace` | Return a complete trace with the call (env: TEVM\_CREATE\_TRACE) (default: false) | | Flag | `--create-access-list` | Return an access list mapping of addresses to storage keys (env: TEVM\_CREATE\_ACCESS\_LIST) (default: false) | | Flag | `--create-transaction [create-transaction]` | Whether to update state (on-success, always, never) (env: TEVM\_CREATE\_TRANSACTION) (choices: "on-success", "always", "never", default: "never") | | Flag | `--json` | Emit the stable machine-readable JSON envelope (env: TEVM\_JSON) (default: false) | | Flag | `-h, --help` | Show help | `--json` and `--session ` are global options accepted before routing. See the [CLI overview](/reference/cli#global-options) for their environment-variable forms and execution model. ### Neighbours [CLI overview](/reference/cli) · [`tevm compile`](/reference/cli/compile) · [`tevm action create-access-list`](/reference/cli/create-access-list) ## tevm action create-access-list `tevm action create-access-list` runs this operation: Create an EIP-2930 access list. Reach for it when you need the operation from a terminal, CI job, or shell script. ### Working example The commands below were run with `@tevm/cli@1.0.0-rc.151`. They create their own local prerequisites or use the named public endpoint, so no hidden process is required. ```bash npm install --global @tevm/cli@1.0.0-rc.151 tevm session docs --local --json tevm action create-access-list --account 0x1000000000000000000000000000000000000001 --to 0x1000000000000000000000000000000000000001 --data 0x8381f58a --session docs --run --json ``` Output captured from the final command: ```json { "ok": true, "command": "create-access-list", "result": { "accessList": [ { "address": "0x1000000000000000000000000000000000000001", "storageKeys": [ "0x0000000000000000000000000000000000000000000000000000000000000000" ] } ], "gasUsed": "23345" }, "session": "docs" } ``` ### Arguments and flags The command schema in [`cli/src/commands/action/createAccessList.tsx`](https://github.com/evmts/tevm/blob/main/cli/src/commands/action/createAccessList.tsx) exposes: | Kind | Syntax | Description | | ---- | ------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | | Flag | `--account [account]` | Account (address) to create an access list for (env: TEVM\_ACCOUNT) | | Flag | `--block-number [block-number]` | Block number to create an access list for (env: TEVM\_BLOCK\_NUMBER) | | Flag | `--block-tag [block-tag]` | Block tag to create an access list for (env: TEVM\_BLOCK\_TAG) | | Flag | `--data [data]` | Contract function selector with encoded arguments (env: TEVM\_DATA) | | Flag | `--gas-price [gas-price]` | Price (in wei) to pay per gas (for Legacy Transactions) (env: TEVM\_GAS\_PRICE) | | Flag | `--max-fee-per-gas [max-fee-per-gas]` | Max fee per gas in wei (for EIP-1559 Transactions) (env: TEVM\_MAX\_FEE\_PER\_GAS) | | Flag | `--max-priority-fee-per-gas [max-priority-fee-per-gas]` | Max priority fee per gas in wei (for EIP-1559 Transactions) (env: TEVM\_MAX\_PRIORITY\_FEE\_PER\_GAS) | | Flag | `--to [to]` | Transaction recipient address (env: TEVM\_TO) | | Flag | `--value [value]` | Value (in wei) sent with this transaction (env: TEVM\_VALUE) | | Flag | `-r, --run` | Run directly without interactive parameter editing (env: TEVM\_RUN) (default: false) | | Flag | `--rpc [rpc]` | RPC endpoint (env: TEVM\_RPC) | | Flag | `--json` | Emit the stable machine-readable JSON envelope (env: TEVM\_JSON) (default: false) | | Flag | `-h, --help` | Show help | `--json` and `--session ` are global options accepted before routing. See the [CLI overview](/reference/cli#global-options) for their environment-variable forms and execution model. ### Neighbours [CLI overview](/reference/cli) · [`tevm contract`](/reference/cli/contract) · [`tevm create-block-filter`](/reference/cli/create-block-filter) ## tevm create-block-filter `tevm create-block-filter` runs this operation: Create a filter to detect new blocks. Reach for it when you need the operation from a terminal, CI job, or shell script. ### Working example The commands below were run with `@tevm/cli@1.0.0-rc.151`. They create their own local prerequisites or use the named public endpoint, so no hidden process is required. ```bash npm install --global @tevm/cli@1.0.0-rc.151 tevm session docs --local --json tevm create-block-filter --session docs --run --json ``` Output captured from the final command: ```json { "ok": true, "command": "create-block-filter", "result": { "id": "0xa4a682eddb4322c80d9ee2c77074edf2", "type": "block" }, "session": "docs" } ``` ### Arguments and flags The command schema in [`cli/src/commands/createBlockFilter.tsx`](https://github.com/evmts/tevm/blob/main/cli/src/commands/createBlockFilter.tsx) exposes: | Kind | Syntax | Description | | ---- | ------------- | ------------------------------------------------------------------------------------ | | Flag | `-r, --run` | Run directly without interactive parameter editing (env: TEVM\_RUN) (default: false) | | Flag | `--rpc [rpc]` | RPC endpoint (env: TEVM\_RPC) | | Flag | `--json` | Emit the stable machine-readable JSON envelope (env: TEVM\_JSON) (default: false) | | Flag | `-h, --help` | Show help | `--json` and `--session ` are global options accepted before routing. See the [CLI overview](/reference/cli#global-options) for their environment-variable forms and execution model. ### Neighbours [CLI overview](/reference/cli) · [`tevm action create-access-list`](/reference/cli/create-access-list) · [`tevm create-contract-event-filter`](/reference/cli/create-contract-event-filter) ## tevm create-contract-event-filter `tevm create-contract-event-filter` runs this operation: Create a filter for decoded contract events. Reach for it when you need the operation from a terminal, CI job, or shell script. ### Working example The commands below were run with `@tevm/cli@1.0.0-rc.151`. They create their own local prerequisites or use the named public endpoint, so no hidden process is required. ```bash npm install --global @tevm/cli@1.0.0-rc.151 tevm session docs --local --json mkdir -p src cat > src/Counter.sol <<'SOLIDITY' // SPDX-License-Identifier: MIT pragma solidity ^0.8.20; contract Counter { uint256 public number; event NumberChanged(uint256 number); function setNumber(uint256 next) public { number = next; emit NumberChanged(next); } } SOLIDITY tevm compile --json jq '.abi' artifacts/Counter.json > artifacts/Counter.abi.json tevm set-account --address 0x1000000000000000000000000000000000000001 --balance 1000000000000000000 --session docs --run --json tevm set-code --address 0x1000000000000000000000000000000000000001 --bytecode "$(jq -r '.deployedBytecode' artifacts/Counter.json)" --session docs --run --json tevm set-storage-at --address 0x1000000000000000000000000000000000000001 --index 0x0 --value 0x2a --session docs --run --json tevm create-contract-event-filter --address 0x1000000000000000000000000000000000000001 --abi artifacts/Counter.abi.json --event-name NumberChanged --session docs --run --json ``` Output captured from the final command: ```json { "ok": true, "command": "create-contract-event-filter", "result": { "abi": [ { "anonymous": false, "inputs": [ { "indexed": false, "internalType": "uint256", "name": "number", "type": "uint256" } ], "name": "NumberChanged", "type": "event" }, { "inputs": [], "name": "number", "outputs": [ { "internalType": "uint256", "name": "", "type": "uint256" } ], "stateMutability": "view", "type": "function" }, { "inputs": [ { "internalType": "uint256", "name": "next", "type": "uint256" } ], "name": "setNumber", "outputs": [], "stateMutability": "nonpayable", "type": "function" } ], "args": [], "eventName": "NumberChanged", "id": "0xd84a7ad846377eacefca04e3dae1a140", "strict": false, "type": "event" }, "session": "docs" } ``` ### Arguments and flags The command schema in [`cli/src/commands/createContractEventFilter.tsx`](https://github.com/evmts/tevm/blob/main/cli/src/commands/createContractEventFilter.tsx) exposes: | Kind | Syntax | Description | | ---- | --------------------------- | ------------------------------------------------------------------------------------ | | Flag | `--abi [abi]` | Contract ABI as JSON string (env: TEVM\_ABI) | | Flag | `--address [address]` | Contract address to filter events from (env: TEVM\_ADDRESS) | | Flag | `--event-name [event-name]` | Name of the event to filter (env: TEVM\_EVENT\_NAME) | | Flag | `--args [args]` | Event arguments as JSON array (env: TEVM\_ARGS) | | Flag | `--from-block [from-block]` | Starting block for filtering (env: TEVM\_FROM\_BLOCK) | | Flag | `--to-block [to-block]` | Ending block for filtering (env: TEVM\_TO\_BLOCK) | | Flag | `-r, --run` | Run directly without interactive parameter editing (env: TEVM\_RUN) (default: false) | | Flag | `--rpc [rpc]` | RPC endpoint (env: TEVM\_RPC) | | Flag | `--json` | Emit the stable machine-readable JSON envelope (env: TEVM\_JSON) (default: false) | | Flag | `-h, --help` | Show help | `--json` and `--session ` are global options accepted before routing. See the [CLI overview](/reference/cli#global-options) for their environment-variable forms and execution model. ### Neighbours [CLI overview](/reference/cli) · [`tevm create-block-filter`](/reference/cli/create-block-filter) · [`tevm create-event-filter`](/reference/cli/create-event-filter) ## tevm create-event-filter `tevm create-event-filter` runs this operation: Create a filter for blockchain logs. Reach for it when you need the operation from a terminal, CI job, or shell script. ### Working example The commands below were run with `@tevm/cli@1.0.0-rc.151`. They create their own local prerequisites or use the named public endpoint, so no hidden process is required. ```bash npm install --global @tevm/cli@1.0.0-rc.151 tevm session docs --local --json tevm create-event-filter --address 0x1000000000000000000000000000000000000001 --session docs --run --json ``` Output captured from the final command: ```json { "ok": true, "command": "create-event-filter", "result": { "args": [], "fromBlock": "latest", "id": "0x820e7fce9eda5f36295160d43860bb2a", "strict": false, "toBlock": "latest", "type": "event" }, "session": "docs" } ``` ### Arguments and flags The command schema in [`cli/src/commands/createEventFilter.tsx`](https://github.com/evmts/tevm/blob/main/cli/src/commands/createEventFilter.tsx) exposes: | Kind | Syntax | Description | | ---- | --------------------------- | ------------------------------------------------------------------------------------ | | Flag | `--address [address]` | Contract address to filter events from (env: TEVM\_ADDRESS) | | Flag | `--abi [abi]` | Contract ABI as JSON string (env: TEVM\_ABI) | | Flag | `--event-name [event-name]` | Name of the event to filter (env: TEVM\_EVENT\_NAME) | | Flag | `--args [args]` | Event arguments as JSON array (env: TEVM\_ARGS) | | Flag | `--from-block [from-block]` | Starting block for filtering (env: TEVM\_FROM\_BLOCK) | | Flag | `--to-block [to-block]` | Ending block for filtering (env: TEVM\_TO\_BLOCK) | | Flag | `-r, --run` | Run directly without interactive parameter editing (env: TEVM\_RUN) (default: false) | | Flag | `--rpc [rpc]` | RPC endpoint (env: TEVM\_RPC) | | Flag | `--json` | Emit the stable machine-readable JSON envelope (env: TEVM\_JSON) (default: false) | | Flag | `-h, --help` | Show help | `--json` and `--session ` are global options accepted before routing. See the [CLI overview](/reference/cli#global-options) for their environment-variable forms and execution model. ### Neighbours [CLI overview](/reference/cli) · [`tevm create-contract-event-filter`](/reference/cli/create-contract-event-filter) · [`tevm deploy`](/reference/cli/deploy) ## tevm deploy `tevm deploy` runs this operation: Deploy bytecode into a local EVM or fork. Reach for it when you need the operation from a terminal, CI job, or shell script. ### Working example The commands below were run with `@tevm/cli@1.0.0-rc.151`. They create their own local prerequisites or use the named public endpoint, so no hidden process is required. ```bash npm install --global @tevm/cli@1.0.0-rc.151 tevm session docs --local --json mkdir -p src cat > src/Counter.sol <<'SOLIDITY' // SPDX-License-Identifier: MIT pragma solidity ^0.8.20; contract Counter { uint256 public number; event NumberChanged(uint256 number); function setNumber(uint256 next) public { number = next; emit NumberChanged(next); } } SOLIDITY tevm compile --json jq '.abi' artifacts/Counter.json > artifacts/Counter.abi.json tevm set-account --address 0x1000000000000000000000000000000000000001 --balance 1000000000000000000 --session docs --run --json tevm set-code --address 0x1000000000000000000000000000000000000001 --bytecode "$(jq -r '.deployedBytecode' artifacts/Counter.json)" --session docs --run --json tevm set-storage-at --address 0x1000000000000000000000000000000000000001 --index 0x0 --value 0x2a --session docs --run --json tevm deploy --bytecode 0x6080604052348015600e575f5ffd5b5060e48061001b5f395ff3fe6080604052348015600e575f5ffd5b50600436106030575f3560e01c80633fb5c1cb1460345780638381f58a146045575b5f5ffd5b6043603f3660046098565b605e565b005b604c5f5481565b60405190815260200160405180910390f35b5f8190556040518181527f2fd81fd19d3c5c4b396dd13f451dafc8bcac1b3094c49c5fa90e68456323f0e39060200160405180910390a150565b5f6020828403121560a7575f5ffd5b503591905056fea26469706673582212203ef1a75b09ee91fb7f995d62885094508a883f40d776c10ba4f1d1427a64bd8b64736f6c63430008230033 --abi artifacts/Counter.abi.json --args [] --skip-balance --session docs --run --json ``` Output captured from the final command: ```json { "ok": true, "command": "deploy", "result": { "rawData": "0x6080604052348015600e575f5ffd5b50600436106030575f3560e01c80633fb5c1cb1460345780638381f58a146045575b5f5ffd5b6043603f3660046098565b605e565b005b604c5f5481565b60405190815260200160405180910390f35b5f8190556040518181527f2fd81fd19d3c5c4b396dd13f451dafc8bcac1b3094c49c5fa90e68456323f0e39060200160405180910390a150565b5f6020828403121560a7575f5ffd5b503591905056fea26469706673582212203ef1a75b09ee91fb7f995d62885094508a883f40d776c10ba4f1d1427a64bd8b64736f6c63430008230033", "executionGasUsed": "45697", "totalGasSpent": "102745", "minerValue": "102745000000000", "amountSpent": "102745000719215", "txHash": "0xc154f0faa56a3f07f4ae5f68567e75d593cd0571c69b8dbad02c6069aeb74ceb", "selfdestruct": [], "gas": "29942855", "logs": [], "createdAddresses": [ "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512" ], "createdAddress": "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512" }, "session": "docs" } ``` ### Arguments and flags The command schema in [`cli/src/commands/deploy.tsx`](https://github.com/evmts/tevm/blob/main/cli/src/commands/deploy.tsx) exposes: | Kind | Syntax | Description | | ---- | ------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | | Flag | `-r, --run` | Run directly without interactive parameter editing (env: TEVM\_RUN) (default: false) | | Flag | `--rpc [rpc]` | RPC endpoint (env: TEVM\_RPC) (default: [http://localhost:8545](http://localhost:8545)) | | Flag | `--bytecode ` | Contract bytecode to deploy (env: TEVM\_BYTECODE) | | Flag | `--abi [abi]` | Contract ABI (JSON string or path to file) (env: TEVM\_ABI) | | Flag | `--args [args]` | Constructor arguments (JSON string array) (env: TEVM\_ARGS) | | Flag | `--salt [salt]` | CREATE2 salt (hex encoded) (env: TEVM\_SALT) | | Flag | `--from [from]` | Address to deploy from (env: TEVM\_FROM) (default: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266) | | Flag | `--value [value]` | ETH value to send in wei (env: TEVM\_VALUE) | | Flag | `--gas [gas]` | Gas limit for the transaction (env: TEVM\_GAS) | | Flag | `--gas-price [gas-price]` | Gas price in wei (env: TEVM\_GAS\_PRICE) | | Flag | `--max-fee-per-gas [max-fee-per-gas]` | Maximum fee per gas (EIP-1559) (env: TEVM\_MAX\_FEE\_PER\_GAS) | | Flag | `--max-priority-fee-per-gas [max-priority-fee-per-gas]` | Maximum priority fee per gas (EIP-1559) (env: TEVM\_MAX\_PRIORITY\_FEE\_PER\_GAS) | | Flag | `--gas-refund [gas-refund]` | Gas refund counter (env: TEVM\_GAS\_REFUND) | | Flag | `--block-tag [block-tag]` | Block tag (latest, pending, etc.) or number (env: TEVM\_BLOCK\_TAG) | | Flag | `--caller [caller]` | Address that ran this code (msg.sender) (env: TEVM\_CALLER) | | Flag | `--origin [origin]` | Address where the call originated from (env: TEVM\_ORIGIN) | | Flag | `--depth [depth]` | Depth of EVM call stack (env: TEVM\_DEPTH) | | Flag | `--skip-balance` | Skip balance check (env: TEVM\_SKIP\_BALANCE) (default: false) | | Flag | `--create-trace` | Return a complete trace with the call (env: TEVM\_CREATE\_TRACE) (default: false) | | Flag | `--create-access-list` | Return an access list mapping of addresses to storage keys (env: TEVM\_CREATE\_ACCESS\_LIST) (default: false) | | Flag | `--create-transaction [create-transaction]` | Whether to update state (on-success, always, never) (env: TEVM\_CREATE\_TRANSACTION) (choices: "on-success", "always", "never", default: "always") | | Flag | `--json` | Emit the stable machine-readable JSON envelope (env: TEVM\_JSON) (default: false) | | Flag | `-h, --help` | Show help | `--json` and `--session ` are global options accepted before routing. See the [CLI overview](/reference/cli#global-options) for their environment-variable forms and execution model. ### Neighbours [CLI overview](/reference/cli) · [`tevm create-event-filter`](/reference/cli/create-event-filter) · [`tevm dump-state`](/reference/cli/dump-state) ## tevm dump-state `tevm dump-state` runs this operation: Dump local EVM state to JSON. Reach for it when you need the operation from a terminal, CI job, or shell script. ### Working example The commands below were run with `@tevm/cli@1.0.0-rc.151`. They create their own local prerequisites or use the named public endpoint, so no hidden process is required. ```bash npm install --global @tevm/cli@1.0.0-rc.151 tevm session docs --local --json tevm dump-state --output-file state.json --session docs --run --json ``` Output captured from the final command: ```json { "ok": true, "command": "dump-state", "result": { "state": { "0x0000000000000000000000000000000000000000": { "nonce": "0x0", "balance": "0x21e19e0efed9554a000", "storageRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", "codeHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "storage": {} }, "0x0000F90827F1C53a10cb7A02335B175320002935": { "nonce": "0x0", "balance": "0x0", "storageRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "storage": { "0x0000000000000000000000000000000000000000000000000000000000000000": "0x04f3224bc7809708a4b860e9fdd4588b38f4bcadb994f9ae1793a2ed2c38011d" } }, "0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02": { "nonce": "0x0", "balance": "0x0", "storageRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "storage": { "0x00000000000000000000000000000000000000000000000000000000000008de": "0x6a685581", "0x000000000000000000000000000000000000000000000000000000000000093c": "0x6a6855df", "0x0000000000000000000000000000000000000000000000000000000000000a11": "0x6a6856b4", "0x0000000000000000000000000000000000000000000000000000000000001003": "0x6a685ca6", "0x000000000000000000000000000000000000000000000000000000000000107a": "0x6a685d1d", "0x00000000000000000000000000000000000000000000000000000000000010b3": "0x6a685d56", "0x00000000000000000000000000000000000000000000000000000000000028dd": "0x", "0x000000000000000000000000000000000000000000000000000000000000293b": "0x", "0x0000000000000000000000000000000000000000000000000000000000002a10": "0x", "0x0000000000000000000000000000000000000000000000000000000000003002": "0x", "0x0000000000000000000000000000000000000000000000000000000000003079": "0x", "0x00000000000000000000000000000000000000000000000000000000000030b2": "0x" } }, "0x1000000000000000000000000000000000000001": { "nonce": "0x7", "balance": "0xde0b6b3a7640000", "storageRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", "codeHash": "0xb651c70c9d4547c40705b18caf3faf5e9ced641e71bab674e665870b09938b1a", "deployedBytecode": "0x6080604052348015600e575f5ffd5b50600436106030575f3560e01c80633fb5c1cb1460345780638381f58a146045575b5f5ffd5b6043603f3660046098565b605e565b005b604c5f5481565b60405190815260200160405180910390f35b5f8190556040518181527f2fd81fd19d3c5c4b396dd13f451dafc8bcac1b3094c49c5fa90e68456323f0e39060200160405180910390a150565b5f6020828403121560a7575f5ffd5b503591905056fea26469706673582212203ef1a75b09ee91fb7f995d62885094508a883f40d776c10ba4f1d1427a64bd8b64736f6c63430008230033", "storage": { "0x0000000000000000000000000000000000000000000000000000000000000000": "0x2a" } }, "0x14dC79964da2C08b23698B3D3cc7Ca32193d9955": { "nonce": "0x0", "balance": "0x21e19e0c9bab2400000", "storageRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", "codeHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "storage": {} }, "0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65": { "nonce": "0x0", "balance": "0x21e19e0c9bab2400000", "storageRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", "codeHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "storage": {} }, "0x23618e81E3f5cdF7f54C3d65f7FBc0aBf5B21E8f": { "nonce": "0x0", "balance": "0x21e19e0c9bab2400000", "storageRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", "codeHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "storage": {} }, "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC": { "nonce": "0x0", "balance": "0x21e19e0c9bab2400000", "storageRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", "codeHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "storage": {} }, "0x5A0B54d5dc17E482fE8B0BDCa5320161B95FB929": { "nonce": "0x0", "balance": "0x1bc16d674ec80000", "storageRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "storage": {} }, "0x70997970C51812dc3A010C7d01b50e0d17dc79C8": { "nonce": "0x0", "balance": "0x21e19e0c9bab2400000", "storageRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", "codeHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "storage": {} }, "0x90F79bf6EB2c4f870365E785982E1f101E93b906": { "nonce": "0x0", "balance": "0x21e19e0c9bab2400000", "storageRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", "codeHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "storage": {} }, "0x976EA74026E726554dB657fA54763abd0C3a0aa9": { "nonce": "0x0", "balance": "0x21e19e0c9bab2400000", "storageRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", "codeHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "storage": {} }, "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc": { "nonce": "0x0", "balance": "0x21e19e0c9bab2400000", "storageRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", "codeHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "storage": {} }, "0xa0Ee7A142d267C1f36714E4a8F75612F20a79720": { "nonce": "0x0", "balance": "0x21e19e0c9bab2400000", "storageRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", "codeHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "storage": {} }, "0xcA11bde05977b3631167028862bE2a173976CA11": { "nonce": "0x0", "balance": "0x0", "storageRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", "codeHash": "0xd5c15df687b16f2ff992fc8d767b4216323184a2bbc6ee2f9c398c318e770891", "deployedBytecode": "0x6080604052600436106100f35760003560e01c80634d2301cc1161008a578063a8b0574e11610059578063a8b0574e1461025a578063bce38bd714610275578063c3077fa914610288578063ee82ac5e1461029b57600080fd5b80634d2301cc146101ec57806372425d9d1461022157806382ad56cb1461023457806386d516e81461024757600080fd5b80633408e470116100c65780633408e47014610191578063399542e9146101a45780633e64a696146101c657806342cbb15c146101d957600080fd5b80630f28c97d146100f8578063174dea711461011a578063252dba421461013a57806327e86d6e1461015b575b600080fd5b34801561010457600080fd5b50425b6040519081526020015b60405180910390f35b61012d610128366004610a85565b6102ba565b6040516101119190610bbe565b61014d610148366004610a85565b6104ef565b604051610111929190610bd8565b34801561016757600080fd5b50437fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0140610107565b34801561019d57600080fd5b5046610107565b6101b76101b2366004610c60565b610690565b60405161011193929190610cba565b3480156101d257600080fd5b5048610107565b3480156101e557600080fd5b5043610107565b3480156101f857600080fd5b50610107610207366004610ce2565b73ffffffffffffffffffffffffffffffffffffffff163190565b34801561022d57600080fd5b5044610107565b61012d610242366004610a85565b6106ab565b34801561025357600080fd5b5045610107565b34801561026657600080fd5b50604051418152602001610111565b61012d610283366004610c60565b61085a565b6101b7610296366004610a85565b610a1a565b3480156102a757600080fd5b506101076102b6366004610d18565b4090565b60606000828067ffffffffffffffff8111156102d8576102d8610d31565b60405190808252806020026020018201604052801561031e57816020015b6040805180820190915260008152606060208201528152602001906001900390816102f65790505b5092503660005b8281101561047757600085828151811061034157610341610d60565b6020026020010151905087878381811061035d5761035d610d60565b905060200281019061036f9190610d8f565b6040810135958601959093506103886020850185610ce2565b73ffffffffffffffffffffffffffffffffffffffff16816103ac6060870187610dcd565b6040516103ba929190610e32565b60006040518083038185875af1925050503d80600081146103f7576040519150601f19603f3d011682016040523d82523d6000602084013e6103fc565b606091505b50602080850191909152901515808452908501351761046d577f08c379a000000000000000000000000000000000000000000000000000000000600052602060045260176024527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060445260846000fd5b5050600101610325565b508234146104e6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4d756c746963616c6c333a2076616c7565206d69736d6174636800000000000060448201526064015b60405180910390fd5b50505092915050565b436060828067ffffffffffffffff81111561050c5761050c610d31565b60405190808252806020026020018201604052801561053f57816020015b606081526020019060019003908161052a5790505b5091503660005b8281101561068657600087878381811061056257610562610d60565b90506020028101906105749190610e42565b92506105836020840184610ce2565b73ffffffffffffffffffffffffffffffffffffffff166105a66020850185610dcd565b6040516105b4929190610e32565b6000604051808303816000865af19150503d80600081146105f1576040519150601f19603f3d011682016040523d82523d6000602084013e6105f6565b606091505b5086848151811061060957610609610d60565b602090810291909101015290508061067d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060448201526064016104dd565b50600101610546565b5050509250929050565b43804060606106a086868661085a565b905093509350939050565b6060818067ffffffffffffffff8111156106c7576106c7610d31565b60405190808252806020026020018201604052801561070d57816020015b6040805180820190915260008152606060208201528152602001906001900390816106e55790505b5091503660005b828110156104e657600084828151811061073057610730610d60565b6020026020010151905086868381811061074c5761074c610d60565b905060200281019061075e9190610e76565b925061076d6020840184610ce2565b73ffffffffffffffffffffffffffffffffffffffff166107906040850185610dcd565b60405161079e929190610e32565b6000604051808303816000865af19150503d80600081146107db576040519150601f19603f3d011682016040523d82523d6000602084013e6107e0565b606091505b506020808401919091529015158083529084013517610851577f08c379a000000000000000000000000000000000000000000000000000000000600052602060045260176024527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060445260646000fd5b50600101610714565b6060818067ffffffffffffffff81111561087657610876610d31565b6040519080825280602002602001820160405280156108bc57816020015b6040805180820190915260008152606060208201528152602001906001900390816108945790505b5091503660005b82811015610a105760008482815181106108df576108df610d60565b602002602001015190508686838181106108fb576108fb610d60565b905060200281019061090d9190610e42565b925061091c6020840184610ce2565b73ffffffffffffffffffffffffffffffffffffffff1661093f6020850185610dcd565b60405161094d929190610e32565b6000604051808303816000865af19150503d806000811461098a576040519150601f19603f3d011682016040523d82523d6000602084013e61098f565b606091505b506020830152151581528715610a07578051610a07576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060448201526064016104dd565b506001016108c3565b5050509392505050565b6000806060610a2b60018686610690565b919790965090945092505050565b60008083601f840112610a4b57600080fd5b50813567ffffffffffffffff811115610a6357600080fd5b6020830191508360208260051b8501011115610a7e57600080fd5b9250929050565b60008060208385031215610a9857600080fd5b823567ffffffffffffffff811115610aaf57600080fd5b610abb85828601610a39565b90969095509350505050565b6000815180845260005b81811015610aed57602081850181015186830182015201610ad1565b81811115610aff576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b600082825180855260208086019550808260051b84010181860160005b84811015610bb1578583037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001895281518051151584528401516040858501819052610b9d81860183610ac7565b9a86019a9450505090830190600101610b4f565b5090979650505050505050565b602081526000610bd16020830184610b32565b9392505050565b600060408201848352602060408185015281855180845260608601915060608160051b870101935082870160005b82811015610c52577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0888703018452610c40868351610ac7565b95509284019290840190600101610c06565b509398975050505050505050565b600080600060408486031215610c7557600080fd5b83358015158114610c8557600080fd5b9250602084013567ffffffffffffffff811115610ca157600080fd5b610cad86828701610a39565b9497909650939450505050565b838152826020820152606060408201526000610cd96060830184610b32565b95945050505050565b600060208284031215610cf457600080fd5b813573ffffffffffffffffffffffffffffffffffffffff81168114610bd157600080fd5b600060208284031215610d2a57600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81833603018112610dc357600080fd5b9190910192915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112610e0257600080fd5b83018035915067ffffffffffffffff821115610e1d57600080fd5b602001915036819003821315610a7e57600080fd5b8183823760009101908152919050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc1833603018112610dc357600080fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa1833603018112610dc357600080fdfea2646970667358221220bb2b5c71a328032f97c676ae39a1ec2148d3e5d6f73d95e9b17910152d61f16264736f6c634300080c0033", "storage": {} }, "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266": { "nonce": "0x1", "balance": "0xde0a39a35d771c8", "storageRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "storage": {} } } }, "session": "docs" } ``` ### Arguments and flags The command schema in [`cli/src/commands/dumpState.tsx`](https://github.com/evmts/tevm/blob/main/cli/src/commands/dumpState.tsx) exposes: | Kind | Syntax | Description | | ---- | ----------------------------- | --------------------------------------------------------------------------------------- | | Flag | `-r, --run` | Run directly without interactive parameter editing (env: TEVM\_RUN) (default: false) | | Flag | `--rpc [rpc]` | RPC endpoint (env: TEVM\_RPC) (default: [http://localhost:8545](http://localhost:8545)) | | Flag | `--block-tag [block-tag]` | Block tag to dump state from (latest, earliest, pending, etc.) (env: TEVM\_BLOCK\_TAG) | | Flag | `--output-file [output-file]` | Optional file path to save the state to (env: TEVM\_OUTPUT\_FILE) | | Flag | `--json` | Emit the stable machine-readable JSON envelope (env: TEVM\_JSON) (default: false) | | Flag | `-h, --help` | Show help | `--json` and `--session ` are global options accepted before routing. See the [CLI overview](/reference/cli#global-options) for their environment-variable forms and execution model. ### Neighbours [CLI overview](/reference/cli) · [`tevm deploy`](/reference/cli/deploy) · [`tevm estimate-fees-per-gas`](/reference/cli/estimate-fees-per-gas) ## tevm estimate-fees-per-gas `tevm estimate-fees-per-gas` runs this operation: Estimate EIP-1559 gas fees. Reach for it when you need the operation from a terminal, CI job, or shell script. ### Working example The commands below were run with `@tevm/cli@1.0.0-rc.151`. They create their own local prerequisites or use the named public endpoint, so no hidden process is required. ```bash npm install --global @tevm/cli@1.0.0-rc.151 tevm session docs --local --json tevm estimate-fees-per-gas --type eip1559 --session docs --run --json ``` Output captured from the final command: ```json { "ok": true, "command": "estimate-fees-per-gas", "result": { "maxFeePerGas": "1000000008", "maxPriorityFeePerGas": "1000000000" }, "session": "docs" } ``` ### Arguments and flags The command schema in [`cli/src/commands/estimateFeesPerGas.tsx`](https://github.com/evmts/tevm/blob/main/cli/src/commands/estimateFeesPerGas.tsx) exposes: | Kind | Syntax | Description | | ---- | --------------- | ------------------------------------------------------------------------------------ | | Flag | `--type [type]` | Transaction type (env: TEVM\_TYPE) | | Flag | `-r, --run` | Run directly without interactive parameter editing (env: TEVM\_RUN) (default: false) | | Flag | `--rpc [rpc]` | RPC endpoint (env: TEVM\_RPC) | | Flag | `--json` | Emit the stable machine-readable JSON envelope (env: TEVM\_JSON) (default: false) | | Flag | `-h, --help` | Show help | `--json` and `--session ` are global options accepted before routing. See the [CLI overview](/reference/cli#global-options) for their environment-variable forms and execution model. ### Neighbours [CLI overview](/reference/cli) · [`tevm dump-state`](/reference/cli/dump-state) · [`tevm estimate-gas`](/reference/cli/estimate-gas) ## tevm estimate-gas `tevm estimate-gas` runs this operation: Estimate transaction gas. Reach for it when you need the operation from a terminal, CI job, or shell script. ### Working example The commands below were run with `@tevm/cli@1.0.0-rc.151`. They create their own local prerequisites or use the named public endpoint, so no hidden process is required. ```bash npm install --global @tevm/cli@1.0.0-rc.151 tevm session docs --local --json mkdir -p src cat > src/Counter.sol <<'SOLIDITY' // SPDX-License-Identifier: MIT pragma solidity ^0.8.20; contract Counter { uint256 public number; event NumberChanged(uint256 number); function setNumber(uint256 next) public { number = next; emit NumberChanged(next); } } SOLIDITY tevm compile --json jq '.abi' artifacts/Counter.json > artifacts/Counter.abi.json tevm set-account --address 0x1000000000000000000000000000000000000001 --balance 1000000000000000000 --session docs --run --json tevm set-code --address 0x1000000000000000000000000000000000000001 --bytecode "$(jq -r '.deployedBytecode' artifacts/Counter.json)" --session docs --run --json tevm set-storage-at --address 0x1000000000000000000000000000000000000001 --index 0x0 --value 0x2a --session docs --run --json tevm estimate-gas --to 0x1000000000000000000000000000000000000001 --data 0x8381f58a --session docs --run --json ``` Output captured from the final command: ```json { "ok": true, "command": "estimate-gas", "result": "23345", "session": "docs" } ``` ### Arguments and flags The command schema in [`cli/src/commands/estimateGas.tsx`](https://github.com/evmts/tevm/blob/main/cli/src/commands/estimateGas.tsx) exposes: | Kind | Syntax | Description | | ---- | ------------------------------------------------------- | ------------------------------------------------------------------------------------ | | Flag | `--to [to]` | Target contract address (env: TEVM\_TO) | | Flag | `--from [from]` | Address to send the transaction from (env: TEVM\_FROM) | | Flag | `--data [data]` | Transaction data (hex encoded) (env: TEVM\_DATA) | | Flag | `--value [value]` | ETH value to send in wei (env: TEVM\_VALUE) | | Flag | `--gas [gas]` | Gas limit for the transaction (env: TEVM\_GAS) | | Flag | `--gas-price [gas-price]` | Gas price in wei (env: TEVM\_GAS\_PRICE) | | Flag | `--max-fee-per-gas [max-fee-per-gas]` | Maximum fee per gas (EIP-1559) (env: TEVM\_MAX\_FEE\_PER\_GAS) | | Flag | `--max-priority-fee-per-gas [max-priority-fee-per-gas]` | Maximum priority fee per gas (EIP-1559) (env: TEVM\_MAX\_PRIORITY\_FEE\_PER\_GAS) | | Flag | `-r, --run` | Run directly without interactive parameter editing (env: TEVM\_RUN) (default: false) | | Flag | `--rpc [rpc]` | RPC endpoint (env: TEVM\_RPC) | | Flag | `--block-tag [block-tag]` | Block tag (latest, pending, etc.) or number (env: TEVM\_BLOCK\_TAG) | | Flag | `--json` | Emit the stable machine-readable JSON envelope (env: TEVM\_JSON) (default: false) | | Flag | `-h, --help` | Show help | `--json` and `--session ` are global options accepted before routing. See the [CLI overview](/reference/cli#global-options) for their environment-variable forms and execution model. ### Neighbours [CLI overview](/reference/cli) · [`tevm estimate-fees-per-gas`](/reference/cli/estimate-fees-per-gas) · [`tevm get-account`](/reference/cli/get-account) ## tevm get-account `tevm get-account` runs this operation: Get local account balance, nonce, code, and storage metadata. Reach for it when you need the operation from a terminal, CI job, or shell script. ### Working example The commands below were run with `@tevm/cli@1.0.0-rc.151`. They create their own local prerequisites or use the named public endpoint, so no hidden process is required. ```bash npm install --global @tevm/cli@1.0.0-rc.151 tevm session docs --local --json mkdir -p src cat > src/Counter.sol <<'SOLIDITY' // SPDX-License-Identifier: MIT pragma solidity ^0.8.20; contract Counter { uint256 public number; event NumberChanged(uint256 number); function setNumber(uint256 next) public { number = next; emit NumberChanged(next); } } SOLIDITY tevm compile --json jq '.abi' artifacts/Counter.json > artifacts/Counter.abi.json tevm set-account --address 0x1000000000000000000000000000000000000001 --balance 1000000000000000000 --session docs --run --json tevm set-code --address 0x1000000000000000000000000000000000000001 --bytecode "$(jq -r '.deployedBytecode' artifacts/Counter.json)" --session docs --run --json tevm set-storage-at --address 0x1000000000000000000000000000000000000001 --index 0x0 --value 0x2a --session docs --run --json tevm get-account --address 0x1000000000000000000000000000000000000001 --return-storage --session docs --run --json ``` Output captured from the final command: ```json { "ok": true, "command": "get-account", "result": { "address": "0x1000000000000000000000000000000000000001", "balance": "1000000000000000000", "codeHash": "0xb651c70c9d4547c40705b18caf3faf5e9ced641e71bab674e665870b09938b1a", "isContract": true, "isEmpty": false, "deployedBytecode": "0x6080604052348015600e575f5ffd5b50600436106030575f3560e01c80633fb5c1cb1460345780638381f58a146045575b5f5ffd5b6043603f3660046098565b605e565b005b604c5f5481565b60405190815260200160405180910390f35b5f8190556040518181527f2fd81fd19d3c5c4b396dd13f451dafc8bcac1b3094c49c5fa90e68456323f0e39060200160405180910390a150565b5f6020828403121560a7575f5ffd5b503591905056fea26469706673582212203ef1a75b09ee91fb7f995d62885094508a883f40d776c10ba4f1d1427a64bd8b64736f6c63430008230033", "nonce": "7", "storageRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", "storage": { "0x0000000000000000000000000000000000000000000000000000000000000000": "0x2a" } }, "session": "docs" } ``` ### Arguments and flags The command schema in [`cli/src/commands/getAccount.tsx`](https://github.com/evmts/tevm/blob/main/cli/src/commands/getAccount.tsx) exposes: | Kind | Syntax | Description | | ---- | ------------------------- | ----------------------------------------------------------------------------------------- | | Flag | `--address
` | Ethereum address of the account to get (env: TEVM\_ADDRESS) | | Flag | `-r, --run` | Run directly without interactive parameter editing (env: TEVM\_RUN) (default: false) | | Flag | `--rpc [rpc]` | RPC endpoint (env: TEVM\_RPC) (default: [http://localhost:8545](http://localhost:8545)) | | Flag | `--return-storage` | Return account storage (can be expensive) (env: TEVM\_RETURN\_STORAGE) (default: false) | | Flag | `--block-tag [block-tag]` | Block tag to fetch account from (latest, earliest, pending, etc.) (env: TEVM\_BLOCK\_TAG) | | Flag | `--json` | Emit the stable machine-readable JSON envelope (env: TEVM\_JSON) (default: false) | | Flag | `-h, --help` | Show help | `--json` and `--session ` are global options accepted before routing. See the [CLI overview](/reference/cli#global-options) for their environment-variable forms and execution model. ### Neighbours [CLI overview](/reference/cli) · [`tevm estimate-gas`](/reference/cli/estimate-gas) · [`tevm action get-balance`](/reference/cli/get-balance) ## tevm action get-balance `tevm action get-balance` runs this operation: Get an account Ether balance. Reach for it when you need the operation from a terminal, CI job, or shell script. ### Working example The commands below were run with `@tevm/cli@1.0.0-rc.151`. They create their own local prerequisites or use the named public endpoint, so no hidden process is required. ```bash npm install --global @tevm/cli@1.0.0-rc.151 tevm session docs --local --json tevm action get-balance --address 0x1000000000000000000000000000000000000001 --session docs --run --json ``` Output captured from the final command: ```json { "ok": true, "command": "get-balance", "result": "1000000000000000000", "session": "docs" } ``` ### Arguments and flags The command schema in [`cli/src/commands/action/getBalance.tsx`](https://github.com/evmts/tevm/blob/main/cli/src/commands/action/getBalance.tsx) exposes: | Kind | Syntax | Description | | ---- | ------------------------------- | ------------------------------------------------------------------------------------ | | Flag | `--address [address]` | Account address to get balance for (env: TEVM\_ADDRESS) | | Flag | `--block-number [block-number]` | Block number to query at (env: TEVM\_BLOCK\_NUMBER) | | Flag | `--block-tag [block-tag]` | Block tag (latest, pending, etc.) (env: TEVM\_BLOCK\_TAG) | | Flag | `-r, --run` | Run directly without interactive parameter editing (env: TEVM\_RUN) (default: false) | | Flag | `--rpc [rpc]` | RPC endpoint (env: TEVM\_RPC) | | Flag | `--json` | Emit the stable machine-readable JSON envelope (env: TEVM\_JSON) (default: false) | | Flag | `-h, --help` | Show help | `--json` and `--session ` are global options accepted before routing. See the [CLI overview](/reference/cli#global-options) for their environment-variable forms and execution model. ### Neighbours [CLI overview](/reference/cli) · [`tevm get-account`](/reference/cli/get-account) · [`tevm get-block`](/reference/cli/get-block) ## tevm get-block-number `tevm get-block-number` runs this operation: Get the current block number. Reach for it when you need the operation from a terminal, CI job, or shell script. ### Working example The commands below were run with `@tevm/cli@1.0.0-rc.151`. They create their own local prerequisites or use the named public endpoint, so no hidden process is required. ```bash npm install --global @tevm/cli@1.0.0-rc.151 tevm session docs --local --json tevm get-block-number --session docs --run --json ``` Output captured from the final command: ```json { "ok": true, "command": "get-block-number", "result": "0", "session": "docs" } ``` ### Arguments and flags The command schema in [`cli/src/commands/getBlockNumber.tsx`](https://github.com/evmts/tevm/blob/main/cli/src/commands/getBlockNumber.tsx) exposes: | Kind | Syntax | Description | | ---- | --------------------------- | ------------------------------------------------------------------------------------ | | Flag | `--cache-time [cache-time]` | Time in milliseconds to cache the result (env: TEVM\_CACHE\_TIME) | | Flag | `-r, --run` | Run directly without interactive parameter editing (env: TEVM\_RUN) (default: false) | | Flag | `--rpc [rpc]` | RPC endpoint (env: TEVM\_RPC) | | Flag | `--json` | Emit the stable machine-readable JSON envelope (env: TEVM\_JSON) (default: false) | | Flag | `-h, --help` | Show help | `--json` and `--session ` are global options accepted before routing. See the [CLI overview](/reference/cli#global-options) for their environment-variable forms and execution model. ### Neighbours [CLI overview](/reference/cli) · [`tevm get-block`](/reference/cli/get-block) · [`tevm get-bytecode`](/reference/cli/get-bytecode) ## tevm get-block `tevm get-block` runs this operation: Get a block by number, hash, or tag. Reach for it when you need the operation from a terminal, CI job, or shell script. ### Working example The commands below were run with `@tevm/cli@1.0.0-rc.151`. They create their own local prerequisites or use the named public endpoint, so no hidden process is required. ```bash npm install --global @tevm/cli@1.0.0-rc.151 tevm session docs --local --json tevm get-block --block-tag latest --session docs --run --json ``` Output captured from the final command: ```json { "ok": true, "command": "get-block", "result": { "number": "0", "hash": "0x04f3224bc7809708a4b860e9fdd4588b38f4bcadb994f9ae1793a2ed2c38011d", "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "nonce": "0x0000000000000042", "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "transactionsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", "stateRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", "miner": "0x0000000000000000000000000000000000000000", "difficulty": "17179869184", "totalDifficulty": "0", "extraData": "0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa", "size": "1695", "gasLimit": "30000000", "gasUsed": "0", "timestamp": "0", "uncles": [], "transactions": [], "baseFeePerGas": "7", "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", "withdrawalsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", "withdrawals": [], "blobGasUsed": "0", "requestsRoot": "0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "requests": [], "excessBlobGas": "0", "parentBeaconBlockRoot": "0x0000000000000000000000000000000000000000000000000000000000000000" }, "session": "docs" } ``` ### Arguments and flags The command schema in [`cli/src/commands/getBlock.tsx`](https://github.com/evmts/tevm/blob/main/cli/src/commands/getBlock.tsx) exposes: | Kind | Syntax | Description | | ---- | ------------------------------- | ----------------------------------------------------------------------------------------------- | | Flag | `--block-hash [block-hash]` | Block hash to get information for (env: TEVM\_BLOCK\_HASH) | | Flag | `--block-number [block-number]` | Block number to get information for (env: TEVM\_BLOCK\_NUMBER) | | Flag | `--block-tag [block-tag]` | Block tag (latest, pending, etc.) (env: TEVM\_BLOCK\_TAG) | | Flag | `--include-transactions` | Whether to include full transaction objects (env: TEVM\_INCLUDE\_TRANSACTIONS) (default: false) | | Flag | `-r, --run` | Run directly without interactive parameter editing (env: TEVM\_RUN) (default: false) | | Flag | `--rpc [rpc]` | RPC endpoint (env: TEVM\_RPC) | | Flag | `--json` | Emit the stable machine-readable JSON envelope (env: TEVM\_JSON) (default: false) | | Flag | `-h, --help` | Show help | `--json` and `--session ` are global options accepted before routing. See the [CLI overview](/reference/cli#global-options) for their environment-variable forms and execution model. ### Neighbours [CLI overview](/reference/cli) · [`tevm action get-balance`](/reference/cli/get-balance) · [`tevm get-block-number`](/reference/cli/get-block-number) ## tevm get-bytecode `tevm get-bytecode` runs this operation: Get deployed bytecode at an address. Reach for it when you need the operation from a terminal, CI job, or shell script. ### Working example The commands below were run with `@tevm/cli@1.0.0-rc.151`. They create their own local prerequisites or use the named public endpoint, so no hidden process is required. ```bash npm install --global @tevm/cli@1.0.0-rc.151 tevm session docs --local --json mkdir -p src cat > src/Counter.sol <<'SOLIDITY' // SPDX-License-Identifier: MIT pragma solidity ^0.8.20; contract Counter { uint256 public number; event NumberChanged(uint256 number); function setNumber(uint256 next) public { number = next; emit NumberChanged(next); } } SOLIDITY tevm compile --json jq '.abi' artifacts/Counter.json > artifacts/Counter.abi.json tevm set-account --address 0x1000000000000000000000000000000000000001 --balance 1000000000000000000 --session docs --run --json tevm set-code --address 0x1000000000000000000000000000000000000001 --bytecode "$(jq -r '.deployedBytecode' artifacts/Counter.json)" --session docs --run --json tevm set-storage-at --address 0x1000000000000000000000000000000000000001 --index 0x0 --value 0x2a --session docs --run --json tevm get-bytecode --address 0x1000000000000000000000000000000000000001 --session docs --run --json ``` Output captured from the final command: ```json { "ok": true, "command": "get-bytecode", "result": "0x6080604052348015600e575f5ffd5b50600436106030575f3560e01c80633fb5c1cb1460345780638381f58a146045575b5f5ffd5b6043603f3660046098565b605e565b005b604c5f5481565b60405190815260200160405180910390f35b5f8190556040518181527f2fd81fd19d3c5c4b396dd13f451dafc8bcac1b3094c49c5fa90e68456323f0e39060200160405180910390a150565b5f6020828403121560a7575f5ffd5b503591905056fea26469706673582212203ef1a75b09ee91fb7f995d62885094508a883f40d776c10ba4f1d1427a64bd8b64736f6c63430008230033", "session": "docs" } ``` ### Arguments and flags The command schema in [`cli/src/commands/getBytecode.tsx`](https://github.com/evmts/tevm/blob/main/cli/src/commands/getBytecode.tsx) exposes: | Kind | Syntax | Description | | ---- | ------------------------------- | ------------------------------------------------------------------------------------ | | Flag | `--address [address]` | Contract address to get bytecode for (env: TEVM\_ADDRESS) | | Flag | `--block-tag [block-tag]` | Block tag (latest, pending, etc.) (env: TEVM\_BLOCK\_TAG) | | Flag | `--block-number [block-number]` | Block number to get bytecode at (env: TEVM\_BLOCK\_NUMBER) | | Flag | `-r, --run` | Run directly without interactive parameter editing (env: TEVM\_RUN) (default: false) | | Flag | `--rpc [rpc]` | RPC endpoint (env: TEVM\_RPC) | | Flag | `--json` | Emit the stable machine-readable JSON envelope (env: TEVM\_JSON) (default: false) | | Flag | `-h, --help` | Show help | `--json` and `--session ` are global options accepted before routing. See the [CLI overview](/reference/cli#global-options) for their environment-variable forms and execution model. ### Neighbours [CLI overview](/reference/cli) · [`tevm get-block-number`](/reference/cli/get-block-number) · [`tevm get-chain-id`](/reference/cli/get-chain-id) ## tevm get-chain-id `tevm get-chain-id` runs this operation: Get the chain ID. Reach for it when you need the operation from a terminal, CI job, or shell script. ### Working example The commands below were run with `@tevm/cli@1.0.0-rc.151`. They create their own local prerequisites or use the named public endpoint, so no hidden process is required. ```bash npm install --global @tevm/cli@1.0.0-rc.151 tevm session docs --local --json tevm get-chain-id --session docs --run --json ``` Output captured from the final command: ```json { "ok": true, "command": "get-chain-id", "result": 900, "session": "docs" } ``` ### Arguments and flags The command schema in [`cli/src/commands/getChainId.tsx`](https://github.com/evmts/tevm/blob/main/cli/src/commands/getChainId.tsx) exposes: | Kind | Syntax | Description | | ---- | ------------- | ------------------------------------------------------------------------------------ | | Flag | `-r, --run` | Run directly without interactive parameter editing (env: TEVM\_RUN) (default: false) | | Flag | `--rpc [rpc]` | RPC endpoint (env: TEVM\_RPC) | | Flag | `--json` | Emit the stable machine-readable JSON envelope (env: TEVM\_JSON) (default: false) | | Flag | `-h, --help` | Show help | `--json` and `--session ` are global options accepted before routing. See the [CLI overview](/reference/cli#global-options) for their environment-variable forms and execution model. ### Neighbours [CLI overview](/reference/cli) · [`tevm get-bytecode`](/reference/cli/get-bytecode) · [`tevm get-ens-address`](/reference/cli/get-ens-address) ## tevm get-ens-address `tevm get-ens-address` runs this operation: Resolve an ENS name to an address. Reach for it when you need the operation from a terminal, CI job, or shell script. ### Working example The commands below were run with `@tevm/cli@1.0.0-rc.151`. They create their own local prerequisites or use the named public endpoint, so no hidden process is required. ```bash npm install --global @tevm/cli@1.0.0-rc.151 tevm get-ens-address --name vitalik.eth --universal-resolver-address 0xeeeeeeee14d718c2b47d9923deab1335e144eeee --rpc https://ethereum-rpc.publicnode.com --run --json ``` Output captured from the final command: ```json { "ok": true, "command": "get-ens-address", "result": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045" } ``` ### Arguments and flags The command schema in [`cli/src/commands/getEnsAddress.tsx`](https://github.com/evmts/tevm/blob/main/cli/src/commands/getEnsAddress.tsx) exposes: | Kind | Syntax | Description | | ---- | ----------------------------------------------------------- | ------------------------------------------------------------------------------------ | | Flag | `--name [name]` | ENS name to resolve (env: TEVM\_NAME) | | Flag | `--block-tag [block-tag]` | Block tag (latest, pending, etc.) (env: TEVM\_BLOCK\_TAG) | | Flag | `--block-number [block-number]` | Block number to query at (env: TEVM\_BLOCK\_NUMBER) | | Flag | `--universal-resolver-address [universal-resolver-address]` | Address of ENS Universal Resolver (env: TEVM\_UNIVERSAL\_RESOLVER\_ADDRESS) | | Flag | `-r, --run` | Run directly without interactive parameter editing (env: TEVM\_RUN) (default: false) | | Flag | `--rpc [rpc]` | RPC endpoint (env: TEVM\_RPC) | | Flag | `--json` | Emit the stable machine-readable JSON envelope (env: TEVM\_JSON) (default: false) | | Flag | `-h, --help` | Show help | `--json` and `--session ` are global options accepted before routing. See the [CLI overview](/reference/cli#global-options) for their environment-variable forms and execution model. ### Neighbours [CLI overview](/reference/cli) · [`tevm get-chain-id`](/reference/cli/get-chain-id) · [`tevm get-ens-name`](/reference/cli/get-ens-name) ## tevm get-ens-name `tevm get-ens-name` runs this operation: Reverse-resolve an address to an ENS name. Reach for it when you need the operation from a terminal, CI job, or shell script. ### Working example The commands below were run with `@tevm/cli@1.0.0-rc.151`. They create their own local prerequisites or use the named public endpoint, so no hidden process is required. ```bash npm install --global @tevm/cli@1.0.0-rc.151 tevm get-ens-name --address 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045 --universal-resolver-address 0xeeeeeeee14d718c2b47d9923deab1335e144eeee --rpc https://ethereum-rpc.publicnode.com --run --json ``` Output captured from the final command: ```json { "ok": true, "command": "get-ens-name", "result": "vitalik.eth" } ``` ### Arguments and flags The command schema in [`cli/src/commands/getEnsName.tsx`](https://github.com/evmts/tevm/blob/main/cli/src/commands/getEnsName.tsx) exposes: | Kind | Syntax | Description | | ---- | ----------------------------------------------------------- | ------------------------------------------------------------------------------------ | | Flag | `--address [address]` | Ethereum address to lookup (env: TEVM\_ADDRESS) | | Flag | `--block-tag [block-tag]` | Block tag (latest, pending, etc.) (env: TEVM\_BLOCK\_TAG) | | Flag | `--block-number [block-number]` | Block number to query at (env: TEVM\_BLOCK\_NUMBER) | | Flag | `--universal-resolver-address [universal-resolver-address]` | Address of ENS Universal Resolver (env: TEVM\_UNIVERSAL\_RESOLVER\_ADDRESS) | | Flag | `-r, --run` | Run directly without interactive parameter editing (env: TEVM\_RUN) (default: false) | | Flag | `--rpc [rpc]` | RPC endpoint (env: TEVM\_RPC) | | Flag | `--json` | Emit the stable machine-readable JSON envelope (env: TEVM\_JSON) (default: false) | | Flag | `-h, --help` | Show help | `--json` and `--session ` are global options accepted before routing. See the [CLI overview](/reference/cli#global-options) for their environment-variable forms and execution model. ### Neighbours [CLI overview](/reference/cli) · [`tevm get-ens-address`](/reference/cli/get-ens-address) · [`tevm get-ens-text`](/reference/cli/get-ens-text) ## tevm get-ens-text `tevm get-ens-text` runs this operation: Get an ENS text record. Reach for it when you need the operation from a terminal, CI job, or shell script. ### Working example The commands below were run with `@tevm/cli@1.0.0-rc.151`. They create their own local prerequisites or use the named public endpoint, so no hidden process is required. ```bash npm install --global @tevm/cli@1.0.0-rc.151 tevm get-ens-text --name vitalik.eth --key url --universal-resolver-address 0xeeeeeeee14d718c2b47d9923deab1335e144eeee --rpc https://ethereum-rpc.publicnode.com --run --json ``` Output captured from the final command: ```json { "ok": true, "command": "get-ens-text", "result": "https://vitalik.ca" } ``` ### Arguments and flags The command schema in [`cli/src/commands/getEnsText.tsx`](https://github.com/evmts/tevm/blob/main/cli/src/commands/getEnsText.tsx) exposes: | Kind | Syntax | Description | | ---- | ----------------------------------------------------------- | ------------------------------------------------------------------------------------ | | Flag | `--name [name]` | ENS name to lookup (env: TEVM\_NAME) | | Flag | `--key [key]` | Text record key to retrieve (env: TEVM\_KEY) | | Flag | `--block-tag [block-tag]` | Block tag (latest, pending, etc.) (env: TEVM\_BLOCK\_TAG) | | Flag | `--block-number [block-number]` | Block number to query at (env: TEVM\_BLOCK\_NUMBER) | | Flag | `--universal-resolver-address [universal-resolver-address]` | Address of ENS Universal Resolver (env: TEVM\_UNIVERSAL\_RESOLVER\_ADDRESS) | | Flag | `-r, --run` | Run directly without interactive parameter editing (env: TEVM\_RUN) (default: false) | | Flag | `--rpc [rpc]` | RPC endpoint (env: TEVM\_RPC) | | Flag | `--json` | Emit the stable machine-readable JSON envelope (env: TEVM\_JSON) (default: false) | | Flag | `-h, --help` | Show help | `--json` and `--session ` are global options accepted before routing. See the [CLI overview](/reference/cli#global-options) for their environment-variable forms and execution model. ### Neighbours [CLI overview](/reference/cli) · [`tevm get-ens-name`](/reference/cli/get-ens-name) · [`tevm get-gas-price`](/reference/cli/get-gas-price) ## tevm get-gas-price `tevm get-gas-price` runs this operation: Get the current gas price. Reach for it when you need the operation from a terminal, CI job, or shell script. ### Working example The commands below were run with `@tevm/cli@1.0.0-rc.151`. They create their own local prerequisites or use the named public endpoint, so no hidden process is required. ```bash npm install --global @tevm/cli@1.0.0-rc.151 tevm session docs --local --json tevm get-gas-price --session docs --run --json ``` Output captured from the final command: ```json { "ok": true, "command": "get-gas-price", "result": "1000000000", "session": "docs" } ``` ### Arguments and flags The command schema in [`cli/src/commands/getGasPrice.tsx`](https://github.com/evmts/tevm/blob/main/cli/src/commands/getGasPrice.tsx) exposes: | Kind | Syntax | Description | | ---- | ------------- | ------------------------------------------------------------------------------------ | | Flag | `-r, --run` | Run directly without interactive parameter editing (env: TEVM\_RUN) (default: false) | | Flag | `--rpc [rpc]` | RPC endpoint (env: TEVM\_RPC) | | Flag | `--json` | Emit the stable machine-readable JSON envelope (env: TEVM\_JSON) (default: false) | | Flag | `-h, --help` | Show help | `--json` and `--session ` are global options accepted before routing. See the [CLI overview](/reference/cli#global-options) for their environment-variable forms and execution model. ### Neighbours [CLI overview](/reference/cli) · [`tevm get-ens-text`](/reference/cli/get-ens-text) · [`tevm get-storage-at`](/reference/cli/get-storage-at) ## tevm get-storage-at `tevm get-storage-at` runs this operation: Read a raw contract storage slot. Reach for it when you need the operation from a terminal, CI job, or shell script. ### Working example The commands below were run with `@tevm/cli@1.0.0-rc.151`. They create their own local prerequisites or use the named public endpoint, so no hidden process is required. ```bash npm install --global @tevm/cli@1.0.0-rc.151 tevm session docs --local --json mkdir -p src cat > src/Counter.sol <<'SOLIDITY' // SPDX-License-Identifier: MIT pragma solidity ^0.8.20; contract Counter { uint256 public number; event NumberChanged(uint256 number); function setNumber(uint256 next) public { number = next; emit NumberChanged(next); } } SOLIDITY tevm compile --json jq '.abi' artifacts/Counter.json > artifacts/Counter.abi.json tevm set-account --address 0x1000000000000000000000000000000000000001 --balance 1000000000000000000 --session docs --run --json tevm set-code --address 0x1000000000000000000000000000000000000001 --bytecode "$(jq -r '.deployedBytecode' artifacts/Counter.json)" --session docs --run --json tevm set-storage-at --address 0x1000000000000000000000000000000000000001 --index 0x0 --value 0x2a --session docs --run --json tevm get-storage-at --address 0x1000000000000000000000000000000000000001 --slot 0x0 --session docs --run --json ``` Output captured from the final command: ```json { "ok": true, "command": "get-storage-at", "result": "0x000000000000000000000000000000000000000000000000000000000000002a", "session": "docs" } ``` ### Arguments and flags The command schema in [`cli/src/commands/getStorageAt.tsx`](https://github.com/evmts/tevm/blob/main/cli/src/commands/getStorageAt.tsx) exposes: | Kind | Syntax | Description | | ---- | ------------------------------- | ------------------------------------------------------------------------------------ | | Flag | `--address [address]` | Contract address to get storage from (env: TEVM\_ADDRESS) | | Flag | `--slot [slot]` | Storage slot to read (env: TEVM\_SLOT) | | Flag | `--block-tag [block-tag]` | Block tag (latest, pending, etc.) (env: TEVM\_BLOCK\_TAG) | | Flag | `--block-number [block-number]` | Block number to get storage at (env: TEVM\_BLOCK\_NUMBER) | | Flag | `-r, --run` | Run directly without interactive parameter editing (env: TEVM\_RUN) (default: false) | | Flag | `--rpc [rpc]` | RPC endpoint (env: TEVM\_RPC) | | Flag | `--json` | Emit the stable machine-readable JSON envelope (env: TEVM\_JSON) (default: false) | | Flag | `-h, --help` | Show help | `--json` and `--session ` are global options accepted before routing. See the [CLI overview](/reference/cli#global-options) for their environment-variable forms and execution model. ### Neighbours [CLI overview](/reference/cli) · [`tevm get-gas-price`](/reference/cli/get-gas-price) · [`tevm get-transaction`](/reference/cli/get-transaction) ## tevm get-transaction `tevm get-transaction` runs this operation: Get a transaction by hash. Reach for it when you need the operation from a terminal, CI job, or shell script. ### Working example The commands below were run with `@tevm/cli@1.0.0-rc.151`. They create their own local prerequisites or use the named public endpoint, so no hidden process is required. ```bash npm install --global @tevm/cli@1.0.0-rc.151 tevm get-transaction --hash 0xf03306d59d6086655178a082e59a78eb097399af84fde1e5ae9f7ca8dc0be51a --rpc https://ethereum-rpc.publicnode.com --run --json ``` Output captured from the final command: ```json { "ok": true, "command": "get-transaction", "result": { "blockHash": "0xdf717cf689cfbddf84b8c6a9311e35376b298e5e207696f7429d3b11b8a54039", "blockNumber": "25629713", "blockTimestamp": "1785222395", "from": "0xbe07d37e54bb57fd2053036f44e6046f3bfb1954", "gas": "314950", "gasPrice": "5050533277", "maxFeePerGas": "6050533277", "maxPriorityFeePerGas": "5000000000", "hash": "0xf03306d59d6086655178a082e59a78eb097399af84fde1e5ae9f7ca8dc0be51a", "input": "0x0b1149ec000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000003e000000000000000000000000000000000000000000000000002c68af0bb1400000000000000000000000000000000000000000000000000000000007709e8783700000000000000000000000000000000000000000000000000005af3107a400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006a685501000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000002710000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000eb7e4c719612e4c68909a938065a8f2dd037fc1900000000000000000000000000000000000000000000000002c68af0bb1400000000000000000000000000000000000000000000000000000000007709e878370000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d5528764584d0a2afe49cfdaa1ef6252d35d2840000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000d721706581d97ecd202bbab5c71b5a85f0f78e69000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000be07d37e54bb57fd2053036f44e6046f3bfb1954", "nonce": 2490, "to": "0x734ab9de48f6bab1f2297a34d257cd757deba6aa", "transactionIndex": 0, "value": "200100000000000000", "type": "eip1559", "accessList": [], "chainId": 1, "v": "0", "r": "0x65cdc66b28b0aba75680d9a1a496194fa8e457d2b2506c4635b80cd87c1b426f", "s": "0x2802b5cb0b68d3501a22391b77ebc743dc78d41be6033fcc8d837314b1f0615a", "yParity": 0, "typeHex": "0x2" } } ``` ### Arguments and flags The command schema in [`cli/src/commands/getTransaction.tsx`](https://github.com/evmts/tevm/blob/main/cli/src/commands/getTransaction.tsx) exposes: | Kind | Syntax | Description | | ---- | --------------- | ------------------------------------------------------------------------------------ | | Flag | `--hash [hash]` | Transaction hash to get information for (env: TEVM\_HASH) | | Flag | `-r, --run` | Run directly without interactive parameter editing (env: TEVM\_RUN) (default: false) | | Flag | `--rpc [rpc]` | RPC endpoint (env: TEVM\_RPC) | | Flag | `--json` | Emit the stable machine-readable JSON envelope (env: TEVM\_JSON) (default: false) | | Flag | `-h, --help` | Show help | `--json` and `--session ` are global options accepted before routing. See the [CLI overview](/reference/cli#global-options) for their environment-variable forms and execution model. ### Neighbours [CLI overview](/reference/cli) · [`tevm get-storage-at`](/reference/cli/get-storage-at) · [`tevm load-state`](/reference/cli/load-state) ## Tevm CLI The Tevm CLI exposes rc.151 node actions, contract tools, state controls, and Solidity compilation as shell commands. Reach for it when a one-off command or script is more direct than creating a JavaScript client. ### Install and create a local session ```bash npm install --global @tevm/cli@1.0.0-rc.151 tevm --version tevm session docs --local --json ``` ```text 1.0.0-rc.151 { "ok": true, "command": "session", "result": { "version": 1, "name": "docs" }, "session": "docs" } ``` A named session reloads and persists local state between commands. Use `--run` to skip the interactive editor and `--json` for the stable `{ ok, command, result, session }` envelope. ### Global options | Flag | Environment | Effect | | --------------------- | -------------- | --------------------------------------------------------- | | `--json`, `--no-json` | `TEVM_JSON` | Select stable JSON or human output. | | `--session ` | `TEVM_SESSION` | Load and persist a named local or forked state file. | | `--run`, `-r` | `TEVM_RUN` | Execute directly instead of opening the parameter editor. | | `--rpc ` | `TEVM_RPC` | Fork or query the selected JSON-RPC endpoint. | ### Command reference | Command | Purpose | | ---------------------------------------------------------------------------------- | --------------------------------- | | [`tevm call`](/reference/cli/call) | call command | | [`tevm compile`](/reference/cli/compile) | compile command | | [`tevm contract`](/reference/cli/contract) | contract command | | [`tevm action create-access-list`](/reference/cli/create-access-list) | createAccessList command | | [`tevm create-block-filter`](/reference/cli/create-block-filter) | createBlockFilter command | | [`tevm create-contract-event-filter`](/reference/cli/create-contract-event-filter) | createContractEventFilter command | | [`tevm create-event-filter`](/reference/cli/create-event-filter) | createEventFilter command | | [`tevm deploy`](/reference/cli/deploy) | deploy command | | [`tevm dump-state`](/reference/cli/dump-state) | dumpState command | | [`tevm estimate-fees-per-gas`](/reference/cli/estimate-fees-per-gas) | estimateFeesPerGas command | | [`tevm estimate-gas`](/reference/cli/estimate-gas) | estimateGas command | | [`tevm get-account`](/reference/cli/get-account) | getAccount command | | [`tevm action get-balance`](/reference/cli/get-balance) | getBalance command | | [`tevm get-block`](/reference/cli/get-block) | getBlock command | | [`tevm get-block-number`](/reference/cli/get-block-number) | getBlockNumber command | | [`tevm get-bytecode`](/reference/cli/get-bytecode) | getBytecode command | | [`tevm get-chain-id`](/reference/cli/get-chain-id) | getChainId command | | [`tevm get-ens-address`](/reference/cli/get-ens-address) | getEnsAddress command | | [`tevm get-ens-name`](/reference/cli/get-ens-name) | getEnsName command | | [`tevm get-ens-text`](/reference/cli/get-ens-text) | getEnsText command | | [`tevm get-gas-price`](/reference/cli/get-gas-price) | getGasPrice command | | [`tevm get-storage-at`](/reference/cli/get-storage-at) | getStorageAt command | | [`tevm get-transaction`](/reference/cli/get-transaction) | getTransaction command | | [`tevm load-state`](/reference/cli/load-state) | loadState command | | [`tevm mine`](/reference/cli/mine) | mine command | | [`tevm multicall`](/reference/cli/multicall) | multicall command | | [`tevm read-contract`](/reference/cli/read-contract) | readContract command | | [`tevm action send-raw-transaction`](/reference/cli/send-raw-transaction) | sendRawTransaction command | | [`tevm serve`](/reference/cli/serve) | serve command | | [`tevm set-account`](/reference/cli/set-account) | setAccount command | | [`tevm set-code`](/reference/cli/set-code) | setCode command | | [`tevm set-nonce`](/reference/cli/set-nonce) | setNonce command | | [`tevm set-storage-at`](/reference/cli/set-storage-at) | setStorageAt command | | [`tevm action simulate-calls`](/reference/cli/simulate-calls) | simulateCalls command | The rc.151 `create`, `generate`, and `tsc` entry points are deliberately absent because their advertised non-interactive examples fail in this release. Their exact failures and disposition are recorded in the documentation ledger. ### Neighbours [JSON-RPC](/api/json-rpc) · [Actions](/reference/actions) · [Contract tools](/reference/contract) · [State management](/core/managing-state) ## tevm load-state `tevm load-state` runs this operation: Load saved state into the local EVM. Reach for it when you need the operation from a terminal, CI job, or shell script. ### Working example The commands below were run with `@tevm/cli@1.0.0-rc.151`. They create their own local prerequisites or use the named public endpoint, so no hidden process is required. ```bash npm install --global @tevm/cli@1.0.0-rc.151 tevm session docs --local --json printf '{}\n' > empty-state.json tevm load-state --state-file empty-state.json --session loaded --run --json ``` Output captured from the final command: ```json { "ok": true, "command": "load-state", "result": {}, "session": "loaded" } ``` ### Arguments and flags The command schema in [`cli/src/commands/loadState.tsx`](https://github.com/evmts/tevm/blob/main/cli/src/commands/loadState.tsx) exposes: | Kind | Syntax | Description | | ---- | --------------------------- | --------------------------------------------------------------------------------------- | | Flag | `-r, --run` | Run directly without interactive parameter editing (env: TEVM\_RUN) (default: false) | | Flag | `--rpc [rpc]` | RPC endpoint (env: TEVM\_RPC) (default: [http://localhost:8545](http://localhost:8545)) | | Flag | `--state-file [state-file]` | Path to JSON file containing the TEVM state (env: TEVM\_STATE\_FILE) | | Flag | `--state-json [state-json]` | JSON string containing the TEVM state (env: TEVM\_STATE\_JSON) | | Flag | `--json` | Emit the stable machine-readable JSON envelope (env: TEVM\_JSON) (default: false) | | Flag | `-h, --help` | Show help | `--json` and `--session ` are global options accepted before routing. See the [CLI overview](/reference/cli#global-options) for their environment-variable forms and execution model. ### Neighbours [CLI overview](/reference/cli) · [`tevm get-transaction`](/reference/cli/get-transaction) · [`tevm mine`](/reference/cli/mine) ## tevm mine `tevm mine` runs this operation: Mine blocks in the local EVM. Reach for it when you need the operation from a terminal, CI job, or shell script. ### Working example The commands below were run with `@tevm/cli@1.0.0-rc.151`. They create their own local prerequisites or use the named public endpoint, so no hidden process is required. ```bash npm install --global @tevm/cli@1.0.0-rc.151 tevm session docs --local --json tevm mine --block-count 1 --interval 1 --session docs --run --json ``` Output captured from the final command: ```json { "ok": true, "command": "mine", "result": { "blockHashes": [ "0x258130424acf469c3d93f4ffdbbc803688fae2ee9c601c130272fed478d508fe" ] }, "session": "docs" } ``` ### Arguments and flags The command schema in [`cli/src/commands/mine.tsx`](https://github.com/evmts/tevm/blob/main/cli/src/commands/mine.tsx) exposes: | Kind | Syntax | Description | | ---- | ----------------------------- | --------------------------------------------------------------------------------------- | | Flag | `-r, --run` | Run directly without interactive parameter editing (env: TEVM\_RUN) (default: false) | | Flag | `--rpc [rpc]` | RPC endpoint (env: TEVM\_RPC) (default: [http://localhost:8545](http://localhost:8545)) | | Flag | `--block-count [block-count]` | Number of blocks to mine (env: TEVM\_BLOCK\_COUNT) | | Flag | `--interval [interval]` | Interval between block timestamps in seconds (env: TEVM\_INTERVAL) | | Flag | `--json` | Emit the stable machine-readable JSON envelope (env: TEVM\_JSON) (default: false) | | Flag | `-h, --help` | Show help | `--json` and `--session ` are global options accepted before routing. See the [CLI overview](/reference/cli#global-options) for their environment-variable forms and execution model. ### Neighbours [CLI overview](/reference/cli) · [`tevm load-state`](/reference/cli/load-state) · [`tevm multicall`](/reference/cli/multicall) ## tevm multicall `tevm multicall` runs this operation: Read several contracts in one request. Reach for it when you need the operation from a terminal, CI job, or shell script. ### Working example The commands below were run with `@tevm/cli@1.0.0-rc.151`. They create their own local prerequisites or use the named public endpoint, so no hidden process is required. ```bash npm install --global @tevm/cli@1.0.0-rc.151 tevm session docs --local --json tevm multicall --contracts [] --session docs --run --json ``` Output captured from the final command: ```json { "ok": true, "command": "multicall", "result": [], "session": "docs" } ``` ### Arguments and flags The command schema in [`cli/src/commands/multicall.tsx`](https://github.com/evmts/tevm/blob/main/cli/src/commands/multicall.tsx) exposes: | Kind | Syntax | Description | | ---- | ----------------------------------------- | ------------------------------------------------------------------------------------ | | Flag | `--contracts [contracts]` | Array of contract calls in JSON format (env: TEVM\_CONTRACTS) | | Flag | `--multicall-address [multicall-address]` | Address of the multicall contract (env: TEVM\_MULTICALL\_ADDRESS) | | Flag | `--allow-failure` | Whether to allow calls to fail (env: TEVM\_ALLOW\_FAILURE) (default: false) | | Flag | `--block-tag [block-tag]` | Block tag (latest, pending, etc.) (env: TEVM\_BLOCK\_TAG) | | Flag | `--block-number [block-number]` | Block number to execute at (env: TEVM\_BLOCK\_NUMBER) | | Flag | `-r, --run` | Run directly without interactive parameter editing (env: TEVM\_RUN) (default: false) | | Flag | `--rpc [rpc]` | RPC endpoint (env: TEVM\_RPC) | | Flag | `--json` | Emit the stable machine-readable JSON envelope (env: TEVM\_JSON) (default: false) | | Flag | `-h, --help` | Show help | `--json` and `--session ` are global options accepted before routing. See the [CLI overview](/reference/cli#global-options) for their environment-variable forms and execution model. ### Neighbours [CLI overview](/reference/cli) · [`tevm mine`](/reference/cli/mine) · [`tevm read-contract`](/reference/cli/read-contract) ## tevm read-contract `tevm read-contract` runs this operation: Read a decoded contract function. Reach for it when you need the operation from a terminal, CI job, or shell script. ### Working example The commands below were run with `@tevm/cli@1.0.0-rc.151`. They create their own local prerequisites or use the named public endpoint, so no hidden process is required. ```bash npm install --global @tevm/cli@1.0.0-rc.151 tevm session docs --local --json mkdir -p src cat > src/Counter.sol <<'SOLIDITY' // SPDX-License-Identifier: MIT pragma solidity ^0.8.20; contract Counter { uint256 public number; event NumberChanged(uint256 number); function setNumber(uint256 next) public { number = next; emit NumberChanged(next); } } SOLIDITY tevm compile --json jq '.abi' artifacts/Counter.json > artifacts/Counter.abi.json tevm set-account --address 0x1000000000000000000000000000000000000001 --balance 1000000000000000000 --session docs --run --json tevm set-code --address 0x1000000000000000000000000000000000000001 --bytecode "$(jq -r '.deployedBytecode' artifacts/Counter.json)" --session docs --run --json tevm set-storage-at --address 0x1000000000000000000000000000000000000001 --index 0x0 --value 0x2a --session docs --run --json tevm read-contract --address 0x1000000000000000000000000000000000000001 --abi [{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"number","type":"uint256"}],"name":"NumberChanged","type":"event"},{"inputs":[],"name":"number","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"next","type":"uint256"}],"name":"setNumber","outputs":[],"stateMutability":"nonpayable","type":"function"}] --function-name number --session docs --run --json ``` Output captured from the final command: ```json { "ok": true, "command": "read-contract", "result": "42", "session": "docs" } ``` ### Arguments and flags The command schema in [`cli/src/commands/readContract.tsx`](https://github.com/evmts/tevm/blob/main/cli/src/commands/readContract.tsx) exposes: | Kind | Syntax | Description | | ---- | --------------------------------- | --------------------------------------------------------------------------------------- | | Flag | `--address
` | Contract address (env: TEVM\_ADDRESS) | | Flag | `--abi ` | Contract ABI as JSON string (env: TEVM\_ABI) | | Flag | `--function-name ` | Function name to call (env: TEVM\_FUNCTION\_NAME) | | Flag | `--args [args]` | Function arguments as JSON array (env: TEVM\_ARGS) | | Flag | `-r, --run` | Run directly without interactive parameter editing (env: TEVM\_RUN) (default: false) | | Flag | `--rpc [rpc]` | RPC endpoint (env: TEVM\_RPC) (default: [http://localhost:8545](http://localhost:8545)) | | Flag | `--block-tag [block-tag]` | Block tag (latest, pending, etc.) or number (env: TEVM\_BLOCK\_TAG) | | Flag | `--json` | Emit the stable machine-readable JSON envelope (env: TEVM\_JSON) (default: false) | | Flag | `-h, --help` | Show help | `--json` and `--session ` are global options accepted before routing. See the [CLI overview](/reference/cli#global-options) for their environment-variable forms and execution model. ### Neighbours [CLI overview](/reference/cli) · [`tevm multicall`](/reference/cli/multicall) · [`tevm action send-raw-transaction`](/reference/cli/send-raw-transaction) ## tevm action send-raw-transaction `tevm action send-raw-transaction` runs this operation: Send a signed raw transaction. Reach for it when you need the operation from a terminal, CI job, or shell script. ### Working example The commands below were run with `@tevm/cli@1.0.0-rc.151`. They create their own local prerequisites or use the named public endpoint, so no hidden process is required. ```bash npm install --global @tevm/cli@1.0.0-rc.151 tevm session docs --local --json tevm set-account --address 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 --balance 1000000000000000000 --nonce 0 --session docs --run --json tevm action send-raw-transaction --serialized-transaction 0x02f86c82038480843b9aca0084773594008252089410000000000000000000000000000000000000010180c001a0f449737ed1e3fcc388aeafc1ff3f947808bc8835cb57e97b7b16401d4fa8537ba0517506d8ab807b8253c682173dfda9aed830cb27bad12683a626c8b6aeecc738 --session docs --run --json ``` Output captured from the final command: ```json { "ok": true, "command": "send-raw-transaction", "result": "0xe710a03cd522dd07ce66a31a4a41623eee4dbf47e1f788d68b94f9ad37297e8b", "session": "docs" } ``` ### Arguments and flags The command schema in [`cli/src/commands/action/sendRawTransaction.tsx`](https://github.com/evmts/tevm/blob/main/cli/src/commands/action/sendRawTransaction.tsx) exposes: | Kind | Syntax | Description | | ---- | --------------------------------------------------- | ------------------------------------------------------------------------------------ | | Flag | `--serialized-transaction [serialized-transaction]` | The signed serialized transaction (env: TEVM\_SERIALIZED\_TRANSACTION) | | Flag | `-r, --run` | Run directly without interactive parameter editing (env: TEVM\_RUN) (default: false) | | Flag | `--rpc [rpc]` | RPC endpoint (env: TEVM\_RPC) | | Flag | `--json` | Emit the stable machine-readable JSON envelope (env: TEVM\_JSON) (default: false) | | Flag | `-h, --help` | Show help | `--json` and `--session ` are global options accepted before routing. See the [CLI overview](/reference/cli#global-options) for their environment-variable forms and execution model. ### Neighbours [CLI overview](/reference/cli) · [`tevm read-contract`](/reference/cli/read-contract) · [`tevm serve`](/reference/cli/serve) ## tevm serve `tevm serve` runs this operation: Start a persistent TEVM JSON-RPC server. Reach for it when you need the operation from a terminal, CI job, or shell script. ### Working example The commands below were run with `@tevm/cli@1.0.0-rc.151`. They create their own local prerequisites or use the named public endpoint, so no hidden process is required. ```bash npm install --global @tevm/cli@1.0.0-rc.151 tevm serve --port 9545 --chain-id 900 --json ``` Output captured from the final command: ```text { "ok": true, "command": "serve", "result": { "rpcUrl": "http://localhost:9545", "chainId": "900", "fork": null } } JSON-RPC eth_chainId response: {"id":1,"jsonrpc":"2.0","method":"eth_chainId","result":"0x384"} ``` ### Arguments and flags The command schema in [`cli/src/commands/serve.tsx`](https://github.com/evmts/tevm/blob/main/cli/src/commands/serve.tsx) exposes: | Kind | Syntax | Description | | ---- | ----------------------------------------- | ------------------------------------------------------------ | | Flag | `--port [port]` | Port to listen on (default: 8545) | | Flag | `--host [host]` | Host to bind to (default: localhost) | | Flag | `--fork [fork]` | URL of network to fork | | Flag | `--chain-id [chain-id]` | Use known chain ID (default: 900 (tevm)) | | Flag | `--fork-block-number [fork-block-number]` | Set fork block number (default: latest) | | Flag | `--logging-level [logging-level]` | Set logging level (default: info) | | Flag | `--verbose` | Enable verbose logging of JSON-RPC requests (default: false) | | Flag | `-h, --help` | Show help | `--json` and `--session ` are global options accepted before routing. See the [CLI overview](/reference/cli#global-options) for their environment-variable forms and execution model. ### Neighbours [CLI overview](/reference/cli) · [`tevm action send-raw-transaction`](/reference/cli/send-raw-transaction) · [`tevm set-account`](/reference/cli/set-account) ## tevm set-account `tevm set-account` runs this operation: Mutate a local account balance, nonce, code, or storage. Reach for it when you need the operation from a terminal, CI job, or shell script. ### Working example The commands below were run with `@tevm/cli@1.0.0-rc.151`. They create their own local prerequisites or use the named public endpoint, so no hidden process is required. ```bash npm install --global @tevm/cli@1.0.0-rc.151 tevm session docs --local --json tevm set-account --address 0x1000000000000000000000000000000000000001 --balance 1000000000000000000 --nonce 0 --session docs --run --json ``` Output captured from the final command: ```json { "ok": true, "command": "set-account", "result": {}, "session": "docs" } ``` ### Arguments and flags The command schema in [`cli/src/commands/setAccount.tsx`](https://github.com/evmts/tevm/blob/main/cli/src/commands/setAccount.tsx) exposes: | Kind | Syntax | Description | | ---- | ----------------------------------------- | ---------------------------------------------------------------------------------------------- | | Flag | `--address
` | Ethereum address of the account to set (env: TEVM\_ADDRESS) | | Flag | `-r, --run` | Run directly without interactive parameter editing (env: TEVM\_RUN) (default: false) | | Flag | `--rpc [rpc]` | RPC endpoint (env: TEVM\_RPC) (default: [http://localhost:8545](http://localhost:8545)) | | Flag | `--nonce [nonce]` | Account nonce (env: TEVM\_NONCE) | | Flag | `--balance [balance]` | Account balance in wei (env: TEVM\_BALANCE) | | Flag | `--deployed-bytecode [deployed-bytecode]` | Contract bytecode to set account to (env: TEVM\_DEPLOYED\_BYTECODE) | | Flag | `--storage-root [storage-root]` | Storage root to set account to (env: TEVM\_STORAGE\_ROOT) | | Flag | `--state [state]` | Key-value mapping to override all slots in the account storage (env: TEVM\_STATE) | | Flag | `--state-diff [state-diff]` | Key-value mapping to override individual slots in the account storage (env: TEVM\_STATE\_DIFF) | | Flag | `--json` | Emit the stable machine-readable JSON envelope (env: TEVM\_JSON) (default: false) | | Flag | `-h, --help` | Show help | `--json` and `--session ` are global options accepted before routing. See the [CLI overview](/reference/cli#global-options) for their environment-variable forms and execution model. ### Neighbours [CLI overview](/reference/cli) · [`tevm serve`](/reference/cli/serve) · [`tevm set-code`](/reference/cli/set-code) ## tevm set-code `tevm set-code` runs this operation: Set bytecode at an address in local state. Reach for it when you need the operation from a terminal, CI job, or shell script. ### Working example The commands below were run with `@tevm/cli@1.0.0-rc.151`. They create their own local prerequisites or use the named public endpoint, so no hidden process is required. ```bash npm install --global @tevm/cli@1.0.0-rc.151 tevm session docs --local --json tevm set-code --address 0x1000000000000000000000000000000000000001 --bytecode 0x6080604052348015600e575f5ffd5b50600436106030575f3560e01c80633fb5c1cb1460345780638381f58a146045575b5f5ffd5b6043603f3660046098565b605e565b005b604c5f5481565b60405190815260200160405180910390f35b5f8190556040518181527f2fd81fd19d3c5c4b396dd13f451dafc8bcac1b3094c49c5fa90e68456323f0e39060200160405180910390a150565b5f6020828403121560a7575f5ffd5b503591905056fea26469706673582212203ef1a75b09ee91fb7f995d62885094508a883f40d776c10ba4f1d1427a64bd8b64736f6c63430008230033 --session docs --run --json ``` Output captured from the final command: ```json { "ok": true, "command": "set-code", "result": {}, "session": "docs" } ``` ### Arguments and flags The command schema in [`cli/src/commands/setCode.tsx`](https://github.com/evmts/tevm/blob/main/cli/src/commands/setCode.tsx) exposes: | Kind | Syntax | Description | | ---- | ----------------------- | ------------------------------------------------------------------------------------ | | Flag | `--address [address]` | Contract address to set bytecode for (env: TEVM\_ADDRESS) | | Flag | `--bytecode [bytecode]` | Bytecode to set at the address (env: TEVM\_BYTECODE) | | Flag | `-r, --run` | Run directly without interactive parameter editing (env: TEVM\_RUN) (default: false) | | Flag | `--rpc [rpc]` | RPC endpoint (env: TEVM\_RPC) | | Flag | `--json` | Emit the stable machine-readable JSON envelope (env: TEVM\_JSON) (default: false) | | Flag | `-h, --help` | Show help | `--json` and `--session ` are global options accepted before routing. See the [CLI overview](/reference/cli#global-options) for their environment-variable forms and execution model. ### Neighbours [CLI overview](/reference/cli) · [`tevm set-account`](/reference/cli/set-account) · [`tevm set-nonce`](/reference/cli/set-nonce) ## tevm set-nonce `tevm set-nonce` runs this operation: Set an account nonce in local state. Reach for it when you need the operation from a terminal, CI job, or shell script. ### Working example The commands below were run with `@tevm/cli@1.0.0-rc.151`. They create their own local prerequisites or use the named public endpoint, so no hidden process is required. ```bash npm install --global @tevm/cli@1.0.0-rc.151 tevm session docs --local --json tevm set-nonce --address 0x1000000000000000000000000000000000000001 --nonce 7 --session docs --run --json ``` Output captured from the final command: ```json { "ok": true, "command": "set-nonce", "result": {}, "session": "docs" } ``` ### Arguments and flags The command schema in [`cli/src/commands/setNonce.tsx`](https://github.com/evmts/tevm/blob/main/cli/src/commands/setNonce.tsx) exposes: | Kind | Syntax | Description | | ---- | --------------------- | ------------------------------------------------------------------------------------ | | Flag | `--address [address]` | Account address to set nonce for (env: TEVM\_ADDRESS) | | Flag | `--nonce [nonce]` | Nonce value to set (env: TEVM\_NONCE) | | Flag | `-r, --run` | Run directly without interactive parameter editing (env: TEVM\_RUN) (default: false) | | Flag | `--rpc [rpc]` | RPC endpoint (env: TEVM\_RPC) | | Flag | `--json` | Emit the stable machine-readable JSON envelope (env: TEVM\_JSON) (default: false) | | Flag | `-h, --help` | Show help | `--json` and `--session ` are global options accepted before routing. See the [CLI overview](/reference/cli#global-options) for their environment-variable forms and execution model. ### Neighbours [CLI overview](/reference/cli) · [`tevm set-code`](/reference/cli/set-code) · [`tevm set-storage-at`](/reference/cli/set-storage-at) ## tevm set-storage-at `tevm set-storage-at` runs this operation: Set a contract storage slot in local state. Reach for it when you need the operation from a terminal, CI job, or shell script. ### Working example The commands below were run with `@tevm/cli@1.0.0-rc.151`. They create their own local prerequisites or use the named public endpoint, so no hidden process is required. ```bash npm install --global @tevm/cli@1.0.0-rc.151 tevm session docs --local --json tevm set-storage-at --address 0x1000000000000000000000000000000000000001 --index 0x0 --value 0x2a --session docs --run --json ``` Output captured from the final command: ```json { "ok": true, "command": "set-storage-at", "result": {}, "session": "docs" } ``` ### Arguments and flags The command schema in [`cli/src/commands/setStorageAt.tsx`](https://github.com/evmts/tevm/blob/main/cli/src/commands/setStorageAt.tsx) exposes: | Kind | Syntax | Description | | ---- | --------------------- | ------------------------------------------------------------------------------------ | | Flag | `--address [address]` | Contract address to set storage for (env: TEVM\_ADDRESS) | | Flag | `--index [index]` | Storage slot index (env: TEVM\_INDEX) | | Flag | `--value [value]` | Value to set at the storage slot (env: TEVM\_VALUE) | | Flag | `-r, --run` | Run directly without interactive parameter editing (env: TEVM\_RUN) (default: false) | | Flag | `--rpc [rpc]` | RPC endpoint (env: TEVM\_RPC) | | Flag | `--json` | Emit the stable machine-readable JSON envelope (env: TEVM\_JSON) (default: false) | | Flag | `-h, --help` | Show help | `--json` and `--session ` are global options accepted before routing. See the [CLI overview](/reference/cli#global-options) for their environment-variable forms and execution model. ### Neighbours [CLI overview](/reference/cli) · [`tevm set-nonce`](/reference/cli/set-nonce) · [`tevm action simulate-calls`](/reference/cli/simulate-calls) ## tevm action simulate-calls `tevm action simulate-calls` runs this operation: Simulate a bundle of calls without committing state. Reach for it when you need the operation from a terminal, CI job, or shell script. ### Working example The commands below were run with `@tevm/cli@1.0.0-rc.151`. They create their own local prerequisites or use the named public endpoint, so no hidden process is required. ```bash npm install --global @tevm/cli@1.0.0-rc.151 tevm session docs --local --json tevm set-account --address 0x5a0b54d5dc17e482fe8b0bdca5320161b95fb929 --balance 2000000000000000000 --session docs --run --json tevm action simulate-calls --session docs --run --json ``` Output captured from the final command: ```json { "ok": true, "command": "simulate-calls", "result": { "assetChanges": [], "block": { "number": "1", "hash": "0x0a9c2eca14d1a331a1dbbeb3cf9489977d0d697bca293322001af9ceaacbf4fb", "timestamp": "12", "gasLimit": "30000000", "gasUsed": "0", "baseFeePerGas": "7", "logsBloom": null, "nonce": null, "transactions": [], "totalDifficulty": null }, "results": [ { "data": "0x", "gasUsed": "0", "logs": [], "status": "success", "result": null }, { "data": "0x", "gasUsed": "0", "logs": [], "status": "success", "result": null } ] }, "session": "docs" } ``` ### Arguments and flags The command schema in [`cli/src/commands/action/simulateCalls.tsx`](https://github.com/evmts/tevm/blob/main/cli/src/commands/action/simulateCalls.tsx) exposes: | Kind | Syntax | Description | | ---- | ------------------------------- | ------------------------------------------------------------------------------------ | | Flag | `--account [account]` | Account to simulate calls from (env: TEVM\_ACCOUNT) | | Flag | `--block-number [block-number]` | Block number to simulate at (env: TEVM\_BLOCK\_NUMBER) | | Flag | `--block-tag [block-tag]` | Block tag (latest, pending, etc.) to simulate at (env: TEVM\_BLOCK\_TAG) | | Flag | `--calls [calls]` | Calls as inline JSON or a JSON file path (env: TEVM\_CALLS) | | Flag | `--trace-asset-changes` | Whether to trace asset changes (env: TEVM\_TRACE\_ASSET\_CHANGES) (default: false) | | Flag | `--trace-transfers` | Whether to trace transfers (env: TEVM\_TRACE\_TRANSFERS) (default: false) | | Flag | `--validation` | Whether to enable validation mode (env: TEVM\_VALIDATION) (default: false) | | Flag | `-r, --run` | Run directly without interactive parameter editing (env: TEVM\_RUN) (default: false) | | Flag | `--rpc [rpc]` | RPC endpoint (env: TEVM\_RPC) | | Flag | `--json` | Emit the stable machine-readable JSON envelope (env: TEVM\_JSON) (default: false) | | Flag | `-h, --help` | Show help | `--json` and `--session ` are global options accepted before routing. See the [CLI overview](/reference/cli#global-options) for their environment-variable forms and execution model. ### Neighbours [CLI overview](/reference/cli) · [`tevm set-storage-at`](/reference/cli/set-storage-at) ## Tevm Contract Bundler Import Solidity files directly into TypeScript with type safety and IDE integration. :::note The bundler is optional. You can also generate contract types with `npx tevm gen` (see [Codegen Approach](/reference/bundler/troubleshooting#codegen-approach)). ::: * **[Overview](/reference/bundler/overview)** - Introduction, key benefits, available plugins * **[Internals](/reference/bundler/internals)** - How the bundler works under the hood * **[Methods & Exports](/reference/bundler/methods)** - Key APIs for advanced usage * **[Troubleshooting](/reference/bundler/troubleshooting)** - Common issues and solutions ### What is the Tevm Bundler? At build time, the bundler reads `.sol` files, runs solc on the dependency graph, extracts ABI and (for `.s.sol`) bytecode, and emits a TypeScript module exporting a [Tevm Contract](/reference/contract) instance. For a quickstart, see [Bundler Quickstart](/getting-started/bundler). ## Bundler Internals The public plugin packages share a base bundler. Host-specific plugins adapt file loading and module resolution, while the shared pipeline owns Solidity resolution, compilation, cache keys, and contract-module generation. ### Boundaries * `tevm/bundler/*-plugin` integrates with a host bundler. * `tevm/bundler/base-bundler` coordinates resolution and compilation. * `tevm/bundler/config` loads Tevm compiler configuration. * `tevm/bundler/compiler` and `tevm/bundler/solc` expose lower-level compiler pieces. These low-level entry points are intended for plugin authors. Their asynchronous Effect-based return values and file-access interfaces are not interchangeable with older pre-1.0 helper signatures. Applications should use a supported plugin and import Solidity normally. See [Methods and Exports](./methods) for the stable package entry points. ## Bundler Methods and Exports For application builds, use one of the plugin exports: * `vitePluginTevm` * `rollupPluginTevm` * `esbuildPluginTevm` * `WebpackPluginTevm` * `RspackPluginTevm` * `bunPluginTevm` The main `tevm/bundler` entry point re-exports the public bundler packages. Dedicated subpaths are recommended because they make the host dependency and bundle boundary explicit. Advanced packages are available at: * `tevm/bundler/base-bundler` * `tevm/bundler/compiler` * `tevm/bundler/config` * `tevm/bundler/solc` Use their shipped TypeScript declarations as the rc.151 reference. Older helpers such as `resolveImports`, `generateTevmBody`, and `generateTevmBodyDts` are not public rc.151 exports. See [Bundler Quickstart](../../getting-started/bundler) for configurations that can be copied directly. ## Bundler Overview The Tevm bundler turns a Solidity import into a typed JavaScript module during a normal application build. ### Pipeline 1. A plugin sees a `.sol` or `.s.sol` import. 2. Tevm resolves Solidity imports and remappings. 3. solc compiles the dependency graph. 4. Tevm converts the selected contract output into a contract module. 5. The host bundler includes the generated JavaScript and TypeScript types. The emitted contract object contains the ABI, optional bytecode and deployed bytecode, type-safe `read` and `write` action creators, event helpers, and `withAddress`. ### Plugin Entry Points | Bundler | Entry point | Export | | ------- | ----------------------------- | ------------------- | | Vite | `tevm/bundler/vite-plugin` | `vitePluginTevm` | | Rollup | `tevm/bundler/rollup-plugin` | `rollupPluginTevm` | | esbuild | `tevm/bundler/esbuild-plugin` | `esbuildPluginTevm` | | Webpack | `tevm/bundler/webpack-plugin` | `WebpackPluginTevm` | | rspack | `tevm/bundler/rspack-plugin` | `RspackPluginTevm` | | Bun | `tevm/bundler/bun-plugin` | `bunPluginTevm` | See the [quickstart](../../getting-started/bundler) for executable configuration examples. ### Runtime Independence Generated contracts are compatible with viem-style contract calls. They can be used with a `MemoryClient`, a remote viem client, or any integration that accepts the generated action parameters. The rc.151 package does not export the proposed inline `sol` template tag or a `loadContract` address loader. ### Related [Methods and Exports](./methods) · [Internals](./internals) · [Troubleshooting](./troubleshooting) ## Bundler Troubleshooting ### Common Issues #### 1. Missing or Red Underlines in Editor Solidity imports show red underlines or no auto-completion. * Add `"plugins": [{ "name": "@tevm/ts-plugin" }]` to tsconfig.json. * In VS Code / Cursor, switch to the workspace TypeScript version: Command Palette → "TypeScript: Select TypeScript Version" → "Use Workspace Version". * For Vim/Neovim/other editors, ensure they use the workspace TS version. #### 2. Type-check Errors with Next.js Build works but Next.js typechecking fails on `.sol` imports. Option 1 - disable typechecking in `next.config.mjs`: ```js export default { typescript: { ignoreBuildErrors: true, }, } ``` Option 2 - use the [Codegen Approach](#codegen-approach) (recommended for Next.js). #### 3. "File Not Found" Errors Bundler can't resolve imports. * Check libs and remappings. * For Foundry projects, set `foundryProject: true` in `tevm.config.json`. * For npm packages, verify install and import path. * Add explicit remappings: ```json { "remappings": { "@customlib/": "node_modules/@customlib/", "local/": "./contracts/" } } ``` #### 4. Cache Stale Issues Solidity changes don't take effect. * Delete `.tevm/` and rebuild. * Add `.tevm` to `.gitignore`. #### 5. No Bytecode Available Deployment fails with missing bytecode. * Use the `.s.sol` extension for deployable contracts. Regular `.sol` produces ABI only. #### 6. Deployment Errors Even with bytecode, deployment fails. * Pass constructor args via `.deploy(...)`: ```ts const deployed = await client.deployContract(MyToken.deploy('TokenName', 'TKN', 18)) ``` #### 7. Test Runner Issues `.sol` imports fail in tests. * Most runners (Vitest) work once the plugin is configured. * Use the bundler matching your test environment (esbuild for Vitest, etc.). ### Codegen Approach ```bash npx tevm gen ``` Generates `.ts` files next to each `.sol`. Recommended when bundler hooks are impractical (e.g., Next.js with strict typechecking). ### Additional Resources * [GitHub Issues](https://github.com/evmts/tevm/issues) * [Examples](https://github.com/evmts/tevm/tree/main/examples) * [Next.js example](https://github.com/evmts/tevm/tree/main/examples/next) ### Further Reading * [Bundler Overview](/reference/bundler/overview) * [Bundler Internals](/reference/bundler/internals) * [Methods & Exports](/reference/bundler/methods) ## Tevm Architecture Overview Tevm is an Ethereum execution node embedded in JavaScript. The batteries-included `MemoryClient` presents a viem-compatible API, while a `TevmNode` owns the EVM, state, blockchain, transaction pool, receipts, mining policy, and optional fork connection underneath it. ### The Runtime at a Glance ```text Application, viem action, or EIP-1193 consumer │ MemoryClient (viem public/wallet/test + tevm* actions) │ Tevm transport │ TevmNode ┌───────────────┼────────────────┐ │ │ │ TxPool Mining policy ReceiptsManager │ │ ▲ └──────────► VM / EVM ───────────┘ │ StateManager + Blockchain │ optional fork transport proxy │ upstream JSON-RPC ``` `createMemoryClient()` constructs this stack synchronously. The underlying node initializes lazily; `client.tevmReady()` lets callers eagerly wait for initialization, which is useful for forks. ### MemoryClient and the Transport Boundary `MemoryClient` is a viem client configured with a Tevm transport. It includes: * viem public actions such as `getBlock`, `getBalance`, `getLogs`, and `getTransactionReceipt`; * viem wallet and Anvil-compatible test actions such as `sendTransaction`, `setBalance`, `mine`, `snapshot`, and `revert`; * Tevm actions such as `tevmCall`, `tevmSetAccount`, `tevmDumpState`, and `tevmMine`. Each action becomes an EIP-1193-style request or a direct Tevm action at the transport boundary. The transport routes it to the same `TevmNode`, so viem, Ethers, raw `request`, and Tevm actions observe one chain. ```ts import { createMemoryClient } from 'tevm' const client = createMemoryClient() const blockNumber = await client.getBlockNumber() const chainId = await client.request({ method: 'eth_chainId' }) console.log(blockNumber, chainId) ``` The `request` shape is `{ method, params? }`. JSON-RPC envelope fields such as `id` and `jsonrpc` belong to HTTP serialization, not EIP-1193 calls. ### StateManager and the EVM The `StateManager` owns Ethereum account state: nonce, balance, bytecode, and storage. It supports checkpoints, commits, reverts, state dumps, and fork-backed reads. The EVM executes bytecode against that state. A call can: 1. checkpoint the current state; 2. execute opcodes and precompiles; 3. collect logs, created addresses, gas data, and an optional trace; 4. commit when execution becomes canonical or revert when it is only a simulation. `tevmCall` is a simulation by default. With `addToMempool: true`, Tevm also creates a pending transaction. State only becomes canonical when that transaction is mined. ### TxPool, Mining, Blocks, and Receipts The txpool holds valid pending transactions and orders executable transactions by sender nonce and fees. The configured mining policy decides when a miner drains it: * `{ type: 'manual' }` keeps transactions pending until a mine action. * `{ type: 'auto' }` mines submitted transactions immediately. * `{ type: 'interval', blockTime: seconds }` mines on a timer. During mining, Tevm selects executable transactions, runs each through the VM, commits the resulting state root, builds a canonical block, removes included transactions from the pool, and indexes receipts and logs. This ordering is why a receipt is unavailable before mining and queryable afterward. ```ts import { createMemoryClient, PREFUNDED_ACCOUNTS } from 'tevm' const client = createMemoryClient({ miningConfig: { type: 'manual' }, }) const { txHash } = await client.tevmCall({ from: PREFUNDED_ACCOUNTS[0].address, to: '0x1111111111111111111111111111111111111111', value: 1n, addToMempool: true, }) if (!txHash) throw new Error('transaction was not added to the txpool') const beforeMining = await client.request({ method: 'txpool_status' }) await client.tevmMine({ blockCount: 1 }) const transaction = await client.getTransaction({ hash: txHash }) const receipt = await client.getTransactionReceipt({ hash: txHash }) const block = await client.getBlock({ blockHash: receipt.blockHash }) console.log(beforeMining.pending, transaction.blockNumber, receipt.status, block.number) ``` Tevm exposes two deliberately different mining parameter shapes: * Tevm action: `client.tevmMine({ blockCount: 2, interval: 1 })` * viem test action: `client.mine({ blocks: 2, interval: 1 })` The receipt manager stores receipts by block and transaction hash and provides the log index used by `eth_getLogs` and viem's `getLogs`. ### The Forking Proxy A fork does not download the entire remote chain. It keeps a local overlay and asks the upstream transport for missing data: 1. the local blockchain resolves the fork block and older remote blocks through the transport; 2. the state manager fetches missing accounts, code, and storage at the fork block; 3. fetched values are cached locally; 4. local writes, pending transactions, and mined blocks live in the overlay and never modify the upstream chain. ```ts import { createMemoryClient, http } from 'tevm' import { mainnet } from 'tevm/common' const client = createMemoryClient({ common: mainnet, fork: { transport: http('https://eth.drpc.org')({}), blockTag: 20_000_000n, }, }) await client.tevmReady() const remoteBalance = await client.getBalance({ address: '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045', blockNumber: 20_000_000n, }) await client.setBalance({ address: '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045', value: remoteBalance + 1n, }) ``` Setting `common` avoids a chain-ID discovery request. Pin `blockTag` in repeatable tests; omit it when the latest upstream state is intentional. ### Low-Level Access `TevmNode` is the ownership boundary for the runtime. Advanced integrations can inspect its components directly: ```ts import { createTevmNode } from 'tevm' const node = createTevmNode() await node.ready() const vm = await node.getVm() const txPool = await node.getTxPool() const receipts = await node.getReceiptsManager() const head = await vm.blockchain.getCanonicalHeadBlock() console.log(head.header.number, txPool.pool.size, receipts.GET_LOGS_LIMIT) ``` Prefer `MemoryClient` for application code. Low-level components use Ethereum-native byte arrays, address objects, typed transactions, and explicit checkpoint rules; they are intended for custom execution tools and Tevm contributors. ### Execution and Data Flow #### Read `getBalance` → viem action → Tevm transport → node handler → state manager → local cache or fork proxy. #### Simulate `tevmCall` → checkpoint → EVM execution → result and optional trace → revert checkpoint. #### Submit and Mine `sendTransaction` or `tevmCall({ addToMempool: true })` → txpool → mining policy → VM execution → state commit → block → receipt and log indexes. #### Query History `getBlock`, `getTransactionReceipt`, or `getLogs` → local blockchain and receipt indexes, falling back to the upstream transport only for fork history that is not local. ### Where to Go Next * [Create a Tevm Node](../core/create-tevm-node) * [Mining Modes](../core/mining-modes) * [Forking](../core/forking) * [Managing State](../core/managing-state) * [Receipts and Logs](../advanced/receipts-and-logs) * [Transaction Pool](../advanced/txpool) ### What is Tevm Node? :::tip[Ethereum in JavaScript] Tevm Node is a complete Ethereum execution environment for JavaScript, backed by `@evmts/zevm` execution primitives and exposed through viem-compatible APIs. It runs in-memory in any JS environment with no native client binary, and includes buildtime tooling for importing EVM contracts into TypeScript. ::: Conceptually similar to Anvil/Hardhat but with more powerful TypeScript-native interop. Tevm is backed by ZEVM packages but is not the native ZEVM CLI client — see [Runtime Model and ZEVM](../core/runtime-model) and the [ZEVM docs](https://zevm.sh/docs). :::tip[You might already know most of the Tevm API!] If you know `viem` or `ethers`, you can use Tevm Node immediately — Tevm extends your library of choice. ::: ### What Makes Tevm Unique? * **Cross-Platform Compatibility** — Same code works everywhere JavaScript runs, including the browser, with zero native dependencies * **Fine-grained EVM Control** — Access execution at any level, from high-level transactions to individual opcodes and debug traces * **Enhanced User Experience** — Instantaneous gas estimation, optimistic UI, fork-backed reads, account impersonation, transaction simulation * **Type-safe Interactions** — Full TypeScript across the API, powered by `abitype` * **Direct Solidity Imports** — Write Solidity that interops with TypeScript via the [Tevm Bundler](/getting-started/bundler) * **Development Node Compatibility** — `tevm_*`, `eth_*`, `debug_*`, `txpool_*`, `engine_*`, `anvil_*`, `hardhat_*`, `ganache_*`, `evm_*` JSON-RPC methods ### Universal JavaScript Compatibility Runs in every JavaScript runtime: * **Node.js** — local dev, testing, CI/CD * **Browser** — advanced dApps with offline capability and real-time simulation * **Any JS Runtime** — Deno, Bun, Edge Functions, or any modern JS environment ### Integration With Popular Libraries Tevm works with `viem`, `wagmi`, and `ethers`: :::code-group ```ts [viem] import { createMemoryClient, http } from "tevm"; const client = createMemoryClient(); const balance = await client.getBalance({ address: "0x..." }); const blockNumber = await client.getBlockNumber(); await client.tevmMine({ blockCount: 1 }); await client.tevmSetAccount({ address: "0x...", balance: 100000000000000000n, }); ``` ```ts [ethers] import { createMemoryClient } from "tevm"; import { requestEip1193 } from "tevm/decorators"; import { BrowserProvider, Wallet } from "ethers"; const client = createMemoryClient(); client.transport.tevm.extend(requestEip1193()); const provider = new BrowserProvider(client.transport.tevm); const signer = Wallet.createRandom().connect(provider); const blockNumber = await provider.getBlockNumber(); // Don't forget to mine after transactions await client.mine({ blocks: 1 }); ``` ::: ### 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 | Library | Support Level | Notes | | ---------------------------------------------- | ------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | | [**viem**](../getting-started/viem.mdx) | Native | First-class native integration with all viem features | | [**ethers.js**](../getting-started/ethers.mdx) | 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 | | [**ZEVM**](https://zevm.sh/docs) | Native | Tevm's VM, transaction, receipt, txpool, common, RLP, trie, and utility facades are backed by `@evmts/zevm` packages | | Legacy low-level consumers | Compatible | Several Tevm low-level APIs keep familiar shapes for migration, but new docs and integrations should target Tevm and ZEVM-backed packages | | Any EIP-1193 library | Full | Standard provider interface | Next: [Why JS?](./why-run-ethereum-in-js) · [Architecture Overview](./architecture-overview) · [Create a Tevm Node](../core/create-tevm-node) ## Why Run An Ethereum Node in JavaScript? > You know what would make solving all these problems trivially easy? If we just were able to use Foundry in the browser That's what [Fucory](https://x.com/fucory) thought the day he started building Tevm — putting the Foundry API in the browser, then growing from there. Tevm's use case is simply TypeScript + EVM. > 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, simulation, and debugging. * **💻 Browser Compatibility** — Enable offline capabilities, optimistic UI, and real-time simulations in dApps. * **🔍 Debug Superpowers** — Step through EVM execution opcode by opcode; inspect memory and stack. * **🛠️ Familiar Developer Experience** — Works with viem, ethers, or any EIP-1193 compatible tool. :::info[Did you know?] Tevm Node is part of a larger ecosystem that includes [Tevm Bundler](https://tevm.sh/bundler) for direct Solidity imports into JavaScript/TypeScript. ::: ### Performance & Efficiency * **⚡ Optimized fork mode** — Benchmarked to outperform Anvil at executing calls in `forked` mode via more efficient storage slot retrieval. * **⚡ Zero network latency** — Local EVM execution eliminates RPC round-trips for near-instant simulations and gas estimation. * **Local-first gas estimation** — No loading spinner, no RPC credits burned. * **🔄 Powerful JS interop** — Simulate multiple transactions, plug directly into the EVM, or write custom contracts in JS. ### Optimistic previews Simulate the user's transaction with `tevmCall` before submitting it to a network. The result includes return data, gas used, logs, and optional traces without changing canonical state: ```typescript import { createMemoryClient, http } from 'tevm' import { mainnet } from 'tevm/common' const client = createMemoryClient({ common: mainnet, fork: { transport: http('https://ethereum-rpc.publicnode.com')({}), blockTag: 20_000_000n, }, }) await client.tevmReady() const preview = await client.tevmCall({ from: '0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266', to: '0x1111111111111111111111111111111111111111', value: 1n, createTrace: true, }) console.log(preview.executionGasUsed, preview.errors) ``` #### Real-World Performance Benefits :::tip[Performance Comparison] Tevm's local execution provides instantaneous gas estimation. ::: Fork-backed reads populate Tevm's local caches, so repeated simulations can reuse account code and storage already fetched from the upstream RPC. ### Enhanced User Experiences JavaScript-based EVM execution enables new categories of dApp features: * **Maximally hackable** — Complete control including deep internals; supports almost any use case. * **⚡ Optimistic UI** — Show users the likely outcome of transactions before they're mined. * **🛡️ Reliable** — Near 100% test coverage; most reported bugs fixed in under 24 hours. * **🧮 Transaction Simulation** — Preview results of complex interactions before sending. * **🔐 Enhanced Privacy** — Process sensitive data locally without sending it to external services. ### Top Tier Devx #### Use the tools you already know Tevm plugs directly into `wagmi`, `viem`, and `ethers`. #### Interop with contracts effortlessly The **Tevm Bundler** (optional) makes TypeScript aware of how to process and compile Solidity. It's in the same category as `Wagmi CLI` or `Typechain`, but more powerful: * Natspec on hover * Typesafe contracts * tRPC-like experience — red underlines before you save the Solidity file * No external build tools — plugs into your existing JS pipeline * Reads foundry config for remappings and lib ##### Import Solidity directly The bundler has a compiler built in — no precompilation needed: ```typescript import { MyContract } from "./MyContract.sol"; console.log(MyContract.abi); ``` You can import from node\_modules or foundry projects. Tevm supports remappings, lib, and other advanced options. Unlike Foundry, Tevm supports node\_module resolution by default. #### Low level control of the EVM Tools like `anvil` run in a separate process over HTTP. Tevm runs in memory with direct node access — enabling programmability no other tool offers. ##### 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. ```typescript filename="debug-example.ts" 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 EVM execution as it runs. ##### Mock EVM contracts with JavaScript contracts Write contracts in JavaScript. Precompiles are like Foundry cheat codes, but instead of a standard library you write arbitrary JS. Works nicely with the Tevm Bundler: ```typescript import { definePrecompile, createContract, createMemoryClient, } from "tevm"; import { hexToBytes, stringToHex } from "tevm/utils"; const contract = createContract({ address: `0x${"1234".repeat(10)}`, humanReadableAbi: ["function hello() returns (bytes)"], }); const { precompile } = definePrecompile({ contract, call: async () => ({ returnValue: hexToBytes(stringToHex("hello")), executionGasUsed: 200n, }), }); const memoryClient = createMemoryClient({ customPrecompiles: [precompile()], }); ``` #### Deterministic Testing 🧪 Though built for application development, Tevm is great for testing too — fully reproducible environments with complete control over blockchain state, time, and mining. ### Solidity Imports Tevm Bundler (optional) creates the best devx for Solidity files in TypeScript: ```typescript import { MyContract } from "./MyContract.sol"; ``` ### JavaScript Ecosystem Integration :::note[Seamless Integration] Running Ethereum in JavaScript means you can leverage the entire JS ecosystem effortlessly. ::: * **🔤 TypeScript** — Type-safe contract interactions with full IntelliSense * **⚛️ 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** — Millions of packages in the npm registry * **🌐 Web APIs** — Browser storage, WebSockets, service workers, and more ### Ready to Get Started? Next: [Install Tevm](../getting-started/overview) · [Create a Tevm Node](../core/create-tevm-node) · [Run examples](../examples/viem) · [GitHub](https://github.com/evmts/tevm) ## Bundler Quickstart Tevm bundler plugins compile `.sol` imports at build time and generate modules containing ABI, bytecode, and type-safe contract helpers. ### Install ```bash npm install tevm@1.0.0-rc.151 viem ``` The `tevm` package exposes plugin entry points for Vite, Rollup, esbuild, Webpack, rspack, and Bun. ### Vite ```ts import { defineConfig } from 'vite' import { vitePluginTevm } from 'tevm/bundler/vite-plugin' export default defineConfig({ plugins: [vitePluginTevm()], }) ``` ### Rollup ```ts import { rollupPluginTevm } from 'tevm/bundler/rollup-plugin' export default { input: 'src/index.ts', plugins: [rollupPluginTevm()], } ``` ### esbuild ```ts import { build } from 'esbuild' import { esbuildPluginTevm } from 'tevm/bundler/esbuild-plugin' await build({ entryPoints: ['src/index.ts'], bundle: true, outfile: 'dist/index.js', plugins: [esbuildPluginTevm()], }) ``` ### Webpack ```ts import { WebpackPluginTevm } from 'tevm/bundler/webpack-plugin' export default { plugins: [new WebpackPluginTevm()], } ``` The Webpack export is the `WebpackPluginTevm` constructor with an uppercase `W`. ### Import a Contract Given: ```solidity // src/Counter.sol pragma solidity ^0.8.20; contract Counter { uint256 public number; function setNumber(uint256 next) public { number = next; } } ``` Import the generated contract module: ```ts import { Counter } from './Counter.sol' import { createMemoryClient } from 'tevm' const client = createMemoryClient() const counter = Counter.withAddress( '0x2222222222222222222222222222222222222222', ) await client.setCode({ address: counter.address, bytecode: counter.deployedBytecode, }) const number = await client.readContract(counter.read.number()) console.log(number) ``` `.s.sol` script contracts include creation bytecode. Plain `.sol` imports always provide ABI helpers and provide bytecode when the compiler output includes it. ### Supported rc.151 Surface The rc.151 bundler supports filesystem Solidity imports and the package plugin entry points above. It does not export the proposed `sol` template tag or `loadContract`/CAIP-10 contract loader APIs. ### Related [Bundler Overview](../reference/bundler/overview) · [Plugin Reference](../reference/bundler-plugins) · [Troubleshooting](../reference/bundler/troubleshooting) ## Getting Started with Ethers.js Tevm's primary client surface is viem-compatible. Ethers v6 can use the same in-memory node through its EIP-1193 provider interface. ### Install :::code-group ```bash [npm] npm install tevm@1.0.0-rc.151 viem ethers@6 ``` ```bash [pnpm] pnpm add tevm@1.0.0-rc.151 viem ethers@6 ``` ```bash [yarn] yarn add tevm@1.0.0-rc.151 viem ethers@6 ``` ```bash [bun] bun add tevm@1.0.0-rc.151 viem ethers@6 ``` ::: ### Create a Provider `createMemoryClient()` is synchronous. Its `request` method follows EIP-1193. Pass the client directly to ethers; Tevm preserves typed RPC return values while also satisfying ethers' open-ended provider interface: ```ts import { createMemoryClient, getAddress } from 'tevm' import { BrowserProvider, Wallet, formatEther, parseEther } from 'ethers' const client = createMemoryClient() await client.tevmReady() const provider = new BrowserProvider(client, undefined, { cacheTimeout: -1, }) const signer = Wallet.createRandom().connect(provider) await client.setBalance({ address: getAddress(signer.address), value: parseEther('10'), }) console.log(formatEther(await provider.getBalance(signer.address))) ``` The negative cache timeout keeps ethers from briefly returning a cached block or balance after Tevm changes local state. ### Transactions and Mining Ethers transactions enter Tevm's txpool. With the default manual mining mode, mine before waiting for the receipt: ```ts const tx = await signer.sendTransaction({ to: '0x1111111111111111111111111111111111111111', value: parseEther('1'), }) await client.mine({ blocks: 1 }) const receipt = await tx.wait() console.log(receipt?.status) ``` `client.mine({ blocks: 1 })` is the viem test action. The equivalent Tevm action is `client.tevmMine({ blockCount: 1 })`. See [Using with Ethers](/examples/ethers) for a complete contract deployment and write example. ## Getting Started These docs target `tevm@1.0.0-rc.151`. ### Install :::code-group ```bash [npm] npm install tevm@1.0.0-rc.151 viem ``` ```bash [pnpm] pnpm add tevm@1.0.0-rc.151 viem ``` ```bash [yarn] yarn add tevm@1.0.0-rc.151 viem ``` ```bash [bun] bun add tevm@1.0.0-rc.151 viem ``` ::: Tevm re-exports the viem helpers used by the examples. Install `viem` separately only when your application imports directly from `viem`. ### Run a Local Transaction ```ts import { createMemoryClient, parseEther, PREFUNDED_ACCOUNTS, } from 'tevm' const client = createMemoryClient({ miningConfig: { type: 'manual' }, }) const sender = PREFUNDED_ACCOUNTS[0].address const recipient = '0x1111111111111111111111111111111111111111' const { txHash } = await client.tevmCall({ from: sender, to: recipient, value: parseEther('1'), addToMempool: true, }) if (!txHash) throw new Error('transaction was not added to the txpool') await client.tevmMine({ blockCount: 1 }) const receipt = await client.getTransactionReceipt({ hash: txHash }) const balance = await client.getBalance({ address: recipient }) console.log(receipt.status, balance) ``` `createMemoryClient()` is synchronous. The first action initializes the node lazily. Use `await client.tevmReady()` when initialization itself should finish before a measurement or forked read. ### What Just Happened? 1. `createMemoryClient` created an in-process Ethereum chain and a viem-compatible client. 2. `tevmCall({ addToMempool: true })` executed the transfer and added its transaction to the txpool. 3. `tevmMine({ blockCount: 1 })` built a canonical block. 4. viem actions read the receipt and final balance. Without `addToMempool`, `tevmCall` is a simulation and does not change canonical state. ### Install Contract Code Use viem test actions to prepare state and public actions to query it. ```ts import { createMemoryClient } from 'tevm' import { SimpleContract } from 'tevm/contract' const client = createMemoryClient() const contract = SimpleContract.withAddress( '0x2222222222222222222222222222222222222222', ) await client.setCode({ address: contract.address, bytecode: contract.deployedBytecode, }) const value = await client.readContract({ address: contract.address, abi: contract.abi, functionName: 'get', }) console.log(value) ``` ### Fork an Existing Chain The fork transport must be an EIP-1193 request function. Invoke the viem HTTP transport factory with `({})` when passing it directly. ```ts import { createMemoryClient, http } from 'tevm' import { mainnet } from 'tevm/common' const client = createMemoryClient({ common: mainnet, fork: { transport: http('https://ethereum-rpc.publicnode.com')({}), blockTag: 20_000_000n, }, }) await client.tevmReady() const balance = await client.getBalance({ address: '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045', blockNumber: 20_000_000n, }) console.log(balance) ``` Pin `blockTag` for reproducible tests. Local writes are stored in an overlay and never sent upstream. ### Choose an API Surface * Use [MemoryClient with viem](./viem) for most apps and tests. * Use [Ethers](./ethers) through the EIP-1193 provider surface. * Use [TevmNode](../core/tevm-node-interface) for low-level runtime integrations. * Use [the bundler](./bundler) to import Solidity files into TypeScript. Next: [Architecture Overview](../introduction/architecture-overview) · [Mining Modes](../core/mining-modes) · [Local Testing](../examples/local-testing) ## Community Here's what developers and industry leaders are saying about Tevm. ### Community Highlights :::tip[Developer Feedback] Tevm's approach of bringing Ethereum execution directly to JavaScript environments has resonated with developers. They report problems previously difficult being simple to solve with Tevm. ::: > "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 :::steps #### Join the Community * [Telegram Group](https://t.me/+ANThR9bHDLAwMjUx) * [Twitter/X](https://twitter.com/tevmtools) #### Report Success Stories * [Create an issue](https://github.com/evmts/tevm/issues/new?labels=testimonial\&template=testimonial.md) with the "testimonial" label * Email [support@tevm.sh](mailto\:support@tevm.sh) ::: Your feedback helps us improve Tevm and guides our development priorities. ## Getting Started with Viem `createMemoryClient` is a viem client backed by an in-process Tevm node. It includes viem public, wallet, and Anvil-compatible test actions plus Tevm-specific actions. ### Install ```bash npm install tevm@1.0.0-rc.151 viem ``` ### Batteries-Included Client ```ts import { createMemoryClient } from 'tevm' const client = createMemoryClient() const chainId = await client.getChainId() const block = await client.getBlock({ blockTag: 'latest' }) const balance = await client.getBalance({ address: '0x1111111111111111111111111111111111111111', }) console.log(chainId, block.number, balance) ``` Client construction is synchronous. `await client.tevmReady()` is optional for local clients and useful before the first forked read. ### Public, Wallet, Test, and Tevm Actions ```ts import { createMemoryClient, PREFUNDED_ACCOUNTS } from 'tevm' const client = createMemoryClient({ account: PREFUNDED_ACCOUNTS[0], miningConfig: { type: 'manual' }, }) // viem test action await client.setBalance({ address: PREFUNDED_ACCOUNTS[0].address, value: 10n ** 18n, }) // viem wallet action const hash = await client.sendTransaction({ to: '0x1111111111111111111111111111111111111111', value: 1n, }) // viem test action await client.mine({ blocks: 1 }) // viem public action const receipt = await client.getTransactionReceipt({ hash }) // Tevm action const account = await client.tevmGetAccount({ address: '0x1111111111111111111111111111111111111111', }) console.log(receipt.status, account.balance) ``` The viem mine action uses `{ blocks }`. The Tevm equivalent uses `client.tevmMine({ blockCount })`. ### Call a Contract ```ts import { createMemoryClient } from 'tevm' import { SimpleContract } from 'tevm/contract' const client = createMemoryClient() const contract = SimpleContract.withAddress( '0x2222222222222222222222222222222222222222', ) await client.setCode({ address: contract.address, bytecode: contract.deployedBytecode, }) const value = await client.readContract({ address: contract.address, abi: contract.abi, functionName: 'get', }) const simulation = await client.tevmContract({ to: contract.address, abi: contract.abi, functionName: 'get', }) console.log(value, simulation.data) ``` Use viem contract actions for familiar reads and writes. Use `tevmContract` when a call needs Tevm-only options such as opcode hooks, state overrides, `createTrace`, or `createAccessList`. ### Fork Through a Viem Transport ```ts import { createMemoryClient, http } from 'tevm' import { optimism } from 'tevm/common' const client = createMemoryClient({ common: optimism, fork: { transport: http('https://mainnet.optimism.io')({}), blockTag: 130_000_000n, }, }) await client.tevmReady() console.log(await client.getBlockNumber()) ``` The value passed as `fork.transport` is an EIP-1193 request function, so invoke `http(url)` with `({})`. ### Tree-Shakable Client For smaller application bundles, construct a plain viem client with the Tevm transport and import actions individually. ```ts import { createTevmTransport, tevmCall, tevmDumpState, } from 'tevm' import { createClient } from 'viem' import { getBlockNumber } from 'viem/actions' const client = createClient({ transport: createTevmTransport(), }) const blockNumber = await getBlockNumber(client) const call = await tevmCall(client, { deployedBytecode: '0x6001600055', createTrace: true, }) const state = await tevmDumpState(client) console.log(blockNumber, call.executionGasUsed, state.state) ``` Standalone Tevm action functions come from `tevm`; `tevm/actions` contains lower-level handler factories and types. ### Raw EIP-1193 Requests The transport also supports the EIP-1193 request shape: ```ts import { createMemoryClient } from 'tevm' const client = createMemoryClient() const chainId = await client.request({ method: 'eth_chainId' }) const balance = await client.request({ method: 'eth_getBalance', params: ['0x1111111111111111111111111111111111111111', 'latest'], }) console.log(chainId, balance) ``` Do not add JSON-RPC envelope fields (`id` and `jsonrpc`) to `request`. ### Related * [Viem Examples](../examples/viem) * [Call API](../api/tevm-call) * [Mining Modes](../core/mining-modes) * [Managing State](../core/managing-state) ## Building a Debugger UI This Svelte example runs a real EVM call in the browser and renders its opcode, stack, gas, and trace data. It uses the public `MemoryClient` call API from `tevm@1.0.0-rc.151`; it does not depend on internal VM event emitters. ### Create the App ```bash npm create vite@latest tevm-debugger -- --template svelte-ts cd tevm-debugger npm install npm install tevm@1.0.0-rc.151 viem ``` Replace `src/App.svelte` with the component below. ### Debugger Component ```svelte Tevm Debugger

Tevm EVM Debugger

Execution gas used: {gasUsed.toString()}

{#if error}
{error}
{/if} {#each steps as step} {/each}
PCOpcodeGas leftDepthStack
{step.pc} {step.opcode} {step.gasLeft.toString()} {step.depth} {step.stack.map((value) => `0x${value.toString(16)}`).join(', ') || 'none'}
``` The call executes three instructions, so the table should show `PUSH1`, `PUSH1`, and `SSTORE`. `Array.from(step.stack)` copies each live interpreter stack into stable display data. ### Use the Returned Trace The same call can return a serializable Geth-style trace. It contains `pc`, `op`, `gas`, `gasCost`, `depth`, and stack values for each instruction. ```ts import { createMemoryClient, PREFUNDED_ACCOUNTS } from 'tevm' const client = createMemoryClient() const contract = '0x4444444444444444444444444444444444444444' await client.tevmSetAccount({ address: contract, deployedBytecode: '0x6001600055', }) const result = await client.tevmCall({ from: PREFUNDED_ACCOUNTS[0].address, to: contract, createTrace: true, }) for (const step of result.trace?.structLogs ?? []) { console.log(step.pc, step.op, step.gas, step.stack) } ``` Use the callback for a live UI and the returned trace for export, filtering, comparisons, or persistence. Always call `next?.()` from a callback so execution can continue. ### Next Steps * Add a source map from bytecode offsets to Solidity locations. * Group trace steps by `depth` to visualize nested calls. * Display `step.memory` from the live callback when building a memory inspector. * Persist traces as JSON after converting bigint fields to strings. See [EVM Events](../api/evm-events), [Call API](../api/tevm-call), and [Performance Profiling](../advanced/performance-profiler) for the underlying APIs. ## Using with Ethers.js v6 Tevm works with Ethers.js through Tevm's EIP-1193 provider interface. Use Tevm for local chain control, state setup, and mining; use ethers for providers, wallets, and contract instances. ### Install :::code-group ```bash [npm] npm install tevm@1.0.0-rc.151 viem ethers@6 ``` ```bash [pnpm] pnpm add tevm@1.0.0-rc.151 viem ethers@6 ``` ```bash [yarn] yarn add tevm@1.0.0-rc.151 viem ethers@6 ``` ```bash [bun] bun add tevm@1.0.0-rc.151 viem ethers@6 ``` ::: ### Create a Provider Create a memory client and pass its EIP-1193 provider interface directly to ethers. ```ts import { createMemoryClient } from 'tevm' import { BrowserProvider } from 'ethers' const client = createMemoryClient() await client.tevmReady() const provider = new BrowserProvider(client, undefined, { // Ethers caches JSON-RPC reads briefly by default. Disable for // deterministic local tests where you manually mine blocks. cacheTimeout: -1, }) console.log(`Connected to block ${await provider.getBlockNumber()}`) ``` ### Fund a Wallet ```ts import { getAddress } from 'tevm' import { Wallet, formatEther, parseEther } from 'ethers' const signer = Wallet.createRandom().connect(provider) await client.setBalance({ address: getAddress(signer.address), value: parseEther('10') }) const balance = await provider.getBalance(signer.address) console.log(`Wallet balance: ${formatEther(balance)} ETH`) ``` ### Deploy and Call a Contract Deploys a small compiled counter contract, mines the deployment, then calls it through an ethers `Contract` instance. ```ts import { ContractFactory } from 'ethers' const counterAbi = [ 'function number() view returns (uint256)', 'function increment() public', ] as const const counterBytecode = '0x608060405234801561001057600080fd5b5060f78061001f6000396000f3fe6080604052348015600f57600080fd5b5060043610603c5760003560e01c80633fb5c1cb1460415780638381f58a146053578063d09de08a14606d575b600080fd5b6051604c3660046083565b600055565b005b605b60005481565b60405190815260200160405180910390f35b6051600080549080607c83609b565b9190505550565b600060208284031215609457600080fd5b5035919050565b60006001820160ba57634e487b7160e01b600052601160045260246000fd5b506001019056fea2646970667358221220d5fb46adf6ce0cfd90fa4324ffd8c48b0fc6fb6c4cac9ca2c69c97e25f355c9d64736f6c63430008110033' const factory = new ContractFactory(counterAbi, counterBytecode, signer) const deployment = await factory.deploy() await client.mine({ blocks: 1 }) const counter = await deployment.waitForDeployment() console.log(`Counter deployed at ${await counter.getAddress()}`) console.log(`Initial count: ${await counter.getFunction('number')()}`) ``` ### Send a Transaction Transactions sent by ethers go through `eth_sendRawTransaction` and enter Tevm's mempool. Mine a block before waiting for the receipt. ```ts const tx = await counter.getFunction('increment')() await client.mine({ blocks: 1 }) await tx.wait() console.log(`Updated count: ${await counter.getFunction('number')()}`) ``` ### Complete Example ```ts filename="ethers-with-tevm.ts" import { createMemoryClient, getAddress } from 'tevm' import { BrowserProvider, ContractFactory, Wallet, formatEther, parseEther } from 'ethers' const client = createMemoryClient() await client.tevmReady() const provider = new BrowserProvider(client, undefined, { cacheTimeout: -1 }) const signer = Wallet.createRandom().connect(provider) await client.setBalance({ address: getAddress(signer.address), value: parseEther('10') }) console.log(`Wallet balance: ${formatEther(await provider.getBalance(signer.address))} ETH`) const counterAbi = [ 'function number() view returns (uint256)', 'function increment() public', ] as const const counterBytecode = '0x608060405234801561001057600080fd5b5060f78061001f6000396000f3fe6080604052348015600f57600080fd5b5060043610603c5760003560e01c80633fb5c1cb1460415780638381f58a146053578063d09de08a14606d575b600080fd5b6051604c3660046083565b600055565b005b605b60005481565b60405190815260200160405180910390f35b6051600080549080607c83609b565b9190505550565b600060208284031215609457600080fd5b5035919050565b60006001820160ba57634e487b7160e01b600052601160045260246000fd5b506001019056fea2646970667358221220d5fb46adf6ce0cfd90fa4324ffd8c48b0fc6fb6c4cac9ca2c69c97e25f355c9d64736f6c63430008110033' const factory = new ContractFactory(counterAbi, counterBytecode, signer) const deployment = await factory.deploy() await client.mine({ blocks: 1 }) const counter = await deployment.waitForDeployment() console.log(`Counter deployed at ${await counter.getAddress()}`) console.log(`Initial count: ${await counter.getFunction('number')()}`) const tx = await counter.getFunction('increment')() await client.mine({ blocks: 1 }) await tx.wait() console.log(`Updated count: ${await counter.getFunction('number')()}`) ``` ### Notes * Use `client.setBalance()`, `client.setStorageAt()`, `client.mine()`, and other Tevm test actions to control the local chain. * Use ethers providers, wallets, factories, and contracts for application code that already depends on ethers. * Tevm does not mine ethers transactions until you call `client.mine()` unless you configure automining. ## Forking Mainnet Example :::tip Set `MAINNET_RPC_URL` to a mainnet RPC endpoint before running these examples. ::: ### Basic Fork Setup Unknown accounts/contracts fetch from the remote on demand and cache locally. ```ts import { createTevmNode, http } from 'tevm' const rpcUrl = process.env.MAINNET_RPC_URL if (!rpcUrl) throw new Error('MAINNET_RPC_URL is required') const node = createTevmNode({ fork: { transport: http(rpcUrl)({}), }, loggingLevel: 'debug', }) await node.ready() ``` ### Account Impersonation ```ts import { callHandler } from 'tevm/actions' const result = await callHandler(node)({ from: '0x28C6c06298d514Db089934071355E5743bf21d60', to: '0x1234567890123456789012345678901234567890', value: 1000000000000000000n, // 1 ETH skipBalance: true, throwOnFail: false, }) ``` ### Working with Forked Contracts ```ts import { callHandler } from 'tevm/actions' import { encodeFunctionData, parseAbi } from 'viem' const USDC_ADDRESS = '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48' const HOLDER_ADDRESS = '0x47ac0fb4f2d84898e4d9e7b4dab3c24507a6d503' const RECIPIENT_ADDRESS = '0x1234567890123456789012345678901234567890' const ERC20_ABI = parseAbi([ 'function balanceOf(address) view returns (uint256)', 'function transfer(address to, uint256 amount) returns (bool)', ]) const balance = await callHandler(node)({ to: USDC_ADDRESS, data: encodeFunctionData({ abi: ERC20_ABI, functionName: 'balanceOf', args: [HOLDER_ADDRESS], }), }) // Simulate a local write; the remote chain is not affected. const transfer = await callHandler(node)({ from: HOLDER_ADDRESS, to: USDC_ADDRESS, data: encodeFunctionData({ abi: ERC20_ABI, functionName: 'transfer', args: [RECIPIENT_ADDRESS, 1n], }), skipBalance: true, throwOnFail: false, }) ``` ### Fork at Specific Block ```ts const node = createTevmNode({ fork: { transport: http(rpcUrl)({}), blockTag: 23_483_670n, }, }) const vm = await node.getVm() const block = await vm.blockchain.getBlock(23_483_670n) ``` ### Multiple Network Support ```ts const optimismNode = createTevmNode({ fork: { transport: http(process.env.OPTIMISM_RPC_URL!)({}) }, }) const arbitrumNode = createTevmNode({ fork: { transport: http(process.env.ARBITRUM_RPC_URL!)({}) }, }) ``` **Related** * [Forking Guide](../core/forking) * [State Management](../core/managing-state) * [JSON-RPC Support](../api/json-rpc) ## Local Testing Tevm runs a deterministic Ethereum chain in the same process as your test runner. The examples below use the viem-compatible `MemoryClient`, which is the recommended testing surface in `tevm@1.0.0-rc.151`. ### Setup ```bash npm install tevm@1.0.0-rc.151 viem npm install --save-dev vitest ``` No RPC server or separate chain process is required. ### Transfer, Mine, and Read a Receipt Tevm actions can simulate a call without changing canonical state. Set `addToMempool: true` to create a pending transaction, then mine it explicitly. ```ts import { createMemoryClient, parseEther, PREFUNDED_ACCOUNTS } from 'tevm' import { expect, test } from 'vitest' test('mines an ETH transfer', async () => { const client = createMemoryClient({ miningConfig: { type: 'manual' }, }) const alice = PREFUNDED_ACCOUNTS[0].address const bob = '0x1111111111111111111111111111111111111111' const { txHash } = await client.tevmCall({ from: alice, to: bob, value: parseEther('1'), addToMempool: true, }) expect(txHash).toBeDefined() if (!txHash) throw new Error('transaction was not added to the txpool') await client.tevmMine({ blockCount: 1 }) const receipt = await client.getTransactionReceipt({ hash: txHash }) expect(receipt.status).toBe('success') expect(await client.getBalance({ address: bob })).toBe(parseEther('1')) }) ``` `createMemoryClient()` is synchronous. Await `client.tevmReady()` only when a test wants to finish initialization eagerly, especially before reading from a fork. ### Test a Contract This example installs Tevm's bundled `SimpleContract` bytecode, writes through viem, mines the pending transaction, and reads the resulting state. ```ts import { createMemoryClient, PREFUNDED_ACCOUNTS } from 'tevm' import { SimpleContract } from 'tevm/contract' import { expect, test } from 'vitest' test('writes and reads contract state', async () => { const client = createMemoryClient({ miningConfig: { type: 'manual' }, }) const contract = SimpleContract.withAddress( '0x2222222222222222222222222222222222222222', ) await client.setCode({ address: contract.address, bytecode: contract.deployedBytecode, }) const hash = await client.writeContract({ account: PREFUNDED_ACCOUNTS[0], address: contract.address, abi: contract.abi, functionName: 'set', args: [42n], }) await client.mine({ blocks: 1 }) await client.waitForTransactionReceipt({ hash }) const value = await client.readContract({ address: contract.address, abi: contract.abi, functionName: 'get', }) expect(value).toBe(42n) }) ``` Notice the two mining APIs: * `client.tevmMine({ blockCount: 1 })` is the Tevm action. * `client.mine({ blocks: 1 })` is viem's Anvil-compatible test action. ### Isolate Tests with Snapshots Use viem test actions to snapshot and restore the complete local chain. ```ts import { createMemoryClient } from 'tevm' import { expect, test } from 'vitest' test('restores a snapshot', async () => { const client = createMemoryClient() const account = '0x3333333333333333333333333333333333333333' const snapshotId = await client.snapshot() await client.setBalance({ address: account, value: 100n }) expect(await client.getBalance({ address: account })).toBe(100n) await client.revert({ id: snapshotId }) expect(await client.getBalance({ address: account })).toBe(0n) }) ``` Create a fresh client per test when possible. Snapshots are useful when setup is expensive or several assertions need the same baseline. ### Control Block Time The viem test actions control the next block without mutating block objects directly. ```ts import { createMemoryClient } from 'tevm' import { expect, test } from 'vitest' test('sets the next block timestamp', async () => { const client = createMemoryClient() const timestamp = 2_000_000_000n await client.setNextBlockTimestamp({ timestamp }) await client.mine({ blocks: 1 }) const block = await client.getBlock({ blockTag: 'latest' }) expect(block.timestamp).toBe(timestamp) }) ``` For automatic interval mining, configure seconds with `miningConfig: { type: 'interval', blockTime: 2 }`. Use manual mining in tests that need deterministic transaction boundaries. ### Inspect Execution `tevmCall` exposes opcode hooks and a Geth-style trace. This is useful for gas assertions and debugger tests. ```ts import { createMemoryClient, PREFUNDED_ACCOUNTS } from 'tevm' import { expect, test } from 'vitest' test('collects an execution trace', async () => { const client = createMemoryClient() const contract = '0x4444444444444444444444444444444444444444' await client.tevmSetAccount({ address: contract, deployedBytecode: '0x6001600055', }) const opcodes: string[] = [] const result = await client.tevmCall({ from: PREFUNDED_ACCOUNTS[0].address, to: contract, createTrace: true, onStep(step, next) { opcodes.push(step.opcode.name) next?.() }, }) expect(result.errors).toBeUndefined() expect(opcodes).toEqual(['PUSH1', 'PUSH1', 'SSTORE']) expect(result.trace?.structLogs).toHaveLength(3) }) ``` ### Use the EIP-1193 Surface The client's `request` method accepts the EIP-1193 shape: `{ method, params? }`. It does not accept a JSON-RPC envelope with `id` or `jsonrpc`. ```ts import { createMemoryClient } from 'tevm' import { expect, test } from 'vitest' test('serves EIP-1193 requests', async () => { const client = createMemoryClient() const chainId = await client.request({ method: 'eth_chainId' }) const blockNumber = await client.request({ method: 'eth_blockNumber' }) expect(chainId).toBe('0x384') expect(blockNumber).toBe('0x0') }) ``` ### Related Topics * [Viem Integration](./viem) * [Mining Modes](../core/mining-modes) * [Call API](../api/tevm-call) * [Receipts and Logs](../advanced/receipts-and-logs) * [Managing State](../core/managing-state) ## Using with Viem Tevm integrates with [viem](https://viem.sh) as a local Ethereum environment with viem's familiar API surface. ### Integration Options Two approaches: :::code-group ```ts [Tree-shakable (Recommended)] // For production frontends — minimize bundle size import { createTevmTransport, tevmDumpState } from 'tevm' import { createClient } from 'viem' import { getBlockNumber } from 'viem/actions' const tevmTransport = createTevmTransport() const client = createClient({ transport: tevmTransport }) // Import viem actions individually await getBlockNumber(client) // Import tevm actions individually await tevmDumpState(client) ``` ```ts [Batteries-included] // All actions pre-attached — convenient for testing import { createMemoryClient } from 'tevm' const client = createMemoryClient() await client.getBlockNumber() await client.tevmDumpState() ``` ::: :::tip The tree-shakable approach enables smaller bundles since only imported actions are included. ::: ### Core Functionality * **Public Actions** — read blockchain state, query contracts, estimate gas ([below](#public-actions)) * **Wallet Actions** — send transactions, sign messages ([below](#wallet-actions)) * **Test Actions** — manipulate state for testing ([below](#test-actions)) * **Tevm Actions** — Tevm-specific EVM extensions ([below](#tevm-actions)) ### Public Actions Use [viem's public actions](https://viem.sh/docs/actions/public/introduction) to read from your local Tevm environment: ```ts import { createMemoryClient } from "tevm"; import { ERC20 } from "tevm/contract"; import { encodeFunctionData, parseAbi } from "viem"; const client = createMemoryClient(); const tokenAddress = "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"; const holderAddress = "0x1234567890123456789012345678901234567890"; const block = await client.getBlock(); console.log(`Block number: ${block.number}`); const balance = await client.getBalance({ address: holderAddress, }); const nonce = await client.getTransactionCount({ address: holderAddress, }); await client.setCode({ address: tokenAddress, bytecode: ERC20.deployedBytecode, }); const result = await client.readContract({ address: tokenAddress, abi: parseAbi(["function balanceOf(address) view returns (uint256)"]), functionName: "balanceOf", args: [holderAddress], }); ``` ### Wallet Actions Tevm supports all [viem wallet actions](https://viem.sh/docs/actions/wallet/introduction) with prefunded accounts: ```ts import { createMemoryClient, PREFUNDED_ACCOUNTS } from "tevm"; import { parseEther } from "viem"; const client = createMemoryClient({ account: PREFUNDED_ACCOUNTS[0], // 10000 ETH miningConfig: { type: "manual" }, }); const hash = await client.sendTransaction({ to: "0x1234567890123456789012345678901234567890", value: parseEther("1"), }); await client.mine({ blocks: 1 }); const receipt = await client.getTransactionReceipt({ hash }); console.log(receipt.status); ```
Working with Custom Accounts ```ts import { createMemoryClient } from "tevm"; import { parseEther } from "viem"; import { privateKeyToAccount } from "viem/accounts"; const account = privateKeyToAccount( "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80", ); const client = createMemoryClient({ account }); await client.setBalance({ address: account.address, value: parseEther("10") }); const hash = await client.sendTransaction({ to: "0x1234567890123456789012345678901234567890", value: parseEther("1"), }); ```
### Test Actions All [viem test actions](https://viem.sh/docs/actions/test/introduction) are supported (Anvil/Hardhat compatible): ```ts import { createMemoryClient } from "tevm"; import { parseEther } from "viem"; const client = createMemoryClient(); await client.mine({ blocks: 5 }); await client.setBalance({ address: "0x1234567890123456789012345678901234567890", value: parseEther("100"), }); await client.setNextBlockTimestamp({ timestamp: 1695311333n }); await client.mine({ blocks: 1 }); // Snapshot and revert const snapshotId = await client.snapshot(); await client.setBalance({ address: "0x1234567890123456789012345678901234567890", value: parseEther("999"), }); await client.revert({ id: snapshotId }); const balance = await client.getBalance({ address: "0x1234567890123456789012345678901234567890", }); ``` ### Tevm Actions Tevm-specific actions for enhanced EVM control. #### Contract Interactions ```ts import { createMemoryClient } from "tevm"; import { ERC20 } from "tevm/contract"; import { encodeFunctionData, parseAbi } from "viem"; const client = createMemoryClient(); const tokenAddress = "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"; const holderAddress = "0x1234567890123456789012345678901234567890"; const result = await client.tevmContract({ abi: parseAbi(["function balanceOf(address) view returns (uint256)"]), to: tokenAddress, deployedBytecode: ERC20.deployedBytecode, functionName: "balanceOf", args: [holderAddress], }); // Low-level call const callResult = await client.tevmCall({ to: tokenAddress, deployedBytecode: ERC20.deployedBytecode, data: encodeFunctionData({ abi: parseAbi(["function balanceOf(address) view returns (uint256)"]), functionName: "balanceOf", args: [holderAddress], }), }); ``` #### Account Management ```ts import { createMemoryClient } from "tevm"; import { parseEther } from "viem"; const client = createMemoryClient(); const account = await client.tevmGetAccount({ address: "0x1234567890123456789012345678901234567890", }); // Set complex account state (EOA or contract) await client.tevmSetAccount({ address: "0xabcdef1234567890abcdef1234567890abcdef12", balance: parseEther("100"), nonce: 5n, deployedBytecode: "0x6080604052348015600e575f80fd5b00", state: { "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000000000002", }, }); // Native ETH await client.tevmDeal({ account: "0x1234567890123456789012345678901234567890", amount: parseEther("10"), }); // ERC20 await client.tevmDeal({ erc20: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", // USDC account: "0x1234567890123456789012345678901234567890", amount: 1000000n, // 1 USDC (6 decimals) }); ``` #### State Management ```ts import { createMemoryClient } from "tevm"; const client = createMemoryClient(); const state = await client.tevmDumpState(); const savedState = await client.tevmDumpState(); await client.setBalance({ address: "0x1234567890123456789012345678901234567890", value: 123456789n, }); await client.tevmLoadState({ state: savedState.state }); await client.tevmMine({ blockCount: 5 }); ``` :::warning `tevmDumpState` / `tevmLoadState` capture the complete VM state including the fork cache — more powerful than regular snapshots. ::: ### Inside the Memory Client A MemoryClient is a viem client with Tevm functionality. Build one from scratch: ```ts import { createTevmTransport } from "tevm"; import { tevmViemActions } from "tevm/memory-client"; import { createClient, publicActions, testActions, walletActions } from "viem"; const rpcUrl = process.env.OPTIMISM_RPC_URL ?? "https://mainnet.optimism.io"; const memoryClient = createClient({ transport: createTevmTransport(), }) .extend(tevmViemActions()) .extend(publicActions) .extend(walletActions) .extend(testActions({ mode: "anvil" })); ``` Key architectural components: 1. **EIP-1193 Compatibility Layer** — standard Ethereum provider interface 2. **In-Memory EVM** — full Ethereum Virtual Machine locally 3. **Viem Integration** — extends viem with EVM-specific capabilities ### Complete Action Reference
Public Actions — Read blockchain state ##### Contract Interactions * [`call`](https://viem.sh/docs/actions/public/call) — Call without sending a transaction * [`readContract`](https://viem.sh/docs/contract/readContract) — Read a constant/view method * [`simulateContract`](https://viem.sh/docs/contract/simulateContract) — Simulate a 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 * [`getBlock`](https://viem.sh/docs/actions/public/getBlock) — Get a block by number or hash * [`getBlockNumber`](https://viem.sh/docs/actions/public/getBlockNumber) — Latest block number * [`getBlockTransactionCount`](https://viem.sh/docs/actions/public/getBlockTransactionCount) — Tx count for a block * [`getTransaction`](https://viem.sh/docs/actions/public/getTransaction) — Tx details by hash * [`getTransactionCount`](https://viem.sh/docs/actions/public/getTransactionCount) — Tx count (nonce) for address * [`getTransactionReceipt`](https://viem.sh/docs/actions/public/getTransactionReceipt) — Receipt by hash * [`waitForTransactionReceipt`](https://viem.sh/docs/actions/public/waitForTransactionReceipt) — Wait for mining ##### Account & Chain * [`getBalance`](https://viem.sh/docs/actions/public/getBalance) — Balance of an address * [`getChainId`](https://viem.sh/docs/actions/public/getChainId) — Chain ID * [`getGasPrice`](https://viem.sh/docs/actions/public/getGasPrice) — Current gas price * [`estimateFeesPerGas`](https://viem.sh/docs/actions/public/estimateFeesPerGas) — Estimate fees per gas unit * [`getStorageAt`](https://viem.sh/docs/actions/public/getStorageAt) — Storage slot value
Test Actions — Manipulate blockchain state ##### Block & Mining * [`mine`](https://viem.sh/docs/actions/test/mine) — Mine blocks * [`setAutomine`](https://viem.sh/docs/actions/test/setAutomine) — Enable/disable automatic mining * [`setIntervalMining`](https://viem.sh/docs/actions/test/setIntervalMining) — Mine at intervals * [`setBlockGasLimit`](https://viem.sh/docs/actions/test/setBlockGasLimit) — Block gas limit * [`setBlockTimestampInterval`](https://viem.sh/docs/actions/test/setBlockTimestampInterval) — Timestamp increment * [`setNextBlockBaseFeePerGas`](https://viem.sh/docs/actions/test/setNextBlockBaseFeePerGas) — Next block base fee * [`setNextBlockTimestamp`](https://viem.sh/docs/actions/test/setNextBlockTimestamp) — Next block timestamp ##### Account & State * [`setBalance`](https://viem.sh/docs/actions/test/setBalance) — Set address balance * [`setCode`](https://viem.sh/docs/actions/test/setCode) — Set contract bytecode * [`setNonce`](https://viem.sh/docs/actions/test/setNonce) — Set nonce * [`setStorageAt`](https://viem.sh/docs/actions/test/setStorageAt) — Set storage slot * [`setCoinbase`](https://viem.sh/docs/actions/test/setCoinbase) — Set miner address * [`setMinGasPrice`](https://viem.sh/docs/actions/test/setMinGasPrice) — Minimum gas price ##### State Management * [`snapshot`](https://viem.sh/docs/actions/test/snapshot) — Snapshot current state * [`revert`](https://viem.sh/docs/actions/test/revert) — Revert to snapshot * [`reset`](https://viem.sh/docs/actions/test/reset) — Reset fork * [`dumpState`](https://viem.sh/docs/actions/test/dumpState) — Export state * [`loadState`](https://viem.sh/docs/actions/test/loadState) — Import state
Wallet Actions — Send transactions, interact with accounts ##### Account Management * [`getAddresses`](https://viem.sh/docs/actions/wallet/getAddresses) — Get available addresses * [`requestAddresses`](https://viem.sh/docs/actions/wallet/requestAddresses) — Request address permission ##### Transaction Operations * [`prepareTransactionRequest`](https://viem.sh/docs/actions/wallet/prepareTransactionRequest) — Prepare tx * [`sendTransaction`](https://viem.sh/docs/actions/wallet/sendTransaction) — Send tx * [`sendRawTransaction`](https://viem.sh/docs/actions/wallet/sendRawTransaction) — Send signed tx * [`signTransaction`](https://viem.sh/docs/actions/wallet/signTransaction) — Sign tx ##### Signing * [`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 * [`addChain`](https://viem.sh/docs/actions/wallet/addChain) — Add a chain * [`switchChain`](https://viem.sh/docs/actions/wallet/switchChain) — Switch chain ##### Permissions & Assets * [`getPermissions`](https://viem.sh/docs/actions/wallet/getPermissions) — Get permissions * [`requestPermissions`](https://viem.sh/docs/actions/wallet/requestPermissions) — Request permissions * [`watchAsset`](https://viem.sh/docs/actions/wallet/watchAsset) — Add a token
Tevm Actions — Enhanced EVM capabilities * `tevmCall` — Low-level EVM call * `tevmContract` — Contract call with detailed EVM info * `tevmDeploy` — Deploy with detailed results * `tevmGetAccount` — Detailed account info * `tevmSetAccount` — Set complex account state * `tevmDeal` — Add native ETH or ERC20 tokens * `tevmDumpState` — Export complete EVM state * `tevmLoadState` — Import complete EVM state * `tevmMine` — Mine blocks with options
### Next Steps * [Using with Ethers.js](/examples/ethers) * [Forking Mainnet](/examples/forking-mainnet) * [Local Testing](/examples/local-testing) * [TevmNode Interface](/core/tevm-node-interface) ## Creating a MemoryClient `createMemoryClient` bootstraps a complete Ethereum execution environment in JavaScript. ### Basic usage ```ts import { createMemoryClient } from "tevm"; const client = createMemoryClient(); // Optional: eagerly finish lazy initialization await client.tevmReady(); ``` ### With configuration ```ts import { createMemoryClient, http } from "tevm"; const rpcUrl = process.env.MAINNET_RPC_URL; if (!rpcUrl) { throw new Error("MAINNET_RPC_URL is required for fork mode"); } const client = createMemoryClient({ fork: { transport: http(rpcUrl)({}) }, miningConfig: { type: "auto" }, loggingLevel: "debug", }); await client.tevmReady(); ``` :::tip All options for `createMemoryClient` also apply to `createTevmNode` and `createTevmTransport`. ::: ### Configuration Options #### Fork Configuration ```ts import { createMemoryClient, http } from "tevm"; const rpcUrl = process.env.MAINNET_RPC_URL; if (!rpcUrl) { throw new Error("MAINNET_RPC_URL is required for fork mode"); } const node = createMemoryClient({ fork: { transport: http(rpcUrl)({}), blockTag: 17_000_000n, // optional }, }); await node.tevmReady(); ``` :::note Forked state is fetched lazily and cached locally. First access is slow, subsequent accesses are fast. ::: #### Mining Configuration ```ts // Auto: mine after each tx const node = createMemoryClient({ miningConfig: { type: "auto" } }); // Interval: mine every N seconds const intervalNode = createMemoryClient({ miningConfig: { type: "interval", blockTime: 12 }, }); ``` #### Chain Configuration ```ts import { createMemoryClient } from "tevm"; import { createCommon } from "tevm/common"; const customNode = createMemoryClient({ common: createCommon({ id: 1337, name: "Local chain", nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 }, rpcUrls: { default: { http: ["http://localhost:8545"] } }, }), }); ``` Or use a preset: ```ts import { createMemoryClient } from "tevm"; import { mainnet, optimism, arbitrum, base } from "tevm/common"; const optimismNode = createMemoryClient({ common: optimism }); ```
Want to add your own network? Add it to `viem/chains` first, then open an issue on the Tevm repo to request inclusion.
#### Logging Configuration ```ts const node = createMemoryClient({ loggingLevel: "debug", // 'fatal' | 'error' | 'warn' | 'info' | 'debug' | 'trace' }); node.logger.debug("Detailed debugging information"); node.logger.info("Informational message"); node.logger.warn("Warning!"); node.logger.error("Error encountered", { details: "Something went wrong" }); ``` #### Custom Precompiles ```ts import { createContract, createMemoryClient, definePrecompile, parseAbi } from "tevm"; const calculatorPrecompile = definePrecompile({ contract: createContract({ abi: parseAbi([ "function add(uint256 a, uint256 b) returns (uint256)", "function subtract(uint256 a, uint256 b) returns (uint256)", ]), address: "0x0000000000000000000000000000000000000100", }), call: async ({ data, gasLimit }) => { return { returnValue: new Uint8Array([0x01]), executionGasUsed: 200n, }; }, }); const node = createMemoryClient({ customPrecompiles: [calculatorPrecompile.precompile()], }); ``` #### Performance Profiling ```ts const node = createMemoryClient({ profiler: true }); await node.tevmReady(); const vm = await node.transport.tevm.getVm(); const performanceLogs = vm.evm.getPerformanceLogs(); ``` ### 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: 'manual' } \| { type: 'auto' } \| { type: 'interval', blockTime: number }` | `{ type: 'manual' }` | Block mining behavior | | `customPrecompiles` | `Precompile[]` | `[]` | Additional precompiled contracts | | `allowUnlimitedContractSize` | `boolean` | `false` | Disables EIP-170 contract size checks | ### Best Practices #### Always pass a `common` when forking * Faster init (no chainId fetch). * Correct hardfork/EIP behavior per chain. Without one, `tevmDefault` is used. ```typescript import { createMemoryClient, http } from "tevm"; import { optimism } from "tevm/common"; const rpcUrl = process.env.OPTIMISM_RPC_URL; if (!rpcUrl) throw new Error("OPTIMISM_RPC_URL is required"); const client = createMemoryClient({ common: optimism, fork: { transport: http(rpcUrl)({}) }, }); const block = await client.getBlock({ blockTag: "latest" }); ``` #### Choose the right mining config Default is manual mining. `auto` mines submitted transactions immediately; `interval` uses `blockTime` in seconds. ```ts const testNode = createMemoryClient({ miningConfig: { type: "auto" } }); const simulationNode = createMemoryClient({ miningConfig: { type: "interval", blockTime: 12 }, }); ``` #### Use debug logging when stuck Tevm produces many debug logs — pipe them through an LLM to triage. ```ts const client = createMemoryClient({ loggingLevel: "debug" }); ``` #### Call `client.tevmReady()` when profiling Otherwise the first action absorbs init time. Tevm init is fast (no sync). ### Next Steps [Runtime Model](./runtime-model) · [Node Interface](./tevm-node-interface) · [Forking](./forking) · [State](./managing-state) · [Custom Precompiles](../advanced/custom-precompiles) ## Forking A Tevm fork reads historical chain data from an upstream EIP-1193 transport and stores local changes in an in-memory overlay. It does not copy the entire remote chain and never writes upstream. ### Create a Reproducible Fork ```ts import { createMemoryClient, http } from 'tevm' import { mainnet } from 'tevm/common' const client = createMemoryClient({ common: mainnet, fork: { transport: http('https://ethereum-rpc.publicnode.com')({}), blockTag: 20_000_000n, }, }) await client.tevmReady() const block = await client.getBlock({ blockNumber: 20_000_000n }) console.log(block.hash) ``` `fork.transport` is an EIP-1193 request function. viem's `http(url)` returns a transport factory, so invoke it with `({})` before passing it to Tevm. Set `common` when the chain is known. This avoids an extra chain-ID request and selects the correct hardfork and chain behavior. Pin `blockTag` for tests; omit it only when following the current upstream head is intended. ### Read Remote State, Write Locally Missing accounts, code, storage, and blocks are fetched lazily and cached. Test actions modify only the overlay. ```ts import { createMemoryClient, http } from 'tevm' import { mainnet } from 'tevm/common' const client = createMemoryClient({ common: mainnet, fork: { transport: http('https://ethereum-rpc.publicnode.com')({}), blockTag: 20_000_000n, }, }) const account = '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045' const remoteBalance = await client.getBalance({ address: account, blockNumber: 20_000_000n, }) await client.setBalance({ address: account, value: remoteBalance + 1n, }) console.log(await client.getBalance({ address: account })) ``` Historical reads at or before the fork block can still resolve remotely. New local blocks, receipts, and state roots are owned by Tevm. :::warning[Arbitrum custom transaction types] Optimism deposit transactions (type `0x7e`) are reconstructed with exact block fidelity. Arbitrum transaction types `0x6a`–`0x6f` are not implemented yet; Tevm throws `UnsupportedForkTransactionError` rather than constructing a block whose transactions differ from upstream. ::: ### Fork Through a Viem Transport The `fork.transport` option accepts the transport object returned by a viem transport factory: ```ts import { createMemoryClient, http } from 'tevm' import { mainnet } from 'tevm/common' const upstream = http('https://ethereum-rpc.publicnode.com')({}) const client = createMemoryClient({ common: mainnet, fork: { transport: upstream, blockTag: 20_000_000n, }, }) await client.tevmReady() console.log(await client.getBlockNumber()) ``` Pass the transport object, not an already-created viem client. ### Test a Fork with Snapshots Snapshots isolate local changes without refetching the fork: ```ts import { createMemoryClient, http } from 'tevm' import { mainnet } from 'tevm/common' const client = createMemoryClient({ common: mainnet, fork: { transport: http('https://ethereum-rpc.publicnode.com')({}), blockTag: 20_000_000n, }, }) const snapshotId = await client.snapshot() await client.setCode({ address: '0x1111111111111111111111111111111111111111', bytecode: '0x6001600055', }) await client.revert({ id: snapshotId }) ``` ### Failure and Cache Behavior * The first uncached read can fail if the upstream transport is unavailable. * Cached fork data and all local state remain usable without another network request. * An invalid `blockTag` fails during initialization or the first read. * rc.151 does not provide an automatic rebase mode. Create a new client when a test needs a different fork block. ### Related [Architecture Overview](../introduction/architecture-overview) · [Managing State](./managing-state) · [Local Testing](../examples/local-testing) ## Managing State Tevm exposes state management via two layers: a low-level `StateManager` and a high-level viem-style client API. ### State Management Approaches :::code-group ```typescript [Raw API] filename="raw-state-manager.ts" import { createTevmNode } from 'tevm' import { createAddress } from 'tevm/address' import { createAccount } from 'tevm/utils' const node = createTevmNode() const vm = await node.getVm() const stateManager = vm.stateManager // Read account state const address = createAddress('0x1234567890123456789012345678901234567890') const account = await stateManager.getAccount(address) if (account) { console.log({ balance: account.balance, nonce: account.nonce, codeHash: account.codeHash, storageRoot: account.storageRoot }) } // Create or update an account await stateManager.putAccount( address, createAccount({ nonce: 0n, balance: 10_000_000n }) ) // Delete an account await stateManager.deleteAccount(address) ``` ```typescript [Client API] filename="client-api.ts" import { createMemoryClient } from 'tevm' const client = createMemoryClient() await client.setBalance({ address: '0x1234567890123456789012345678901234567890', value: 1000000000000000000n }) const balance = await client.getBalance({ address: '0x1234567890123456789012345678901234567890' }) ``` ::: :::tip Raw API gives maximum control; client API is the recommended interface for most users (mirrors viem). ::: ### Contract State Management * Deploy bytecode * Read deployed code * Read/write storage slots * Clear storage or delete contracts :::code-group ```typescript [Raw API] filename="contract-management.ts" import { createAddress } from 'tevm/address' import { hexToBytes } from 'tevm/utils' const address = createAddress('0x1234567890123456789012345678901234567890') // Deploy contract code await stateManager.putCode(address, new Uint8Array([1, 2, 3])) // Read contract code const code = await stateManager.getCode(address) // Read storage slot const slot = hexToBytes('0x0000000000000000000000000000000000000000000000000000000000000000') const value = await stateManager.getStorage(address, slot) // Write storage const key = hexToBytes('0x0000000000000000000000000000000000000000000000000000000000000000') const newValue = hexToBytes('0x0000000000000000000000000000000000000000000000000000000000000001') await stateManager.putStorage(address, key, newValue) // Clear all storage await stateManager.clearStorage(address) ``` ```typescript [Client API] filename="client-contract-management.ts" import { createMemoryClient } from 'tevm' const client = createMemoryClient() const contractAddress = '0x1234567890123456789012345678901234567890' await client.setCode({ address: contractAddress, bytecode: '0x608060405234801561001057600080fd5b50' }) const code = await client.getCode({ address: contractAddress, blockTag: 'latest' }) const result = await client.call({ to: contractAddress, data: '0x70a08231000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266' }) ``` ::: ### Framework Integration You can combine viem/ethers with raw state access. :::code-group ```typescript [Viem] filename="viem-integration.ts" import { createMemoryClient } from 'tevm' const client = createMemoryClient() await client.setBalance({ address: '0x1234567890123456789012345678901234567890', value: 1000000000000000000n }) // Drop down to raw state manager const vm = await client.transport.tevm.getVm() const stateManager = vm.stateManager await stateManager.checkpoint() try { await stateManager.putStorage(address, key, value) await stateManager.commit() } catch (error) { await stateManager.revert() } ``` ```typescript [Ethers] filename="ethers-integration.ts" import { createTevmNode } from 'tevm' import { requestEip1193 } from 'tevm/decorators' import { BrowserProvider } from 'ethers' const node = createTevmNode().extend(requestEip1193()) const provider = new BrowserProvider(node) const balance = await provider.getBalance('0x1234...') const vm = await node.getVm() const stateManager = vm.stateManager ``` ::: :::note `createMemoryClient` implements viem's public actions. The `requestEip1193` decorator makes a Tevm node compatible with Ethers.js providers. ::: ### Advanced Features #### State Checkpoints Atomic changes that can be committed or reverted (transaction-like semantics): ```typescript filename="checkpoints.ts" const stateManager = (await node.getVm()).stateManager await stateManager.checkpoint() try { await stateManager.putAccount(address, account) await stateManager.putStorage(address, key, value) await stateManager.commit() } catch (error) { await stateManager.revert() console.error('State changes reverted:', error) } ``` #### State Persistence Dump and restore canonical state to any storage backend (localStorage, DB, etc.): ```typescript filename="persistence.ts" const state = await stateManager.dumpCanonicalGenesis() localStorage.setItem('tevmState', JSON.stringify(state)) const serialized = localStorage.getItem('tevmState') if (!serialized) throw new Error('No saved Tevm state') const savedState = JSON.parse(serialized) await stateManager.generateCanonicalGenesis(savedState) ``` #### Fork Mode Forked nodes lazy-load and cache state from a remote provider: ```typescript filename="fork-mode.ts" import { createTevmNode, http } from 'tevm' import { createAddress } from 'tevm/address' const rpcUrl = process.env.MAINNET_RPC_URL if (!rpcUrl) { throw new Error('MAINNET_RPC_URL is required for fork mode') } const node = createTevmNode({ fork: { transport: http(rpcUrl)({}) } }) const stateManager = (await node.getVm()).stateManager const address = createAddress('0x1234567890123456789012345678901234567890') // First access fetches from remote const account = await stateManager.getAccount(address) // Subsequent access uses cache const cachedAccount = await stateManager.getAccount(address) ``` ### Best Practices * Handle errors from state operations. * Use `deepCopy` for isolated test scenarios. * Group related changes with checkpoints. :::code-group ```typescript [Error Handling] filename="error-handling.ts" import { createAddress } from 'tevm/address' const address = createAddress('0x1234567890123456789012345678901234567890') try { const account = await stateManager.getAccount(address) if (!account) { console.log('Account does not exist yet') } else { console.log('Balance:', account.balance) } } catch (error) { console.error('State operation failed:', error) } ``` ```typescript [State Isolation] filename="state-isolation.ts" const isolatedState = await stateManager.deepCopy() await isolatedState.putAccount(address, account) // Original stateManager unaffected ``` ```typescript [Atomic Operations] filename="atomic-operations.ts" await stateManager.checkpoint() try { await stateManager.putAccount(address, account) await stateManager.putStorage(address, key, value) await stateManager.commit() } catch (error) { await stateManager.revert() console.error('Transaction reverted:', error) } ``` ::: :::warning Low-level state reads return `undefined` for missing local accounts. High-level actions such as `getAccountHandler` throw by default unless `throwOnFail: false` is set. ::: ### Related Resources [Runtime Model and ZEVM](./runtime-model) · [State Manager API](https://github.com/evmts/tevm/blob/main/packages/state/docs/interfaces/StateManager.md) · [Account Management](../api/account-management) · [Contract Storage](/reference/contract) · [Forking Guide](../core/forking) ## Mining Modes Mining controls when pending transactions become part of the canonical chain. `tevm@1.0.0-rc.151` supports manual, automatic, and interval mining. ### Configure a Mode ```ts import { createMemoryClient } from 'tevm' const manualClient = createMemoryClient({ miningConfig: { type: 'manual' }, }) const autoClient = createMemoryClient({ miningConfig: { type: 'auto' }, }) const intervalClient = createMemoryClient({ miningConfig: { type: 'interval', blockTime: 12, // seconds }, }) ``` * **Manual** keeps submitted transactions in the txpool until a mine action runs. Use it for deterministic tests. * **Auto** mines a block after each submitted transaction. Use it for fast local development. * **Interval** mines on a timer. `blockTime` is measured in seconds; `0` disables the timer while preserving manual mining. Gas-threshold mining is not a supported rc.151 mining mode. ### Submit and Mine Manually ```ts import { createMemoryClient, PREFUNDED_ACCOUNTS } from 'tevm' const client = createMemoryClient({ miningConfig: { type: 'manual' }, }) const { txHash } = await client.tevmCall({ from: PREFUNDED_ACCOUNTS[0].address, to: '0x1111111111111111111111111111111111111111', value: 1n, addToMempool: true, }) if (!txHash) throw new Error('transaction was not added to the txpool') await client.tevmMine({ blockCount: 1, interval: 1 }) const receipt = await client.getTransactionReceipt({ hash: txHash }) console.log(receipt.blockNumber) ``` `interval` on `tevmMine` is the number of seconds added between the timestamps of blocks created by that call. It is separate from the interval mining policy's `blockTime`. ### Tevm and Viem Mining Actions The memory client exposes both APIs: ```ts import { createMemoryClient } from 'tevm' const client = createMemoryClient() // Tevm action await client.tevmMine({ blockCount: 2, interval: 1 }) // viem's Anvil-compatible test action await client.mine({ blocks: 2, interval: 1 }) ``` Do not mix the parameter names: Tevm uses `blockCount`; viem uses `blocks`. ### Change the Policy at Runtime The low-level node owns the current policy and the interval timer. ```ts import { createTevmNode } from 'tevm' const node = createTevmNode({ miningConfig: { type: 'manual' }, }) node.setMiningConfig({ type: 'interval', blockTime: 5 }) node.setMiningConfig({ type: 'auto' }) node.setMiningConfig({ type: 'manual' }) await node.close() ``` Call `node.close()` when an application is finished with an interval-mining node so its timer is stopped. ### Observe Mining The Tevm mine action accepts execution callbacks. Each callback must call `next?.()` to continue. ```ts import { createMemoryClient } from 'tevm' const client = createMemoryClient() const mined: bigint[] = [] await client.tevmMine({ blockCount: 2, onBlock(block, next) { mined.push(block.header.number) next?.() }, }) console.log(mined) ``` For application-level results, prefer viem queries such as `getBlock`, `getTransaction`, `getTransactionReceipt`, and `getLogs` after mining. ### Related [Transaction Pool](../advanced/txpool) · [Receipts and Logs](../advanced/receipts-and-logs) · [Call API](../api/tevm-call) ## Runtime Model and ZEVM Tevm and [ZEVM](https://zevm.sh/docs) share execution primitives but are different products with different public interfaces. * Tevm is a JavaScript-first in-memory node, viem transport, EIP-1193 provider, and package family. * ZEVM is the native Zig client with CLI/runtime docs for trusted mode and light mode. * Tevm docs should describe Tevm APIs first, then link to ZEVM for the native client contract. ### Tevm Runtime Shapes #### Local writable node The default Tevm node is a writable local Ethereum execution environment. It supports local accounts, state mutation, transaction submission, mining controls, snapshots, traces, and the full JSON-RPC method set in the [JSON-RPC Guide](../api/json-rpc#supported-methods). This is the Tevm equivalent of ZEVM's trusted-mode development-node docs, with Tevm's JavaScript APIs and broader compatibility namespaces. Start here: [Creating a Tevm Node](./create-tevm-node) · [Mining Modes](./mining-modes) · [Managing State](./managing-state) · [Local Testing Flow](../examples/local-testing) #### Forked local node Forking is configuration on top of the writable local node, not a separate runtime. Tevm fetches remote state lazily, caches it locally, and stores local writes in an overlay. Start here: [Forking and Reforking](./forking) · [Forking Mainnet](../examples/forking-mainnet) · [Managing State](./managing-state) This matches the boundary in ZEVM's [State Fork and Snapshots](https://zevm.sh/docs/concepts/state-fork-and-snapshots/) docs: the fork source is a read source; local writes belong to the local overlay. #### Optional light-client consensus service Tevm can be configured with an injected consensus service for proof-aware reads. This is not the same as running the native ZEVM light-mode binary. In Tevm, the consensus service affects specific read paths and light-sync status inside a JavaScript node. When `consensus.mode` is `light-client`, these RPC paths use consensus/readiness/proof hooks: * `eth_chainId` * `eth_blockNumber` * `eth_getBalance` * `eth_getCode` * `eth_getStorageAt` * `eth_getTransactionCount` * `tevm_lightSyncStatus` * `zevm_lightSyncStatus` The rest of the Tevm node remains Tevm's JavaScript runtime surface unless the application restricts it. For the native ZEVM light-mode contract (startup checkpoints, selector rules, readiness gating, mode-unsupported error codes), see ZEVM's [Light Mode](https://zevm.sh/docs/concepts/light-mode/) and [Verified Light-Mode Reads](https://zevm.sh/docs/reference/json-rpc/verified-light-mode-reads/) docs. ### ZEVM Docs Cross-Reference ZEVM has a strong docs split that Tevm mirrors through Tevm-specific guides rather than copying native CLI details directly. | ZEVM docs area | Tevm version | | --------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | [Installation](https://zevm.sh/docs/quickstart/installation/) | [Getting Started](../getting-started/overview), [Creating a Tevm Node](./create-tevm-node), and package docs. Tevm installs from npm; native Zig build steps belong to ZEVM. | | [Run Trusted Mode](https://zevm.sh/docs/quickstart/run-trusted-mode/) | [Creating a Tevm Node](./create-tevm-node), [Local Testing Flow](../examples/local-testing), [Mining Modes](./mining-modes). | | [Forked Dev Node](https://zevm.sh/docs/quickstart/forked-dev-node/) | [Forking and Reforking](./forking), [Forking Mainnet](../examples/forking-mainnet). | | [Run Light Mode](https://zevm.sh/docs/quickstart/run-light-mode/) | Tevm's injectable consensus service and `tevm_lightSyncStatus`/`zevm_lightSyncStatus` compatibility docs. Use ZEVM's page for the native CLI light client. | | [Troubleshooting](https://zevm.sh/docs/quickstart/troubleshooting/) | Split by surface: [Bundler Troubleshooting](../reference/bundler/troubleshooting), [Forking and Reforking](./forking), JSON-RPC errors in [JSON-RPC Guide](../api/json-rpc#error-handling). | | [Runtime Modes](https://zevm.sh/docs/concepts/runtime-modes/) | This page. Tevm has local, forked local, and optional injected light-client consensus — not the same CLI mode selector as ZEVM. | | [Trusted Mode](https://zevm.sh/docs/concepts/trusted-mode/) | Tevm's local writable node docs: [Creating a Tevm Node](./create-tevm-node), [Mining Modes](./mining-modes), [Managing State](./managing-state), [Account Management](../api/account-management). | | [Light Mode](https://zevm.sh/docs/concepts/light-mode/) | Tevm's light-client consensus notes on this page plus `tevm_lightSyncStatus` in [JSON-RPC Guide](../api/json-rpc#tevm-and-zevm-compatibility). Use ZEVM docs for full native light-mode operation. | | [State Fork and Snapshots](https://zevm.sh/docs/concepts/state-fork-and-snapshots/) | [Forking and Reforking](./forking), [Managing State](./managing-state), including checkpoint, dump/load, snapshot, and revert flows. | | [Method Support by Mode](https://zevm.sh/docs/concepts/method-support-by-mode/) | [JSON-RPC Guide](../api/json-rpc#supported-methods). Tevm documents every registered method and calls out compatibility stubs/aliases. | | [Architecture and Upstream Ownership](https://zevm.sh/docs/concepts/architecture-and-upstream-ownership/) | [Architecture Overview](../introduction/architecture-overview), [VM and Submodules](../api/vm-and-submodules), and package references explaining which Tevm facades are backed by ZEVM packages. | | [Configuration Reference](https://zevm.sh/docs/reference/configuration/overview/) | [Creating a Tevm Node](./create-tevm-node#complete-configuration-reference), [Forking and Reforking](./forking), [Mining Modes](./mining-modes). Tevm config is JS options, not a ZEVM CLI JSON config. | | [JSON-RPC Overview](https://zevm.sh/docs/reference/json-rpc/overview/) | [JSON-RPC Guide](../api/json-rpc): EIP-1193 usage, error handling, exhaustive method index. | | [Core Reads](https://zevm.sh/docs/reference/json-rpc/core-reads/) | [Methods Overview](../api/methods), [JSON-RPC Guide](../api/json-rpc), and viem-compatible read actions on `createMemoryClient`. | | [Managed Dev Wallet](https://zevm.sh/docs/reference/json-rpc/managed-dev-wallet/) | [Account Management](../api/account-management), [Methods Overview](../api/methods), [JSON-RPC Guide](../api/json-rpc). | | [Simulation](https://zevm.sh/docs/reference/json-rpc/simulation/) | [Call API](../api/tevm-call), [Methods Overview](../api/methods), `eth_call`/`eth_estimateGas` in [JSON-RPC Guide](../api/json-rpc). | | [Transactions and Mining](https://zevm.sh/docs/reference/json-rpc/transactions-and-mining/) | [Mining Modes](./mining-modes), [Transaction Pool](../advanced/txpool), tx methods in [JSON-RPC Guide](../api/json-rpc). | | [Blocks, Receipts, and Logs](https://zevm.sh/docs/reference/json-rpc/blocks-receipts-and-logs/) | [Receipts and Logs](../advanced/receipts-and-logs), [Block reference](../reference/block), block/log methods in [JSON-RPC Guide](../api/json-rpc). | | [ZEVM Controls](https://zevm.sh/docs/reference/json-rpc/dev-controls/) | Control methods in [JSON-RPC Guide](../api/json-rpc#tevm-and-zevm-compatibility), [Account Management](../api/account-management), [Managing State](./managing-state), [Mining Modes](./mining-modes). | | [Unsupported and Deferred](https://zevm.sh/docs/reference/json-rpc/unsupported-and-deferred/) | Tevm does not inherit ZEVM's unsupported list. Tevm supports many debug, filter, subscription, txpool, Engine API, Anvil, Hardhat, Ganache, and EVM compatibility methods ZEVM marks deferred. Source of truth: [JSON-RPC Guide](../api/json-rpc#supported-methods). | ### Compatibility Rules Tevm's canonical custom namespace is `tevm_*`. ZEVM's canonical native namespace is `zevm_*`. Tevm exposes only low-risk `zevm_*` aliases where semantics match. Today that means `zevm_lightSyncStatus` as an alias for `tevm_lightSyncStatus`. Other ZEVM-native control names should not be assumed to work in Tevm unless they appear in [JSON-RPC Guide](../api/json-rpc#supported-methods). When writing Tevm docs: * Use `tevm_*` for Tevm-specific methods. * Mention `zevm_lightSyncStatus` only as a compatibility alias. * Link to [ZEVM docs](https://zevm.sh/docs) for native CLI mode selection, trusted/light mode operation, release metadata, and exact ZEVM JSON-RPC contracts. * Keep Tevm method support grounded in Tevm's registered handler map and JSON-RPC guide. ### Next Steps [Creating a Tevm Node](./create-tevm-node) · [Forking and Reforking](./forking) · [Managing State](./managing-state) · [JSON-RPC Guide](../api/json-rpc) · [ZEVM Docs](https://zevm.sh/docs) ## TevmNode Interface `TevmNode` owns Tevm's stateful runtime. Most applications should use `createMemoryClient`; use the node directly when building decorators, servers, or execution tooling. ### Create and Initialize a Node ```ts import { createTevmNode } from 'tevm' const node = createTevmNode({ miningConfig: { type: 'manual' }, }) console.log(node.mode, node.miningConfig) await node.ready() ``` `createTevmNode()` is synchronous. `ready()` eagerly completes the lazy VM, chain, state, txpool, and receipt initialization. ### Component Access ```ts import { createTevmNode } from 'tevm' const node = createTevmNode() const vm = await node.getVm() const txPool = await node.getTxPool() const receipts = await node.getReceiptsManager() const head = await vm.blockchain.getCanonicalHeadBlock() console.log({ blockNumber: head.header.number, pooledSenders: txPool.pool.size, maximumLogs: receipts.GET_LOGS_LIMIT, }) ``` These objects use low-level Ethereum types. Prefer public actions for normal account, block, transaction, receipt, and log queries. ### Add APIs with Decorators The base node does not expose `request`. Add the EIP-1193 decorator explicitly: ```ts import { createTevmNode } from 'tevm' import { requestEip1193, tevmActions } from 'tevm/decorators' const node = createTevmNode() .extend(tevmActions()) .extend(requestEip1193()) const chainId = await node.request({ method: 'eth_chainId' }) const account = await node.getAccount({ address: '0x1111111111111111111111111111111111111111', }) console.log(chainId, account.balance) ``` Other built-in decorators include `ethActions` and `tevmSend`. Decorators return an extended node and share the original node's state. ### Runtime Controls ```ts import { createTevmNode } from 'tevm' const node = createTevmNode() node.setMiningConfig({ type: 'interval', blockTime: 5 }) node.setNextBlockTimestamp(2_000_000_000n) node.setNextBlockGasLimit(30_000_000n) node.setTracesEnabled(true) node.setAutoImpersonate(true) node.setMiningConfig({ type: 'manual' }) await node.close() ``` `close()` stops interval mining and releases node resources. ### Extend with Application Logic ```ts import { createTevmNode } from 'tevm' const node = createTevmNode().extend((baseNode) => ({ async getHeadNumber() { const vm = await baseNode.getVm() const head = await vm.blockchain.getCanonicalHeadBlock() return head.header.number }, })) console.log(await node.getHeadNumber()) ``` Keep extensions thin and compose existing node methods. Use the handler factories in `tevm/actions` when an extension needs Tevm or JSON-RPC behavior. ### Related [Architecture Overview](../introduction/architecture-overview) · [Memory Client](../reference/memory-client) · [Decorators](../api/decorators) ## Account Management Two actions manage account state: `getAccountHandler` and `setAccountHandler`. ### getAccountHandler Retrieve the current state of an account. #### Parameters ```ts import type { GetAccountParams } from 'tevm' ``` #### Return Type ```ts import type { GetAccountResult } from 'tevm' ``` #### Example ```ts import { createTevmNode } from 'tevm' import { getAccountHandler, setAccountHandler } from 'tevm/actions' import { parseEther } from 'viem' const node = createTevmNode() const address = '0x1234567890123456789012345678901234567890' await setAccountHandler(node)({ address, balance: parseEther('1') }) const account = await getAccountHandler(node)({ address, blockTag: 'latest', returnStorage: true }) console.log('Balance:', account.balance) console.log('Nonce:', account.nonce) if (account.isContract) { console.log('Code:', account.deployedBytecode) console.log('Storage:', account.storage) } ``` ### setAccountHandler Modify account state directly. #### Parameters ```ts import type { SetAccountParams } from 'tevm' ``` #### Return Type ```ts import type { SetAccountResult } from 'tevm' ``` #### Examples ##### Setting Balance ```ts import { setAccountHandler } from 'tevm/actions' await setAccountHandler(node)({ address: '0x...', balance: parseEther('100') }) ``` ##### Deploying Contract Code ```ts await setAccountHandler(node)({ address: contractAddress, deployedBytecode: '0x...', state: { '0x0000...': '0x0000...' } }) ``` ##### Modifying Multiple Properties ```ts await setAccountHandler(node)({ address: '0x...', nonce: 5n, balance: parseEther('10'), state: { [slot1]: value1, [slot2]: value2 } }) ``` ### Best Practices Skip storage fetches unless needed: ```ts const account = await getAccountHandler(node)({ address: '0x...', returnStorage: false // default }) ``` Check existence before modifying: ```ts const account = await getAccountHandler(node)({ address, throwOnFail: false }) if (account.errors) { await setAccountHandler(node)({ address, balance: amount }) } else if (!account.isEmpty) { await setAccountHandler(node)({ address, balance: account.balance + amount }) } ``` By default, `getAccountHandler` throws when an account is missing. Use `throwOnFail: false` when probing for existence. Error handling: ```ts const result = await setAccountHandler(node)({ address: '0x...', balance: newBalance, throwOnFail: false }) if (result.errors) { console.error('Failed to set account:', result.errors) } ``` ### Related Topics * [State Management](../core/managing-state) * [Call API](./tevm-call) * [JSON-RPC Support](./json-rpc) ### See Also * [JSON-RPC API](/api/json-rpc) * [Client Types](#TODO) * [Actions Reference](/reference/actions) * [EIP-1193 Specification](https://eips.ethereum.org/EIPS/eip-1193) * [Ethereum JSON-RPC](https://ethereum.org/en/developers/docs/apis/json-rpc/) ## EVM Events Tevm call actions accept callbacks for live execution inspection. They are useful for debuggers, tracers, profilers, and test assertions. ### Call Events The four callbacks are: * `onStep(step, next)` before each opcode; * `onBeforeMessage(message, next)` before an EVM call frame; * `onAfterMessage(result, next)` after an EVM call frame; * `onNewContract(contract, next)` when execution creates a contract. Callbacks use a middleware continuation. Always call `next?.()` or execution will stop at that callback. ```ts import { bytesToHex, createMemoryClient, PREFUNDED_ACCOUNTS, } from 'tevm' const client = createMemoryClient() const contract = '0x4444444444444444444444444444444444444444' await client.tevmSetAccount({ address: contract, deployedBytecode: '0x6001600055', }) const opcodes: string[] = [] const result = await client.tevmCall({ from: PREFUNDED_ACCOUNTS[0].address, to: contract, createTrace: true, onStep(step, next) { opcodes.push(step.opcode.name) console.log(step.pc, step.gasLeft, Array.from(step.stack)) next?.() }, onBeforeMessage(message, next) { console.log('call', message.to?.toString(), message.value) next?.() }, onAfterMessage(messageResult, next) { console.log( messageResult.execResult.executionGasUsed, bytesToHex(messageResult.execResult.returnValue), ) next?.() }, }) console.log(opcodes, result.executionGasUsed, result.trace?.structLogs) ``` The live `step` object contains interpreter state, including memory and the mutable stack. Copy values with `Array.from(step.stack)` before retaining them in a UI. ### Tree-Shakable Calls The standalone action works with a viem client using a Tevm transport. ```ts import { createTevmTransport, tevmCall } from 'tevm' import { createClient } from 'viem' const client = createClient({ transport: createTevmTransport(), }) const result = await tevmCall(client, { deployedBytecode: '0x6001600055', createTrace: true, }) console.log(result.trace?.structLogs) ``` Standalone Tevm action functions are exported from `tevm`. `tevm/actions` exports lower-level handler factories and types. ### Returned Traces `createTrace: true` adds a Geth-style trace to the call result: ```ts import { createMemoryClient } from 'tevm' const client = createMemoryClient() const result = await client.tevmCall({ deployedBytecode: '0x6001600055', createTrace: true, }) for (const step of result.trace?.structLogs ?? []) { console.log({ pc: step.pc, opcode: step.op, gasLeft: step.gas, gasCost: step.gasCost, depth: step.depth, stack: step.stack, }) } ``` The returned trace is easier to serialize than live interpreter objects. Use callbacks when updates must stream during execution and `result.trace` when post-processing is enough. ### Mining Events `tevmMine` can report each block as it is produced: ```ts import { createMemoryClient } from 'tevm' const client = createMemoryClient() const blockNumbers: bigint[] = [] await client.tevmMine({ blockCount: 2, onBlock(block, next) { blockNumbers.push(block.header.number) next?.() }, }) console.log(blockNumbers) ``` Query canonical results with viem actions such as `getBlock`, `getTransactionReceipt`, and `getLogs`. ### Related * [Call API](./tevm-call) * [Building a Debugger UI](../examples/debugger-ui) * [Performance Profiler](../advanced/performance-profiler) * [Mining Modes](../core/mining-modes) ## JSON-RPC Support Tevm Node provides [EIP-1193](https://eips.ethereum.org/EIPS/eip-1193)-compatible [JSON-RPC](https://ethereum.org/en/developers/docs/apis/json-rpc/) support for integration with Ethereum libraries and tools. ### EIP-1193 Provider ```ts import { createTevmNode } from 'tevm' import { requestEip1193 } from 'tevm/decorators' const node = createTevmNode().extend(requestEip1193()) const blockNum = await node.request({ method: 'eth_blockNumber' }) ``` ### Supported Methods For Tevm's runtime model and the mapping to ZEVM's native trusted/light-mode docs, see [Runtime Model and ZEVM](../core/runtime-model). Native ZEVM has its own mode-gated [JSON-RPC Overview](https://zevm.sh/docs/reference/json-rpc/overview/) and [Verified Light-Mode Reads](https://zevm.sh/docs/reference/json-rpc/verified-light-mode-reads/) contract; the index below is the Tevm source of truth. Engine API methods are only registered when `engineApi` is enabled. `tevm_*`, `hardhat_*`, and `ganache_*` development-control aliases share implementations with matching `anvil_*` methods. `tevm_contract` and `eth_sendUnsignedTransaction` are registered compatibility stubs returning unsupported-method errors. #### Tevm and ZEVM compatibility Native Tevm methods: * `tevm_call` * `tevm_contract` * `tevm_dumpState` * `tevm_getAccount` * `tevm_lightSyncStatus` * `tevm_loadState` * `tevm_mine` * `tevm_miner` * `tevm_setAccount` * `zevm_lightSyncStatus` Tevm aliases for development controls: * `tevm_addBalance` * `tevm_autoImpersonateAccount` * `tevm_deal` * `tevm_dealErc20` * `tevm_dropAllTransactions` * `tevm_dropTransaction` * `tevm_enableTraces` * `tevm_getAutomine` * `tevm_getIntervalMining` * `tevm_impersonateAccount` * `tevm_increaseTime` * `tevm_metadata` * `tevm_mineDetailed` * `tevm_nodeInfo` * `tevm_removeBlockTimestampInterval` * `tevm_removePoolTransactions` * `tevm_reset` * `tevm_revert` * `tevm_setAutomine` * `tevm_setBalance` * `tevm_setBlockGasLimit` * `tevm_setBlockTimestampInterval` * `tevm_setChainId` * `tevm_setCode` * `tevm_setCoinbase` * `tevm_setErc20Allowance` * `tevm_setIntervalMining` * `tevm_setLoggingEnabled` * `tevm_setMinGasPrice` * `tevm_setNextBlockBaseFeePerGas` * `tevm_setNextBlockTimestamp` * `tevm_setNonce` * `tevm_setPrevRandao` * `tevm_setRpcUrl` * `tevm_setStorageAt` * `tevm_setTime` * `tevm_snapshot` * `tevm_stopImpersonatingAccount` #### Ethereum * `eth_accounts` * `eth_blobBaseFee` * `eth_blobGasPrice` * `eth_blockNumber` * `eth_call` * `eth_chainId` * `eth_coinbase` * `eth_createAccessList` * `eth_estimateGas` * `eth_feeHistory` * `eth_gasPrice` * `eth_getBalance` * `eth_getBlockAccessList` * `eth_getBlockByHash` * `eth_getBlockByNumber` * `eth_getBlockReceipts` * `eth_getBlockTransactionCountByHash` * `eth_getBlockTransactionCountByNumber` * `eth_getCode` * `eth_getFilterChanges` * `eth_getFilterLogs` * `eth_getLogs` * `eth_getProof` * `eth_getStorageAt` * `eth_getStorageValues` * `eth_getTransactionByBlockHashAndIndex` * `eth_getTransactionByBlockNumberAndIndex` * `eth_getTransactionByHash` * `eth_getTransactionCount` * `eth_getTransactionReceipt` * `eth_getUncleByBlockHashAndIndex` * `eth_getUncleByBlockNumberAndIndex` * `eth_getUncleCountByBlockHash` * `eth_getUncleCountByBlockNumber` * `eth_getWork` * `eth_hashrate` * `eth_maxPriorityFeePerGas` * `eth_mining` * `eth_newBlockFilter` * `eth_newFilter` * `eth_newPendingTransactionFilter` * `eth_protocolVersion` * `eth_sendRawTransaction` * `eth_sendTransaction` * `eth_sendUnsignedTransaction` * `eth_sign` * `eth_signTransaction` * `eth_simulateV1` * `eth_simulateV2` * `eth_submitHashrate` * `eth_submitWork` * `eth_subscribe` * `eth_syncing` * `eth_uninstallFilter` * `eth_unsubscribe` #### Anvil * `anvil_addBalance` * `anvil_autoImpersonateAccount` * `anvil_deal` * `anvil_dealErc20` * `anvil_dropAllTransactions` * `anvil_dropTransaction` * `anvil_dumpState` * `anvil_enableTraces` * `anvil_getAutomine` * `anvil_getIntervalMining` * `anvil_impersonateAccount` * `anvil_increaseTime` * `anvil_loadState` * `anvil_metadata` * `anvil_mine` * `anvil_mineDetailed` * `anvil_nodeInfo` * `anvil_removeBlockTimestampInterval` * `anvil_removePoolTransactions` * `anvil_reset` * `anvil_revert` * `anvil_setAutomine` * `anvil_setBalance` * `anvil_setBlockGasLimit` * `anvil_setBlockTimestampInterval` * `anvil_setChainId` * `anvil_setCode` * `anvil_setCoinbase` * `anvil_setErc20Allowance` * `anvil_setIntervalMining` * `anvil_setLoggingEnabled` * `anvil_setMinGasPrice` * `anvil_setNextBlockBaseFeePerGas` * `anvil_setNextBlockTimestamp` * `anvil_setNonce` * `anvil_setPrevRandao` * `anvil_setRpcUrl` * `anvil_setStorageAt` * `anvil_setTime` * `anvil_snapshot` * `anvil_stopImpersonatingAccount` #### Hardhat * `hardhat_addBalance` * `hardhat_autoImpersonateAccount` * `hardhat_deal` * `hardhat_dealErc20` * `hardhat_dropAllTransactions` * `hardhat_dropTransaction` * `hardhat_dumpState` * `hardhat_enableTraces` * `hardhat_getAutomine` * `hardhat_getIntervalMining` * `hardhat_impersonateAccount` * `hardhat_increaseTime` * `hardhat_loadState` * `hardhat_metadata` * `hardhat_mine` * `hardhat_mineDetailed` * `hardhat_nodeInfo` * `hardhat_removeBlockTimestampInterval` * `hardhat_removePoolTransactions` * `hardhat_reset` * `hardhat_revert` * `hardhat_setAutomine` * `hardhat_setBalance` * `hardhat_setBlockGasLimit` * `hardhat_setBlockTimestampInterval` * `hardhat_setChainId` * `hardhat_setCode` * `hardhat_setCoinbase` * `hardhat_setErc20Allowance` * `hardhat_setIntervalMining` * `hardhat_setLoggingEnabled` * `hardhat_setMinGasPrice` * `hardhat_setNextBlockBaseFeePerGas` * `hardhat_setNextBlockTimestamp` * `hardhat_setNonce` * `hardhat_setPrevRandao` * `hardhat_setRpcUrl` * `hardhat_setStorageAt` * `hardhat_setTime` * `hardhat_snapshot` * `hardhat_stopImpersonatingAccount` #### Ganache * `ganache_addBalance` * `ganache_autoImpersonateAccount` * `ganache_deal` * `ganache_dealErc20` * `ganache_dropAllTransactions` * `ganache_dropTransaction` * `ganache_dumpState` * `ganache_enableTraces` * `ganache_getAutomine` * `ganache_getIntervalMining` * `ganache_impersonateAccount` * `ganache_increaseTime` * `ganache_loadState` * `ganache_metadata` * `ganache_mine` * `ganache_mineDetailed` * `ganache_nodeInfo` * `ganache_removeBlockTimestampInterval` * `ganache_removePoolTransactions` * `ganache_reset` * `ganache_revert` * `ganache_setAutomine` * `ganache_setBalance` * `ganache_setBlockGasLimit` * `ganache_setBlockTimestampInterval` * `ganache_setChainId` * `ganache_setCode` * `ganache_setCoinbase` * `ganache_setErc20Allowance` * `ganache_setIntervalMining` * `ganache_setLoggingEnabled` * `ganache_setMinGasPrice` * `ganache_setNextBlockBaseFeePerGas` * `ganache_setNextBlockTimestamp` * `ganache_setNonce` * `ganache_setPrevRandao` * `ganache_setRpcUrl` * `ganache_setStorageAt` * `ganache_setTime` * `ganache_snapshot` * `ganache_stopImpersonatingAccount` #### Debug * `debug_dumpBlock` * `debug_getBadBlocks` * `debug_getModifiedAccountsByHash` * `debug_getModifiedAccountsByNumber` * `debug_getRawBlock` * `debug_getRawHeader` * `debug_getRawReceipts` * `debug_getRawTransaction` * `debug_intermediateRoots` * `debug_preimage` * `debug_storageRangeAt` * `debug_traceBlock` * `debug_traceBlockByHash` * `debug_traceBlockByNumber` * `debug_traceCall` * `debug_traceChain` * `debug_traceState` * `debug_traceTransaction` #### EVM test-runner compatibility * `evm_increaseTime` * `evm_mine` * `evm_revert` * `evm_setBlockGasLimit` * `evm_setIntervalMining` * `evm_setNextBlockTimestamp` * `evm_snapshot` #### Engine API * `engine_exchangeCapabilities` * `engine_exchangeTransitionConfigurationV1` * `engine_forkchoiceUpdatedV1` * `engine_forkchoiceUpdatedV2` * `engine_forkchoiceUpdatedV3` * `engine_forkchoiceUpdatedV4` * `engine_getBlobsV1` * `engine_getBlobsV2` * `engine_getBlobsV3` * `engine_getClientVersionV1` * `engine_getPayloadBodiesByHashV1` * `engine_getPayloadBodiesByHashV2` * `engine_getPayloadBodiesByRangeV1` * `engine_getPayloadBodiesByRangeV2` * `engine_getPayloadV1` * `engine_getPayloadV2` * `engine_getPayloadV3` * `engine_getPayloadV4` * `engine_getPayloadV5` * `engine_getPayloadV6` * `engine_newPayloadV1` * `engine_newPayloadV2` * `engine_newPayloadV3` * `engine_newPayloadV4` * `engine_newPayloadV5` * `testing_buildBlockV1` #### Txpool, web3, net, rpc, and miner compatibility * `miner_start` * `miner_stop` * `net_listening` * `net_peerCount` * `net_version` * `rpc_modules` * `txpool_content` * `txpool_contentFrom` * `txpool_inspect` * `txpool_status` * `web3_clientVersion` * `web3_sha3` ### Client Integration #### Viem See [Viem Documentation](https://viem.sh/docs/clients/custom.html). ```ts import { createTevmTransport } from 'tevm' import { mainnet } from 'tevm/common' import { createPublicClient } from 'viem' const tevmTransport = createTevmTransport() const client = createPublicClient({ chain: mainnet, transport: tevmTransport }) ``` #### Ethers See [Ethers Documentation](https://docs.ethers.org/v6/api/providers/#Provider). ```ts import { createMemoryClient } from 'tevm' import { BrowserProvider } from 'ethers' const client = createMemoryClient() const provider = new BrowserProvider(client) ``` ### Error Handling JSON-RPC errors follow the [standard format](https://www.jsonrpc.org/specification#error_object) and are fully typed. See [JsonRpcError type](https://github.com/evmts/tevm/blob/main/packages/actions/docs/type-aliases/JsonRpcError.md): ```ts interface JsonRpcError { code: number message: string data?: unknown } ``` Common codes (see [ErrorCodes](https://github.com/evmts/tevm/blob/main/packages/actions/docs/variables/ErrorCodes.md)): * `-32700`: Parse error ([`ParseError`](https://github.com/evmts/tevm/blob/main/packages/actions/docs/type-aliases/ParseError.md)) * `-32600`: Invalid request ([`InvalidRequest`](https://github.com/evmts/tevm/blob/main/packages/actions/docs/type-aliases/InvalidRequest.md)) * `-32601`: Method not found ([`MethodNotFound`](https://github.com/evmts/tevm/blob/main/packages/actions/docs/type-aliases/MethodNotFound.md)) * `-32602`: Invalid params ([`InvalidParams`](https://github.com/evmts/tevm/blob/main/packages/actions/docs/type-aliases/InvalidParams.md)) * `-32603`: Internal error ([`InternalError`](https://github.com/evmts/tevm/blob/main/packages/actions/docs/type-aliases/InternalError.md)) * `-32000` to `-32099`: Server error ([`ServerError`](https://github.com/evmts/tevm/blob/main/packages/actions/docs/type-aliases/ServerError.md)) See [Error Handling Guide](https://github.com/evmts/tevm/blob/main/packages/actions/docs/variables/ErrorHandling.md). ### Best Practices Wrap RPC calls in try-catch. Estimate gas before sending ([ErrorCodes](https://github.com/evmts/tevm/blob/main/packages/actions/docs/variables/ErrorCodes.md)): ```ts const gasEstimate = await node.request({ method: 'eth_estimateGas', params: [tx] }) ``` Wait for receipts ([ethGetTransactionReceipt](https://github.com/evmts/tevm/blob/main/packages/actions/docs/functions/ethGetTransactionReceipt.md)): ```ts const txHash = await node.request({ method: 'eth_sendTransaction', params: [tx] }) const receipt = await node.request({ method: 'eth_getTransactionReceipt', params: [txHash] }) ``` Filter efficiently: set block ranges, use specific [topics](https://docs.soliditylang.org/en/latest/abi-spec.html#events), clean up with [`eth_uninstallFilter`](https://github.com/evmts/tevm/blob/main/packages/actions/docs/functions/ethUninstallFilterProcedure.md). See: * [Actions Documentation](https://github.com/evmts/tevm/tree/main/packages/actions/docs) * [Type Definitions](https://github.com/evmts/tevm/blob/main/packages/actions/docs/type-aliases) * [Function Reference](https://github.com/evmts/tevm/blob/main/packages/actions/docs/functions) * [Variables and Constants](https://github.com/evmts/tevm/blob/main/packages/actions/docs/variables) ### Related Topics * [Using with Viem](../examples/viem) * [Using with Ethers](../examples/ethers) * [Managing State](../core/managing-state) * [Receipts & Logs](../advanced/receipts-and-logs) * [Ethereum JSON-RPC Specification](https://ethereum.org/en/developers/docs/apis/json-rpc/) * [EIP-1193](https://eips.ethereum.org/EIPS/eip-1193) * [Tevm API Documentation](https://github.com/evmts/tevm/tree/main/packages/actions/docs) ### Using Tevm Actions High-level action functions are exported by `tevm`. Handler factories and parameter/result types are exported by `tevm/actions`. ```ts import { createMemoryClient, tevmCall, tevmMine, tevmGetAccount, tevmSetAccount, } from 'tevm' const client = createMemoryClient() const address = '0x1111111111111111111111111111111111111111' const result = await tevmCall(client, { to: address, value: 0n, }) await tevmMine(client, { blockCount: 1 }) const account = await tevmGetAccount(client, { address, blockTag: 'latest', }) await tevmSetAccount(client, { address, balance: 100n, nonce: 0n, deployedBytecode: '0x', }) ``` Type references: * [`CallParams`](https://github.com/evmts/tevm/blob/main/packages/actions/docs/type-aliases/CallParams.md) * [`MineParams`](https://github.com/evmts/tevm/blob/main/packages/actions/docs/type-aliases/MineParams.md) * [`GetAccountParams`](https://github.com/evmts/tevm/blob/main/packages/actions/docs/type-aliases/GetAccountParams.md) * [`SetAccountParams`](https://github.com/evmts/tevm/blob/main/packages/actions/docs/type-aliases/SetAccountParams.md) * [`AnvilDealParams`](https://github.com/evmts/tevm/blob/main/packages/actions/docs/type-aliases/AnvilDealParams.md) Tevm calls are simulations unless they create a transaction. Use `addToMempool: true` and mine for a receipt, or configure `{ miningConfig: { type: 'auto' } }`. ## Tevm Node Methods Reference for the main API methods on a Tevm Node instance: EVM interaction, state management, execution control. ### Core Methods #### Initialization ```ts import { createTevmNode, http } from 'tevm' const rpcUrl = process.env.MAINNET_RPC_URL if (!rpcUrl) { throw new Error('MAINNET_RPC_URL is required for fork mode') } const node = createTevmNode({ fork: { transport: http(rpcUrl)({}) } }) await node.ready() ``` :::warning Always `await node.ready()` before using the node. ::: #### Virtual Machine ```ts import { createImpersonatedTx } from 'tevm/tx' import { createAddress } from 'tevm/address' const vm = await node.getVm() const tx = createImpersonatedTx({ impersonatedAddress: createAddress('0x1234567890123456789012345678901234567890'), nonce: 0n, gasLimit: 21064n, maxFeePerGas: 8n, maxPriorityFeePerGas: 1n, to: createAddress('0x5678901234567890123456789012345678901234'), value: 1000000000000000000n, // 1 ETH }) const result = await vm.runTx({ tx, skipNonce: true, skipBalance: true }) if (!result.execResult.exceptionError) { console.log('Gas used:', result.totalGasSpent) } ``` :::note The VM interface provides the lowest level of control for executing transactions and inspecting execution. ::: #### Transaction Pool ```ts const txPool = await node.getTxPool() await txPool.add({ from: '0x1234...', to: '0x5678...', value: 1000000000000000000n, }) // Sorted by gas price and nonce const pending = await txPool.txsByPriceAndNonce() // Raw access const allPending = txPool.getPendingTransactions() // Pending nonce for an address const nextNonce = txPool.getPendingNonce('0x1234...') ``` :::tip Pool transactions remain pending until mined. Mining behavior depends on your mining configuration. ::: #### Receipts & Logs ```ts import { hexToBytes } from 'tevm/utils' const receipts = await node.getReceiptsManager() const vm = await node.getVm() const fromBlock = await vm.blockchain.getBlock(0n) const toBlock = fromBlock const receipt = await receipts.getReceiptByTxHash( hexToBytes('0x1234567890123456789012345678901234567890123456789012345678901234'), ) const logs = await receipts.getLogs( fromBlock, toBlock, [hexToBytes('0x1234567890123456789012345678901234567890')], [hexToBytes('0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef')], ) ``` The logs API mirrors Ethereum's JSON-RPC pattern (filter by address, topics, block range). ### State Management #### Account Impersonation ```ts // Impersonate (fork mode only) node.setImpersonatedAccount('0x1234...') const impersonated = node.getImpersonatedAccount() // Stop node.setImpersonatedAccount(undefined) ``` :::warning Impersonation primarily affects the JSON-RPC layer, enabling `eth_sendRawTransaction` to execute as the impersonated account. Works best in fork mode. ::: ##### Strict impersonation (anvil parity) By default Tevm auto-impersonates every sender, so `eth_sendTransaction` succeeds from any address. Anvil instead rejects unknown senders with `No Signer available`. Opt into anvil's behavior with `strictImpersonation`: ```ts import { createTevmNode } from '@tevm/node' const node = createTevmNode({ strictImpersonation: true }) // throws NoSignerAvailableError: No Signer available for 0xd8dA... await node.request({ method: 'eth_sendTransaction', params: [{ from: '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045', to: '0x0000000000000000000000000000000000000001', value: '0x0' }], }) // anvil_impersonateAccount grants access, anvil_stopImpersonatingAccount revokes it again node.setImpersonatedAccount('0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045') ``` Prefunded dev accounts always have a signer, and `anvil_autoImpersonateAccount` still bypasses the check while enabled. The mode can also be toggled at runtime with `node.setStrictImpersonation(true)` and is preserved across `deepCopy` and snapshot/revert. It defaults to `false`, so existing behavior is unchanged. #### Event Filtering ```ts node.setFilter({ id: '0x1', fromBlock: 0n, toBlock: 'latest', address: '0x1234...', topics: [ '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef', // Transfer ], }) const filters = node.getFilters() node.removeFilter('0x1') const logs = await node.request({ method: 'eth_getFilterChanges', params: ['0x1'] }) ``` Topic `0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef` is keccak256 of `Transfer(address,address,uint256)`. ### Node Properties #### Status ```ts console.log(node.status) // 'INITIALIZING' | 'READY' | 'SYNCING' | 'MINING' | 'STOPPED' const waitForReady = async () => { while (node.status !== 'READY') { await new Promise(resolve => setTimeout(resolve, 100)) } } ``` #### Mode ```ts console.log(node.mode) // 'fork' or 'normal' if (node.mode === 'fork') { // fork-specific features like impersonation } else { // local-only features } ``` #### Logger ```ts node.logger.trace('Extremely detailed information') node.logger.debug('Detailed debugging information') node.logger.info('General information') node.logger.warn('Warning messages') node.logger.error('Error information') node.logger.fatal('Critical errors that stop execution') node.logger.info('Transaction processed', { hash: '0x1234...', from: '0x5678...', to: '0x9abc...', value: '1 ETH' }) ``` ### Advanced Actions The `tevm`-prefixed actions provide direct EVM execution with debugging hooks. #### tevmCall Low-level EVM call with execution tracing: ```ts import { encodeFunctionData } from 'viem' import { bytesToHex, createMemoryClient } from 'tevm' const client = createMemoryClient() const result = await client.tevmCall({ to: '0x1234...', data: encodeFunctionData({ abi, functionName: 'myFunction', args: [arg1, arg2] }), onStep: (step, next) => { console.log(`Opcode: ${step.opcode.name}, PC: ${step.pc}`) next?.() }, onNewContract: (data, next) => { console.log(`New contract at: ${data.address.toString()}`) next?.() }, onBeforeMessage: (message, next) => { console.log(`Call to: ${message.to?.toString()}`) next?.() }, onAfterMessage: (result, next) => { console.log(`Return: ${bytesToHex(result.execResult.returnValue)}`) next?.() } }) ``` :::tip `onStep` fires for every EVM instruction, enabling opcode-level tracing. ::: #### tevmContract High-level contract interaction with event monitoring: ```ts import { tevmContract } from 'tevm' import { createMemoryClient } from 'tevm' const client = createMemoryClient() const result = await tevmContract(client, { abi, to: '0x1234567890123456789012345678901234567890', functionName: 'myFunction', args: [arg1, arg2], onStep: (step, next) => { console.log(`Opcode: ${step.opcode.name}, Stack: ${step.stack.length}`) next?.() }, onNewContract: (data, next) => { console.log(`New contract: ${data.address.toString()}`) next?.() } }) ``` #### tevmDeploy Contract deployment with execution monitoring: ```ts import { tevmDeploy } from 'tevm' import { createMemoryClient } from 'tevm' const client = createMemoryClient() const deployResult = await tevmDeploy(client, { abi, bytecode, args: [constructorArg1, constructorArg2], onStep: (step, next) => { console.log(`Executing: ${step.opcode.name}`) next?.() }, onNewContract: (data, next) => { console.log(`Deployed at: ${data.address.toString()}`) next?.() } }) console.log('Deployed:', deployResult.createdAddress) console.log('Gas used:', deployResult.executionGasUsed) ``` Debug use cases: gas profiling, contract testing, security auditing, educational EVM visualizers. ### Extensibility #### Custom Methods ```ts const enhancedNode = node.extend((baseNode) => ({ async getBalance(address: string) { const vm = await baseNode.getVm() const account = await vm.stateManager.getAccount(address) return account.balance }, })) const balance = await enhancedNode.getBalance('0x1234...') ``` :::tip Extension methods have full access to the base node's functionality. ::: #### State Cloning `await node.deepCopy()` creates an independent copy of the node's blockchain, state manager, txpool, and receipt data. State copying is useful for alternative execution paths and expensive test setup. Use the higher-level `client.snapshot()` and `client.revert({ id })` actions when a test only needs to restore one client. ### JSON-RPC Support Tevm Node implements standard Ethereum JSON-RPC methods. #### EIP-1193 Interface ```ts import { requestEip1193 } from 'tevm/decorators' const node = createTevmNode().extend(requestEip1193()) const blockNumber = await node.request({ method: 'eth_blockNumber', params: [] }) const balance = await node.request({ method: 'eth_getBalance', params: ['0x1234...', 'latest'] }) ``` The EIP-1193 interface is compatible with libraries like Ethers.js. #### Action Methods ```ts import { ethActions } from 'tevm/decorators' const node = createTevmNode().extend(ethActions()) const blockNumber = await node.eth.getBlockNumber() const balance = await node.eth.getBalance('0x1234...') const hash = await node.eth.sendTransaction({ from: '0x1234...', to: '0x5678...', value: 1000000000000000000n }) ``` Action methods provide ergonomic TypeScript-typed alternatives to raw JSON-RPC. #### Common JSON-RPC Methods For the exhaustive list, see the [JSON-RPC Guide](./json-rpc#supported-methods). **State Access** * `eth_getBalance` * `eth_getCode` * `eth_getStorageAt` * `eth_getTransactionCount` **Block Methods** * `eth_blockNumber` * `eth_getBlockByHash` * `eth_getBlockByNumber` **Transaction Methods** * `eth_sendTransaction` * `eth_sendRawTransaction` * `eth_getTransactionByHash` * `eth_getTransactionReceipt` **Anvil Methods** * `anvil_impersonateAccount` * `anvil_stopImpersonatingAccount` * `anvil_mine` * `anvil_setBalance` **Tevm Methods** * `tevm_snapshot` * `tevm_revert` * `tevm_mine` * `tevm_setAccount` See [Complete JSON-RPC API](../api/json-rpc). ## Package Reference Tevm Node is modular. These docs target the `1.0.0-rc.151` package set. ### Installation #### Complete Package ```bash npm install tevm@1.0.0-rc.151 viem ``` ```typescript import { createTevmNode } from 'tevm' import { callHandler } from 'tevm/actions' import { http } from 'tevm' ``` #### Individual Packages ```bash npm install @tevm/node@1.0.0-rc.151 @tevm/actions@1.0.0-rc.151 viem ``` ```typescript import { createTevmNode } from '@tevm/node' import { callHandler } from '@tevm/actions' ``` ### Core Packages #### Node & Client * **@tevm/node** - Core node implementation; blockchain and state management; mining and block production. * **@tevm/memory-client** - In-memory Ethereum client with Viem-compatible interface; local state and transaction handling. #### EVM & Execution * **@tevm/vm** - VM coordinating EVM execution, block building, receipts, and state transitions; backed by ZEVM-compatible EVM, tx, common, and block primitives; emits VM/EVM lifecycle events. * **@tevm/evm** - Low-level EVM operations: ZEVM-backed bytecode execution, gas accounting, step events, custom precompiles, profiling, and direct `runCall` access. #### State & Storage * **@tevm/state** - Account state, storage manipulation, fork-backed reads, snapshots, state roots, and proof support. * **@tevm/blockchain** - Block management, chain reorganization, header validation. ### Transaction Handling #### Transaction Processing * **@tevm/tx** - ZEVM-backed transaction facade; legacy, EIP-2930, EIP-1559, EIP-4844, EIP-7702 helpers; Tevm impersonated transactions for local execution and fork testing. * **@tevm/txpool** - Pending transaction queue, ordering, replacement handling, `txpool_*` JSON-RPC support. #### Block & Receipt Management * **@tevm/block** - Block creation, validation, chain management. * **@tevm/receipt-manager** - Receipt storage, event logging, gas tracking; `eth_getTransactionReceipt`, `eth_getBlockReceipts`, filters, subscriptions. ### Client Integration #### Communication * **@tevm/jsonrpc** - Standard Ethereum and custom Tevm methods, error handling; HTTP, WebSocket, rate-limit, and load-balance transports. * **@tevm/http-client** - HTTP client; remote node communication, request batching, error handling. #### Actions & Procedures * **@tevm/actions** - High-level actions for contract interaction, account management, state queries; `eth_*`, `tevm_*`, `debug_*`, `engine_*`, `txpool_*`, `anvil_*`, `hardhat_*`, `ganache_*`, `evm_*` handlers. * **@tevm/procedures** - State manipulation, chain operations, utility functions. ### Smart Contract Tools #### Contract Interaction * **@tevm/contract** - ABI handling, function encoding, event parsing. * **@tevm/precompiles** - Standard and custom precompiles; gas calculation. #### Contract Management * **@tevm/predeploys** - Pre-deployed standard and network-specific contracts. ### Utilities & Helpers #### Core Utilities * **@tevm/utils** - Address handling, data encoding, type conversion; ZEVM-backed utilities and EIP-7702 authorization helpers. * **@tevm/common** - Chain configurations and network parameters; ZEVM-backed Common object plus viem chain definitions. #### Development Tools * **@tevm/decorators** - Function decorators for method extension and behavior modification. * **@tevm/errors** - Error types, messages, stack traces. #### Data Structures * **@tevm/rlp** - ZEVM-backed RLP encoding/decoding for serialization, network protocol, storage. * **@tevm/trie** - ZEVM-backed Merkle Patricia Tree for state storage, proof verification, tree manipulation. ### Development & Debugging #### Logging & Debugging * **@tevm/logger** - Configurable levels, output formatting, debug information. * **@tevm/effect** - Side effect handling, async operations, error recovery. #### Storage & Types * **@tevm/sync-storage-persister** - State synchronization, persistence, cache management. * **@tevm/client-types** - Interface and type definitions. ### Best Practices * **Start simple** - Begin with the complete `tevm` package. Split only to optimize bundle size. * **Bundle optimization** - Import from subpaths (`tevm/actions`) and use tree-shaking-friendly imports. * **Version management** - Keep all `@tevm/*` packages on the same version. * **Development** - Use TypeScript; leverage provided type definitions. ### Related Topics * [Architecture Overview](../introduction/architecture-overview) * [API Reference](./methods) * [GitHub Repository](https://github.com/evmts/tevm) ## Call API The Call API covers \~90% of use cases (with mining) and provides an EVM call interface with extensive configuration. :::warning[Transaction Inclusion] Tevm defaults to manual mining mode: * With `addToMempool: true` (or deprecated `createTransaction: true`), you must call `client.tevmMine()` to include the transaction * `addToBlockchain: true` auto-mines for immediate inclusion * You cannot use both `addToMempool` and `addToBlockchain` ::: ### Basic Usage Two API styles: #### Client-based API ```ts import { createMemoryClient } from 'tevm' const client = createMemoryClient() const result = await client.tevmCall({ from: '0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266', to: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', // WETH data: '0x' }) ``` #### Tree-shakable API ```ts import { createTevmTransport, tevmCall } from 'tevm' import { createClient } from 'viem' const client = createClient({ transport: createTevmTransport() }) const result = await tevmCall(client, { from: '0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266', to: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', // WETH data: '0x' }) ``` ### Parameters ```ts type CallParams = { to?: Address // required except contract deployment data?: Hex value?: bigint // wei gas?: bigint blockTag?: 'latest' | 'pending' | 'earliest' | number createTransaction?: 'on-success' | 'always' | 'never' | boolean // DEPRECATED addToMempool?: 'on-success' | 'always' | 'never' | boolean // requires mining addToBlockchain?: 'on-success' | 'always' | 'never' | boolean // auto-mines skipBalance?: boolean createAccessList?: boolean createTrace?: boolean from?: Address // defaults to first account maxFeePerGas?: bigint maxPriorityFeePerGas?: bigint stateOverrideSet?: StateOverrideSet blockOverrideSet?: BlockOverrideSet onStep?: (data: InterpreterStep, next?: () => void) => void onNewContract?: (data: NewContractEvent, next?: () => void) => void onBeforeMessage?: (data: Message, next?: () => void) => void onAfterMessage?: (data: EVMResult, next?: () => void) => void } ``` ### Return Type ```ts type CallResult = { rawData: Hex // return data executionGasUsed: bigint totalGasSpent?: bigint // includes intrinsic costs txHash?: Hex logs?: Log[] createdAddress?: Address accessList?: Record> trace?: TraceResult errors?: TevmCallError[] } ``` ### Examples #### Simple Contract Call ```ts import { createMemoryClient, PREFUNDED_ACCOUNTS } from 'tevm' import { ERC20 } from 'tevm/contract' import { encodeFunctionData, decodeFunctionResult, parseAbi } from 'viem' const abi = parseAbi(['function balanceOf(address account) view returns (uint256 balance)']) const client = createMemoryClient() const result = await client.tevmCall({ to: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', // WETH from: PREFUNDED_ACCOUNTS[0].address, deployedBytecode: ERC20.deployedBytecode, data: encodeFunctionData({ abi, functionName: 'balanceOf', args: [PREFUNDED_ACCOUNTS[0].address] }) }) const balance = decodeFunctionResult({ abi, functionName: 'balanceOf', data: result.rawData }) ``` #### Contract Deployment ```ts import { createMemoryClient, PREFUNDED_ACCOUNTS } from 'tevm' import { SimpleContract } from 'tevm/contract' import { encodeDeployData } from 'viem' const client = createMemoryClient() const result = await client.tevmCall({ from: PREFUNDED_ACCOUNTS[0].address, data: encodeDeployData(SimpleContract.deploy(2n)), addToBlockchain: true // auto-mines }) console.log('Deployed at:', result.createdAddress) ``` #### State Override ```ts import { createMemoryClient, PREFUNDED_ACCOUNTS } from 'tevm' const client = createMemoryClient() const result = await client.tevmCall({ from: PREFUNDED_ACCOUNTS[0].address, to: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', data: '0x', stateOverrideSet: { [PREFUNDED_ACCOUNTS[0].address]: { balance: 4096n, nonce: 2n, state: {} } } }) ``` #### Debug Trace ```ts import { createMemoryClient } from 'tevm' const client = createMemoryClient() const result = await client.tevmCall({ from: '0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266', to: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', data: '0x', createTrace: true }) if (result.trace) { result.trace.structLogs.forEach(log => { console.log(log.op, log.stack, log.gas, log.gasCost) }) } ``` #### EVM Event Handlers Monitor execution in real-time: ```ts import { bytesToHex, createMemoryClient } from 'tevm' import { encodeFunctionData } from 'viem' const client = createMemoryClient() const result = await client.tevmCall({ from: '0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266', to: contractAddress, data: encodeFunctionData({ abi, functionName: 'myFunction', args: [arg1, arg2] }), onStep: (step, next) => { console.log( `${step.opcode.name} at PC=${step.pc}`, `Gas: ${step.gasLeft.toString()}`, `Stack depth: ${step.stack.length}` ) next?.() }, onNewContract: (data, next) => { console.log(`New contract: ${data.address.toString()}`) next?.() }, onBeforeMessage: (message, next) => { console.log(`Call to: ${message.to?.toString()}`, `Value: ${message.value.toString()}`, `Gas limit: ${message.gasLimit.toString()}`) next?.() }, onAfterMessage: (result, next) => { console.log(`Result: ${bytesToHex(result.execResult.returnValue)}`, `Gas used: ${result.execResult.executionGasUsed.toString()}`) if (result.execResult.exceptionError) { console.error(`Error: ${result.execResult.exceptionError.error}`) } next?.() } }) ``` ### Higher Level APIs While `tevmCall` ## VM & Submodules [Tevm Node](https://github.com/evmts/tevm) is built from submodules usable together as an in-memory Ethereum node or independently. High-level APIs (`createMemoryClient`, viem actions, JSON-RPC) sit on top of these. ### Overview Runtime submodules: 1. **VM** - Coordinates transaction execution, block building, state changes, receipts, event hooks. 2. **EVM** - Runs EVM bytecode via `@evmts/zevm/evm`. 3. **Blockchain** - Local block storage, forked block resolution, canonical heads. 4. **StateManager** - Accounts, code, storage, snapshots, fork-backed reads. 5. **TxPool** - Pending transactions including EIP-4844 and EIP-7702 shapes. 6. **ReceiptsManager** - Receipts and logs for JSON-RPC queries, filters, subscriptions. 7. **Common, RLP, Trie, Tx, Utils** - Tevm facades over ZEVM-compatible primitives. ### ZEVM Backing Tevm migrated its low-level EVM, transaction, receipt, txpool, common, RLP, trie, and utility primitives to `@evmts/zevm`. Tevm retains its own public package boundaries and viem-style ergonomics; low-level docs describe Tevm facades over ZEVM-backed primitives. ### EVM Module The EVM module handles bytecode execution and state transitions. Exported from `tevm/evm`, backed by `@evmts/zevm/evm`. ```ts import { createImpersonatedTx } from 'tevm/tx' const vm = await node.getVm() const evm = vm.evm // Direct EVM execution const result = await evm.runCall({ to, data, value: 0n, caller }) // Full transaction via VM const tx = createImpersonatedTx({ impersonatedAddress: caller, to, data, gasLimit: 1_000_000n, }) const txResult = await vm.runTx({ tx }) ``` #### Key Features * **State management**: Executes against Tevm's account, code, and storage state. * **Gas metering**: Tracks execution gas, intrinsic gas, refunds, fee behavior. * **Precompiles**: Built-in plus Tevm custom precompiles. * **Tracing**: Step, message, call trace, prestate trace, flat trace, mux trace, four-byte trace. * **EIP support**: EIP-4844 blob transactions and EIP-7702 EOA code transactions via `tevm/tx`. ### Blockchain Module Manages block lookup, canonical heads, forked block resolution, local block writes. Tevm implementation working with Tevm block types and ZEVM-compatible constants/utilities. ```ts const chain = (await node.getVm()).blockchain const latest = await chain.getCanonicalHeadBlock() const blockByNumber = await chain.getBlock(1234n) const blockByHash = await chain.getBlock(blockHash) await chain.putBlock(localBlock) await chain.delBlock(blockHash) ``` #### Fork Support ```ts const forkedBlock = await chain.getBlock(blockNumber) // Local blocks override forked blocks once written await chain.putBlock(localBlock) ``` ### StateManager Accounts, storage, contract code, state roots, snapshots, fork-backed reads. ```ts const state = (await node.getVm()).stateManager const account = await state.getAccount(address) await state.putAccount(address, account) await state.putContractCode(address, bytecode) const code = await state.getContractCode(address) await state.putContractStorage(address, key, value) const storageValue = await state.getContractStorage(address, key) await state.checkpoint() await state.commit() await state.revert() ``` ### Transaction Pool Pending transactions before block inclusion. Backed by `@evmts/zevm/txpool`; broadens fee classification for fee-market-shaped transactions including EIP-7702. ```ts const pool = await node.getTxPool() await pool.add(tx) await pool.addUnverified(tx) const senderTxs = await pool.getBySenderAddress(sender) const byHash = pool.getByHash([txHash]) const ordered = await pool.txsByPriceAndNonce({ baseFee: 10n, allowedBlobs: 6 }) ``` JSON-RPC exposes `txpool_content`, `txpool_contentFrom`, `txpool_inspect`, `txpool_status`. ### ReceiptsManager Transaction receipts, block receipt lookup, event logs. ```ts const receipts = await node.getReceiptsManager() const blockReceipts = await receipts.getReceipts(blockHash) const receiptResult = await receipts.getReceiptByTxHash(txHash) const logs = await receipts.getLogs(fromBlock, toBlock, addresses, topics) ``` Supports pre-Byzantium, post-Byzantium, and EIP-4844 blob receipt shapes. ### JSON-RPC Integration Submodules power Tevm's RPC handlers: * `eth_*` standard JSON-RPC, including `eth_getProof`, `eth_blobBaseFee`, `eth_simulateV1`, `eth_simulateV2`. * `tevm_*` native calls, account/state management, mining, light sync status. * `debug_*` trace, raw block/header/receipt/transaction, storage range, preimage, modified account methods. * `anvil_*`, `hardhat_*`, `ganache_*`, `evm_*` development-node compatibility. * `engine_*` Engine API payload and forkchoice methods (when `engineApi` enabled). * `txpool_*`, `web3_*`, `net_*`, `rpc_modules` broader client compatibility. ### Best Practices * **Use high-level APIs first**: Prefer `createMemoryClient`, viem actions, or JSON-RPC. * **Drop down deliberately**: Use `vm.runTx`, `evm.runCall`, txpool, or receipts directly for tooling, debuggers, or extensions. * **Handle snapshots carefully**: Use checkpoints and `evm_snapshot`/`evm_revert` flows for test isolation. * **Choose the right trace**: `debug_traceCall`/`debug_traceTransaction` for RPC-compatible tracing; `onStep`, `onBeforeMessage`, `onAfterMessage` for in-process instrumentation. ### Related Topics * [JSON-RPC Support](./json-rpc) * [Managing State](../core/managing-state) * [Transaction Pool](../advanced/txpool) * [Receipts & Logs](../advanced/receipts-and-logs) * [EVM Events](./evm-events) * [EVM Opcodes Reference](https://www.evm.codes/) * [Ethereum Yellow Paper](https://ethereum.github.io/yellowpaper/paper.pdf) ## Custom Precompiles Tevm lets you register JavaScript functions as EVM precompiles at fixed addresses — useful for crypto, oracles, complex math, bridges, custom data structures, and test helpers. ### Quick Start #### Basic Example ```typescript showLineNumbers filename="simple-precompile.ts" import { createTevmNode, definePrecompile, PREFUNDED_ACCOUNTS } from 'tevm' import { createAddress } from 'tevm/address' import { createContract } from 'tevm/contract' import { hexToBytes, parseAbi } from 'tevm/utils' import { createImpersonatedTx } from 'tevm/tx' const customPrecompile = definePrecompile({ contract: createContract({ abi: parseAbi(['function double(bytes) returns (bytes)']), address: '0x0000000000000000000000000000000000000123' }), call: async ({ data }) => { const input = Array.from(hexToBytes(data)) return { returnValue: new Uint8Array(input.map(byte => Number(byte) * 2)), executionGasUsed: 200n, } }, }) const node = createTevmNode({ customPrecompiles: [customPrecompile.precompile()], }) const tx = createImpersonatedTx({ impersonatedAddress: createAddress(PREFUNDED_ACCOUNTS[0].address), to: customPrecompile.contract.address, data: '0x00', gasLimit: 100000n, maxFeePerGas: 10n, maxPriorityFeePerGas: 1n, }) const vm = await node.getVm() const result = await vm.runTx({ tx }) ``` :::warning[Modern Gas Rules] When calling `vm.runTx()` directly, build a valid transaction for the active hardfork. Prague uses EIP-1559 fees, so `maxFeePerGas` must be at least the block base fee and the gas limit must cover intrinsic calldata gas. ::: :::tip[Type Safety] `definePrecompile` provides full type safety based on the provided ABI. ::: #### Complex Example ```typescript showLineNumbers filename="advanced-precompile.ts" import { createTevmNode, definePrecompile } from 'tevm' import { createContract } from 'tevm/contract' import { parseAbi, hexToBytes, keccak256 } from 'tevm/utils' const hashPrecompile = definePrecompile({ contract: createContract({ abi: parseAbi(['function hash(bytes) returns (bytes32)']), address: '0x0000000000000000000000000000000000000321' }), call: async ({ data }) => { const gasPerByte = 10n const gasUsed = BigInt(hexToBytes(data).length) * gasPerByte + 100n const hash = hexToBytes(keccak256(data)) return { returnValue: hash, executionGasUsed: gasUsed } }, }) const node = createTevmNode({ customPrecompiles: [hashPrecompile.precompile()], }) ``` ### Precompile Interface Every precompile needs an ABI/address and a call handler: ```typescript showLineNumbers filename="interface.ts" const contract = createContract({ abi: parseAbi(['function myFunction(uint256) returns (uint256)']), address: '0x0000000000000000000000000000000000000123' }) ``` ```typescript showLineNumbers filename="handler.ts" const call = async ({ data, gasLimit }: PrecompileInput): Promise => { return { returnValue: new Uint8Array([/* result data */]), executionGasUsed: 1000n, // Optional: exceptionError for when the operation fails } } ``` ```typescript showLineNumbers filename="register.ts" const myPrecompile = definePrecompile({ contract, call }) const node = createTevmNode({ customPrecompiles: [myPrecompile.precompile()] }) ``` ### Example Implementations #### JavaScript State Example ```typescript showLineNumbers filename="state-precompile.ts" const storage = new Map() const statePrecompile = definePrecompile({ contract: createContract({ abi: parseAbi(['function store(bytes32,bytes32)']), address: '0x0000000000000000000000000000000000000124' }), call: async ({ data, gasLimit }) => { const bytes = hexToBytes(data) const key = bytes.slice(0, 32) const value = bytes.slice(32, 64) storage.set(Buffer.from(key).toString('hex'), value) return { returnValue: new Uint8Array(), executionGasUsed: 200n } }, }) ``` :::tip[Persistent Storage] This demonstrates JavaScript-side state persisting across precompile calls. Use normal EVM storage from Solidity if the data must be visible as contract storage. ::: #### Gas Calculation Example ```typescript showLineNumbers filename="gas-precompile.ts" const gasPrecompile = definePrecompile({ contract: createContract({ abi: parseAbi(['function processWithGas(bytes)']), address: '0x0000000000000000000000000000000000000125' }), call: async ({ data, gasLimit }) => { const gasUsed = BigInt(hexToBytes(data).length * 100) if (gasUsed > gasLimit) { return { returnValue: new Uint8Array(), exceptionError: new EvmError('out of gas'), executionGasUsed: gasLimit, } } return { returnValue: new Uint8Array(), executionGasUsed: gasUsed } }, }) ``` :::warning[Gas Handling] Always check gas before executing and return the exact amount used. ::: #### Error Handling Example ```typescript showLineNumbers filename="error-precompile.ts" const errorPrecompile = definePrecompile({ contract: createContract({ abi: parseAbi(['function process(bytes)']), address: '0x0000000000000000000000000000000000000126' }), call: async ({ data, gasLimit }) => { try { if (data === '0x') { throw new Error('Empty input not allowed') } return { returnValue: processData(data), executionGasUsed: 200n } } catch (error) { return { returnValue: new Uint8Array(), exceptionError: new EvmError( `Precompile error: ${error instanceof Error ? error.message : String(error)}`, ), executionGasUsed: gasLimit, } } }, }) ``` #### Multiple Precompiles Example ```typescript showLineNumbers filename="multiple-precompiles.ts" const precompileA = definePrecompile({ contract: createContract({ abi: parseAbi(['function processA() returns (bytes)']), address: '0x0000000000000000000000000000000000000127' }), call: async () => ({ returnValue: new Uint8Array([1]), executionGasUsed: 200n }), }) const precompileB = definePrecompile({ contract: createContract({ abi: parseAbi(['function processB() returns (bytes)']), address: '0x0000000000000000000000000000000000000128' }), call: async () => ({ returnValue: new Uint8Array([2]), executionGasUsed: 200n }), }) const node = createTevmNode({ customPrecompiles: [precompileA.precompile(), precompileB.precompile()], }) ``` ### Use Cases * Cryptographic operations (encryption, hashing, signature verification) * Oracle / external data simulation for local testing * Complex math that would be gas-intensive in Solidity * Cross-chain bridge verification logic * Custom data structures (trees, graphs, etc.) * Testing helpers (time manipulation, state snapshots) ### Best Practices #### Gas Calculation Calculate gas based on actual work performed, similar to native EVM ops. ```typescript showLineNumbers filename="gas-best-practices.ts" const precompile = definePrecompile({ contract: createContract({ abi: parseAbi(['function process(bytes)']), address: createAddress('0x0000000000000000000000000000000000000123') }), call: async ({ data, gasLimit }) => { const baseGas = 100n const dataGas = BigInt(hexToBytes(data).length * 10) const totalGas = baseGas + dataGas if (totalGas > gasLimit) { return { returnValue: new Uint8Array(), exceptionError: new EvmError('out of gas'), executionGasUsed: gasLimit, } } return { returnValue: processData(data), executionGasUsed: totalGas } }, }) ``` #### Error Handling Use appropriate error types and include detailed info. ```typescript showLineNumbers filename="error-best-practices.ts" const precompile = definePrecompile({ contract: createContract({ abi: parseAbi(['function process(bytes32,uint256)']), address: createAddress('0x0000000000000000000000000000000000000123') }), call: async ({ data, gasLimit }) => { try { if (hexToBytes(data).length < 36) { return { returnValue: new Uint8Array(), exceptionError: new EvmError('Invalid input: insufficient data'), executionGasUsed: 100n, } } return { returnValue: result, executionGasUsed: gasUsed } } catch (error) { console.error('Precompile execution error:', error) return { returnValue: new Uint8Array(), exceptionError: new EvmError( error instanceof Error ? error.message : 'Unknown precompile error', ), executionGasUsed: gasLimit < 100n ? gasLimit : 100n, } } }, }) ``` #### Performance Cache results for expensive deterministic operations. ```typescript showLineNumbers filename="performance-best-practices.ts" const precompile = definePrecompile({ // Contract definition... call: async ({ data, gasLimit }) => { const cacheKey = data.toString() if (resultsCache.has(cacheKey)) { return resultsCache.get(cacheKey) } const result = performExpensiveOperation(data) resultsCache.set(cacheKey, { returnValue: result, executionGasUsed: gasUsed }) return { returnValue: result, executionGasUsed: gasUsed } }, }) ``` ### Related Resources * [Contract Reference](/reference/contract) * [State Management](/core/managing-state) * [JSON-RPC Support](../api/json-rpc) * [EVM Precompiles Reference](https://www.evm.codes/precompiled) ## Performance Profiler Tevm provides two inspection levels: * `createTrace: true` returns a serializable per-opcode trace for one call. * `profiler: true` enables the low-level EVM performance log collector. Use traces for application tooling and profiler logs when investigating the EVM implementation itself. ### Profile a Call with a Trace ```ts import { createMemoryClient, PREFUNDED_ACCOUNTS } from 'tevm' const client = createMemoryClient() const contract = '0x4444444444444444444444444444444444444444' await client.tevmSetAccount({ address: contract, deployedBytecode: '0x6001600055', }) const result = await client.tevmCall({ from: PREFUNDED_ACCOUNTS[0].address, to: contract, createTrace: true, }) const gasByOpcode = new Map() for (const step of result.trace?.structLogs ?? []) { gasByOpcode.set( step.op, (gasByOpcode.get(step.op) ?? 0n) + step.gasCost, ) } console.log(result.executionGasUsed, gasByOpcode) ``` `executionGasUsed` covers EVM execution. `totalGasSpent` also includes intrinsic transaction costs when available. ### Stream Live Steps ```ts import { createMemoryClient } from 'tevm' const client = createMemoryClient() let stepCount = 0 await client.tevmCall({ deployedBytecode: '0x6001600055', onStep(step, next) { stepCount += 1 console.log(step.pc, step.opcode.name, step.gasLeft) next?.() }, }) console.log(stepCount) ``` Live callbacks avoid retaining a full trace but add work to every opcode. Keep handlers small and always call `next?.()`. ### Low-Level Profiler Logs ```ts import { createMemoryClient } from 'tevm' const client = createMemoryClient({ profiler: true }) await client.tevmReady() await client.tevmCall({ deployedBytecode: '0x6001600055', }) const vm = await client.transport.tevm.getVm() const logs = vm.evm.getPerformanceLogs() console.log(logs) ``` Profiler mode has runtime and memory overhead. Enable it only around measurements, warm up initialization before timing, and compare the same bytecode and chain configuration. ### Related [EVM Events](../api/evm-events) · [Building a Debugger UI](../examples/debugger-ui) · [Call API](../api/tevm-call) ## Receipts & Logs Tevm Node manages transaction receipts and event logs through the ReceiptsManager and filter system — enabling event listening, status tracking, and log filtering. ### Quick Start :::code-group ```typescript [Basic Usage] showLineNumbers filename="basic-receipt-usage.ts" import { createTevmNode, PREFUNDED_ACCOUNTS } from 'tevm' import { callHandler, mineHandler } from 'tevm/actions' import { hexToBytes } from 'tevm/utils' const node = createTevmNode() const receiptsManager = await node.getReceiptsManager() const callResult = await callHandler(node)({ addToMempool: true, from: PREFUNDED_ACCOUNTS[0].address, to: '0x2345678901234567890123456789012345678901', value: 1000000000000000000n, }) await mineHandler(node)({}) if (!callResult.txHash) { throw new Error('Transaction was not added to the mempool') } const receiptResult = await receiptsManager.getReceiptByTxHash( hexToBytes(callResult.txHash) ) if (receiptResult) { const [receipt, blockHash, txIndex, logIndex] = receiptResult console.log({ status: 'status' in receipt ? receipt.status : undefined, gasUsed: receipt.cumulativeBlockGasUsed, logs: receipt.logs }) } ``` ```typescript [Log Filtering] showLineNumbers filename="log-filtering.ts" import { createTevmNode } from 'tevm' import { createAddress } from 'tevm/address' import { hexToBytes } from 'tevm/utils' const node = createTevmNode() const receiptsManager = await node.getReceiptsManager() const vm = await node.getVm() const fromBlock = await vm.blockchain.getBlock(0n) const toBlock = await vm.blockchain.getCanonicalHeadBlock() const contractAddress = createAddress('0x1234567890123456789012345678901234567890') // Filter by contract address const addressLogs = await receiptsManager.getLogs( fromBlock, toBlock, [contractAddress.toBytes()], undefined ) // Filter by event topic (Transfer) const eventTopic = hexToBytes('0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef') const topicLogs = await receiptsManager.getLogs( fromBlock, toBlock, undefined, [eventTopic] ) console.log(`Found ${addressLogs.length} logs from the contract`) console.log(`Found ${topicLogs.length} Transfer events`) ``` ::: ### Receipt Types Tevm supports receipts across all Ethereum hard forks: * **Pre-Byzantium** — uses state root for transaction results * **Post-Byzantium** — uses status codes (success/failure) * **EIP-4844** — includes blob gas information ```typescript showLineNumbers filename="receipt-types.ts" interface PreByzantiumReceipt { stateRoot: Uint8Array // Merkle root after transaction cumulativeBlockGasUsed: bigint logs: Log[] // No status field } interface PostByzantiumReceipt { status: number // 1 = success, 0 = failure cumulativeBlockGasUsed: bigint logs: Log[] } interface EIP4844Receipt extends PostByzantiumReceipt { blobGasUsed: bigint blobGasPrice: bigint } ``` ```typescript showLineNumbers filename="receipt-handling.ts" function processReceipt(receiptResult) { if (!receiptResult) return 'Receipt not found' const [receipt] = receiptResult if ('status' in receipt) { return `Transaction ${receipt.status === 1 ? 'succeeded' : 'failed'}` } else { return `Transaction included with state root: 0x${Buffer.from(receipt.stateRoot).toString('hex')}` } } ``` :::tip[Type Detection] Always check the receipt structure before accessing properties — the type depends on the active hard fork. ::: ### Working with Event Logs #### Contract Deployment ```typescript showLineNumbers filename="deploy-contract.ts" import { createTevmNode, PREFUNDED_ACCOUNTS } from 'tevm' import { callHandler, mineHandler } from 'tevm/actions' import { SimpleContract } from 'tevm/contract' import { encodeDeployData } from 'viem' const node = createTevmNode() const deployResult = await callHandler(node)({ addToMempool: true, from: PREFUNDED_ACCOUNTS[0].address, data: encodeDeployData(SimpleContract.deploy(2n)), throwOnFail: false, }) await mineHandler(node)({}) const contractAddress = deployResult.createdAddress if (!contractAddress) { throw new Error('Contract deployment failed') } ``` #### Emit Events ```typescript showLineNumbers filename="emit-events.ts" import { PREFUNDED_ACCOUNTS } from 'tevm' import { callHandler, mineHandler } from 'tevm/actions' import { SimpleContract } from 'tevm/contract' import { encodeFunctionData } from 'viem' const contract = SimpleContract.withAddress(contractAddress) const callResult = await callHandler(node)({ blockTag: 'pending', addToMempool: true, from: PREFUNDED_ACCOUNTS[0].address, to: contractAddress, data: encodeFunctionData(contract.write.set(42n)), gas: 100000n, throwOnFail: false, }) await mineHandler(node)({}) ``` #### Query Logs ```typescript showLineNumbers filename="query-logs.ts" import { createAddress } from 'tevm/address' import { hexToBytes } from 'tevm/utils' const vm = await node.getVm() const receiptsManager = await node.getReceiptsManager() const fromBlock = await vm.blockchain.getBlock(0n) const toBlock = await vm.blockchain.getCanonicalHeadBlock() const contract = createAddress(contractAddress) // 1. All logs from the contract const contractLogs = await receiptsManager.getLogs( fromBlock, toBlock, [contract.toBytes()], undefined ) // 2. Logs for a specific event const setEventSignature = '0x012c78e2b84325878b1bd9d250d772cfe5bda7722d795f45036fa5e1e6e303fc' const setLogs = await receiptsManager.getLogs( fromBlock, toBlock, [contract.toBytes()], [hexToBytes(setEventSignature)] ) // 3. Logs with wildcard topics const wildcardLogs = await receiptsManager.getLogs( fromBlock, toBlock, [contract.toBytes()], [null] ) ``` #### Process Log Data ```typescript showLineNumbers filename="decode-logs.ts" // ReceiptsManager logs are returned with their block and transaction metadata. for (const { log, block, txIndex, logIndex } of setLogs) { const [address, topics, data] = log const value = BigInt('0x' + Buffer.from(data).toString('hex')) console.log(`Contract: 0x${Buffer.from(address).toString('hex')}`) console.log(`Topic: 0x${Buffer.from(topics[0]).toString('hex')}`) console.log(`Value: ${value}`) console.log(`Block: ${block.header.number}, TxIndex: ${txIndex}, LogIndex: ${logIndex}`) } ``` ### Advanced Features #### Complex Filtering Ethereum logs support up to 4 topics: ```typescript showLineNumbers filename="complex-filtering.ts" const fromAddress = '0x1234567890123456789012345678901234567890' const toAddress = '0x2345678901234567890123456789012345678901' // undefined = wildcard const topics = [ hexToBytes('0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef'), // Transfer hexToBytes('0x000000000000000000000000' + fromAddress.slice(2)), hexToBytes('0x000000000000000000000000' + toAddress.slice(2)) ] const filteredLogs = await receiptsManager.getLogs( fromBlock, toBlock, [contractAddress.toBytes()], topics ) ``` #### Multiple Addresses ```typescript showLineNumbers filename="multi-contract-filtering.ts" const tokenAddress = createAddress('0x1234567890123456789012345678901234567890') const marketplaceAddress = createAddress('0x2345678901234567890123456789012345678901') const transferEvent = '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef' const transfers = await receiptsManager.getLogs( fromBlock, toBlock, [tokenAddress.toBytes(), marketplaceAddress.toBytes()], [hexToBytes(transferEvent)] ) const tokenEvents = transfers.filter(log => Buffer.from(log.address).toString('hex') === Buffer.from(tokenAddress.toBytes()).toString('hex') ) const marketplaceEvents = transfers.filter(log => Buffer.from(log.address).toString('hex') === Buffer.from(marketplaceAddress.toBytes()).toString('hex') ) ``` #### Receipt Indexing :::note[Internal Indexing] ReceiptsManager maintains indexes for efficient queries: tx hash → receipt, block hash → receipts, address → logs, topics → logs. ::: ```typescript showLineNumbers filename="receipt-indexing.ts" // Receipt by tx hash const receipt = await receiptsManager.getReceiptByTxHash(txHash) // All receipts in a block const block = await vm.blockchain.getCanonicalHeadBlock() const receipts = await receiptsManager.getReceipts(block.hash()) // Built-in limits const GET_LOGS_LIMIT = 10000 // Max logs returned const GET_LOGS_LIMIT_MEGABYTES = 150 // Max response size const GET_LOGS_BLOCK_RANGE_LIMIT = 2500 // Max block range ``` ### Best Practices * **Efficient Queries** — use specific filters and limited block ranges * **Handle Null Results** — always check for null/undefined receipts * **Type Safety** — check receipt type before accessing fields * **Pagination** — paginate large log queries #### Efficient Log Queries ```typescript showLineNumbers filename="efficient-queries.ts" const latestBlock = await vm.blockchain.getCanonicalHeadBlock() const blockNumber = latestBlock.header.number // Last 100 blocks only const fromBlock = await vm.blockchain.getBlock( blockNumber - 100n > 0n ? blockNumber - 100n : 0n ) const logs = await receiptsManager.getLogs( fromBlock, latestBlock, [contractAddress.toBytes()], [eventTopic] ) ``` #### Proper Error Handling ```typescript showLineNumbers filename="error-handling.ts" async function safeGetReceipt(txHash) { try { const receiptResult = await receiptsManager.getReceiptByTxHash(txHash) if (receiptResult === null) { console.log('Receipt not found - transaction may be pending or not exist') return null } const [receipt] = receiptResult return receipt } catch (error) { console.error('Error retrieving receipt:', error.message) return null } } ``` #### Working with Receipt Types ```typescript showLineNumbers filename="type-safety.ts" function getTransactionStatus(receipt) { if (!receipt) return 'Unknown' if ('status' in receipt) { return receipt.status === 1 ? 'Success' : 'Failed' } else if ('stateRoot' in receipt) { const emptyRoot = '0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421' const actualRoot = '0x' + Buffer.from(receipt.stateRoot).toString('hex') return actualRoot === emptyRoot ? 'Likely Failed' : 'Likely Success' } return 'Unknown Format' } ``` ### Related Resources * [JSON-RPC Support](../api/json-rpc) * [VM & Submodules](../api/vm-and-submodules) * [Transaction Pool](./txpool) * [Solidity Events](https://docs.soliditylang.org/en/latest/contracts.html#events) ## Transaction Pool The TxPool manages pending transactions before block inclusion. Tevm's facade is backed by `@evmts/zevm/txpool` and adds Tevm-specific fee handling for modern fee-market transactions. ### Quick Start ```ts import { createTevmNode, PREFUNDED_ACCOUNTS } from 'tevm' import { createAddress } from 'tevm/address' import { createImpersonatedTx } from 'tevm/tx' const node = createTevmNode() const txPool = await node.getTxPool() const tx = createImpersonatedTx({ impersonatedAddress: createAddress(PREFUNDED_ACCOUNTS[0].address), to: createAddress('0x2345678901234567890123456789012345678901'), value: 1000000000000000000n, // 1 ETH gasLimit: 21000n, maxFeePerGas: 20000000000n, maxPriorityFeePerGas: 20000000000n, nonce: 0n, }) await txPool.addUnverified(tx) ``` ### Key Features * **Transaction Validation** — nonce, balance, gas checks * **Transaction Replacement** — replace pending tx with higher gas price * **Nonce Ordering** — correct sequence per account * **Automatic Pruning** — removes stale txs * **Performance Optimized** — handles large volumes * **Modern Transaction Support** — legacy, EIP-2930, EIP-1559, EIP-4844, EIP-7702, and Tevm impersonated transactions * **JSON-RPC Access** — `txpool_content`, `txpool_contentFrom`, `txpool_inspect`, `txpool_status` ### Core Concepts #### Pool Limits ```ts const LIMITS = { MAX_POOL_SIZE: 5000, // Maximum total transactions MAX_TXS_PER_ACCOUNT: 100, // Maximum per account MIN_GAS_PRICE: 100000000n, // 0.1 GWei minimum TX_MAX_DATA_SIZE: 128 * 1024, // 128KB max transaction size } ``` #### Transaction Lifecycle 1. **Addition** — via `add()` or `addUnverified()` 2. **Validation** — optional nonce, balance, gas checks 3. **Storage** — stored and ordered by nonce 4. **Pruning** — removed after `POOLED_STORAGE_TIME_LIMIT` (20 minutes) ### Detailed Usage #### Adding Transactions ```ts // Full validation try { await txPool.add(tx) } catch (error) { if (error.message.includes('insufficient balance')) { console.error('Account has insufficient funds') } } // No validation (faster) await txPool.addUnverified(tx) ``` #### Transaction Replacement Submit a new tx with the same nonce and higher gas price (>= 10% bump): ```ts const originalTx = createImpersonatedTx({ // ... base transaction params ... maxFeePerGas: 20000000000n, nonce: 0n, }) const replacementTx = createImpersonatedTx({ // ... same params as original ... maxFeePerGas: 30000000000n, // At least 10% higher nonce: 0n, }) await txPool.addUnverified(originalTx) await txPool.addUnverified(replacementTx) // Replaces originalTx ``` :::note Replacements must bump gas price by at least `MIN_GAS_PRICE_BUMP_PERCENT` (10%). ::: #### Querying Transactions ```ts const senderTxs = await txPool.getBySenderAddress(senderAddress) const txHashes = [hash1, hash2] const specificTxs = txPool.getByHash(txHashes) const orderedTxs = await txPool.txsByPriceAndNonce({ baseFee: currentBaseFee, allowedBlobs: 6, // For EIP-4844 }) ``` #### Block Processing ```ts import { mineHandler } from 'tevm/actions' await mineHandler(node)() txPool.removeNewBlockTxs(newBlocks) ``` ### Advanced Features #### Pool Management ```ts txPool.start() // Start processing txPool.stop() // Stop (keep transactions) txPool.close() // Clear all txPool.cleanup() // Manual cleanup of old txs ``` #### Transaction Types Supports: Legacy, EIP-2930 (Access Lists), EIP-1559 (Fee Market), EIP-4844 (Blob), EIP-7702 (EOA Code), and Tevm Impersonated Transactions. ### Best Practices #### 1. Transaction Creation ```ts import { PREFUNDED_ACCOUNTS, parseEther, parseGwei } from 'tevm' import { createAddress } from 'tevm/address' import { createImpersonatedTx } from 'tevm/tx' const tx = createImpersonatedTx({ impersonatedAddress: createAddress(PREFUNDED_ACCOUNTS[0].address), to: createAddress('0x2345678901234567890123456789012345678901'), value: parseEther('1'), gasLimit: 21000n, maxFeePerGas: parseGwei('20'), maxPriorityFeePerGas: parseGwei('2'), nonce: 0n, }) ``` #### 2. Error Handling ```ts try { await txPool.add(tx) } catch (error) { switch (true) { case error.message.includes('insufficient balance'): break case error.message.includes('nonce too low'): break case error.message.includes('gas price too low'): break default: // unknown error } } ``` #### 3. Performance Optimization * Use `addUnverified` for bulk operations * Run cleanup cycles * Monitor pool size and tx age #### 4. Memory Management ```ts setInterval(() => { txPool.cleanup() }, 5 * 60 * 1000) // Every 5 minutes const poolSize = txPool.txsInPool if (poolSize > MAX_POOL_SIZE * 0.8) { console.warn('Pool approaching capacity') } ``` ### API Reference ```ts class TxPool { constructor(options: { vm: Vm }) async add(tx: Transaction): Promise async addUnverified(tx: Transaction): Promise async getBySenderAddress(address: Address): Promise getByHash(hashes: Uint8Array[]): Transaction[] removeByHash(hash: string): void removeNewBlockTxs(blocks: Block[]): void start(): boolean stop(): boolean cleanup(): void close(): void } ``` ### Related Topics * [JSON-RPC Support](../api/json-rpc) * [VM & Submodules](../api/vm-and-submodules) * [Receipts & Logs](./receipts-and-logs)