Skip to content
LogoLogo

Tevm Test

Vitest matchers for the EVM, an in-memory test node, and test utilities — everything you need to test Ethereum TypeScript code without an external node.

npm install @tevm/test-matchers @tevm/test-node @tevm/test-utils

What is Tevm Test?

Tevm Test is the standalone home for Tevm's testing libraries. It publishes three packages:

PackageWhat it gives you
@tevm/test-matchersVitest matchers for emitted events, reverts and custom errors, ETH and ERC20 balance deltas, account state, and contract calls
@tevm/test-nodeA Tevm node, client, and transport that record forked JSON-RPC responses to disk so fork tests are deterministic and run offline
@tevm/test-utilsPrecompiled Solidity fixtures (SimpleContract, ErrorContract, ERC20/ERC721, …) and RPC helpers

Why it exists

Solidity contracts are usually tested in Solidity, in a second toolchain, with a second set of assertions. That works, but the code that calls your contracts — the frontend, the indexer, the SDK — is TypeScript, and its tests are Vitest. Tevm Test lets that TypeScript suite make the same assertions Foundry makes:

import { SimpleContract } from '@tevm/test-utils'
import { createMemoryClient } from '@tevm/memory-client'
import { expect, test } from 'vitest'
 
const client = createMemoryClient()
 
test('set() emits ValueSet', async () => {
  const { createdAddress } = await client.tevmDeploy({
    ...SimpleContract.deploy(0n),
    addToBlockchain: true,
  })
  const contract = SimpleContract.withAddress(createdAddress!)
 
  await expect(client.tevmContract(contract.write.set(100n)))
    .toEmit(contract, 'ValueSet')
    .withEventArgs(100n)
})

No RPC endpoint, no anvil process, no separate assertion language.

Three things that are hard elsewhere

Balance deltas

toChangeBalance replays your transaction under a prestateTracer and diffs the pre/post state, so you get exact wei deltas including gas — and the same works for ERC20 balances, where the token's storage slot is discovered automatically rather than hardcoded.

Custom errors with arguments

toBeRevertedWithError(client, contract, 'InsufficientBalance').withErrorArgs(50n, 1000n) decodes the revert data against your ABI, with full type inference on the argument tuple.

Forked tests that don't flake

createTestSnapshotNode writes every upstream JSON-RPC response into rpc_snapshots/<test file>.snap.json next to your test. Commit it, and CI never touches the network again.

Matcher playground

Try the pure matchers live — same validation logic as @tevm/test-matchers, running in your browser:

matcher playground — live, powered by @tevm/test-matchers logic
Asserts a value is a valid Ethereum address (EIP-55 checksummed by default)
expect("0x742d35Cc6634C0532925a3b844Bc454e4438f44e").toBeAddress()
PASSExpected 0x742d35Cc6634C0532925a3b844Bc454e4438f44e not to be a valid Ethereum address (checksummed)

Next

  • Getting started — install, set up Vitest, write your first assertion
  • Guides — one page per matcher family, with complete runnable examples
  • Relation to Tevm — how this repo fits with tevm core and the other split repos