Skip to content

Managing State

Tevm offers various approaches to manage Ethereum state, from low-level direct state access to high-level client APIs. Each approach has its benefits and use cases.

State Management Approaches

Raw API
import { createTevmNode } from 'tevm'
import { EthjsAccount } from 'tevm/utils'
 
const node = createTevmNode()
const vm = await node.getVm()
const stateManager = vm.stateManager 
 
// Read account state
const address = '0x1234567890123456789012345678901234567890'
const account = await stateManager.getAccount(address) 
console.log({
  balance: account.balance, 
  nonce: account.nonce, 
  codeHash: account.codeHash, 
  storageRoot: account.storageRoot 
})
 
// Create or update an account
await stateManager.putAccount( 
  address,
  new EthjsAccount({
    nonce: 0n,
    balance: 10_000_000n,
    storageRoot: '0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421',
    codeHash: '0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470'
  })
)
 
// Delete an account
await stateManager.deleteAccount(address) 

Contract State Management

📄 Deploy Code

Deploy smart contract bytecode to the blockchain

👁️ Read Code

Read the deployed bytecode of a contract

💾 Storage Access

Read and write to contract storage slots

🔄 State Reset

Clear contract storage or delete contracts

Raw API
// Using the raw StateManager API
 
// Deploy contract code
await stateManager.putContractCode( 
  address,
  new Uint8Array([/* bytecode */]) 
)
 
// Read contract code
const code = await stateManager.getContractCode(address) 
 
// Read storage slot
const slot = '0x0000000000000000000000000000000000000000000000000000000000000000'
const value = await stateManager.getContractStorage(address, slot) 
 
// Write storage
const key = '0x0000000000000000000000000000000000000000000000000000000000000000'
const newValue = '0x0000000000000000000000000000000000000000000000000000000000000001'
await stateManager.putContractStorage(address, key, newValue) 
 
// Clear all storage
await stateManager.clearContractStorage(address) 

Framework Integration

Viem
import { createMemoryClient } from 'tevm'
 
const client = createMemoryClient()
 
// Use Viem-style API for basic operations
await client.setBalance({ 
  address: '0x1234567890123456789012345678901234567890', 
  value: 1000000000000000000n
}) 
 
// Access raw state manager for advanced operations
const vm = await client.transport.tevm.getVm() 
const stateManager = vm.stateManager 
 
// Use raw API for complex operations
await stateManager.checkpoint() 
try { 
  await stateManager.putContractStorage(address, key, value) 
  await stateManager.commit() 
} catch (error) { 
  await stateManager.revert() 
} 

Advanced Features

State Checkpoints

Create atomic state changes that can be committed or reverted:

const stateManager = (await node.getVm()).stateManager
 
await stateManager.checkpoint() 
try { 
  // Batch multiple state changes
  await Promise.all([
    stateManager.putAccount(address, account),
    stateManager.putContractStorage(address, key, value),
  ])
  await stateManager.commit() 
} catch (error) { 
  await stateManager.revert() 
  console.error('State changes reverted:', error) 
}

State Persistence

Save and load blockchain state:

// Dump complete state
const state = await stateManager.dumpCanonicalGenesis() 
 
// Save state (example with localStorage)
localStorage.setItem('tevmState', JSON.stringify(state)) 
 
// Load saved state
const savedState = JSON.parse(localStorage.getItem('tevmState')) 
await stateManager.generateCanonicalGenesis(savedState) 

Fork Mode

Tevm supports lazy loading with caching when forking from another network:

const node = createTevmNode({
  fork: {
    transport: http('https://mainnet.optimism.io')
  }
})
 
const stateManager = (await node.getVm()).stateManager 
 
// First access fetches from remote
const account = await stateManager.getAccount('0x1234...') 
 
// Subsequent access uses cache
const cachedAccount = await stateManager.getAccount('0x1234...') 

Best Practices

⚠️ Error Handling

Properly handle errors from state operations

🛡️ State Isolation

Create isolated copies of state for testing

⚛️ Atomic Operations

Group related state changes with checkpoints

Error Handling
try {
  const account = await stateManager.getAccount('0x1234...')
  if (!account) {
    throw new Error('Account not found')
  }
  // Work with account
} catch (error) {
  if (error instanceof MissingAccountError) {
    // Handle specific error types
    console.log('Account does not exist yet')
  } else {
    // Handle generic errors
    console.error('State operation failed:', error)
  }
}

Related Resources

State Manager API
Complete API reference for the StateManager interface
Account Management
Learn how to manage Ethereum accounts
Contract Storage
Working with contract storage in depth
Forking Guide
Learn how to fork from live networks