Tevm Node Methods
Reference for the main API methods on a Tevm Node instance: EVM interaction, state management, execution control.
Core Methods
Initialization
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()Virtual Machine
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)
}Transaction Pool
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...')Receipts & Logs
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
// Impersonate (fork mode only)
node.setImpersonatedAccount('0x1234...')
const impersonated = node.getImpersonatedAccount()
// Stop
node.setImpersonatedAccount(undefined)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:
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
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
console.log(node.status)
// 'INITIALIZING' | 'READY' | 'SYNCING' | 'MINING' | 'STOPPED'
const waitForReady = async () => {
while (node.status !== 'READY') {
await new Promise(resolve => setTimeout(resolve, 100))
}
}Mode
console.log(node.mode) // 'fork' or 'normal'
if (node.mode === 'fork') {
// fork-specific features like impersonation
} else {
// local-only features
}Logger
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:
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?.()
}
})tevmContract
High-level contract interaction with event monitoring:
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:
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
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...')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
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
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.
State Accesseth_getBalanceeth_getCodeeth_getStorageAteth_getTransactionCount
eth_blockNumbereth_getBlockByHasheth_getBlockByNumber
eth_sendTransactioneth_sendRawTransactioneth_getTransactionByHasheth_getTransactionReceipt
anvil_impersonateAccountanvil_stopImpersonatingAccountanvil_mineanvil_setBalance
tevm_snapshottevm_reverttevm_minetevm_setAccount

