Skip to content

Bundler Overview

Key Benefits

The Tevm bundler offers numerous advantages for Ethereum developers:

  • Direct Imports: Import Solidity files just like any other TypeScript module
  • Type Safety: Full TypeScript type checking for contract methods, arguments, and return values
  • IDE Integration: Go-to-definition, auto-completion, and hover documentation
  • NatSpec Support: Contract documentation appears in your editor
  • Hot Module Reloading: Changes to Solidity files update immediately during development
  • Framework Integration: Works with popular bundlers like Vite, Webpack, Next.js, Bun, and more

Available Plugins

Tevm provides plugins for most popular JavaScript bundlers:

BundlerPlugin Import PathRepository
Vitetevm/bundler/vite-plugin@tevm/vite-plugin
Webpacktevm/bundler/webpack-plugin@tevm/webpack-plugin
Rolluptevm/bundler/rollup-plugin@tevm/rollup-plugin
ESBuildtevm/bundler/esbuild-plugin@tevm/esbuild-plugin
Buntevm/bundler/bun-plugin@tevm/bun-plugin
Rspacktevm/bundler/rspack-plugin@tevm/rspack-plugin

All plugins share a similar usage pattern and a single configuration interface. For detailed plugin configuration, see the Quickstart Guide.

Prerequisites & Key Points

Optional Bundler

You can compile contracts manually or use npx tevm gen. The plugins are purely optional if you prefer a different workflow.

TypeScript Integration

For best results, add the Tevm TS plugin to your tsconfig.json. This allows your editor to resolve Solidity imports, provide NatSpec docs on hover, go-to-definition on solidity methods, and more.

.s.sol for Bytecode

By default, Tevm only generates bytecode for Solidity files ending in .s.sol. Regular .sol files still compile for ABIs, but omit deployable bytecode. This helps differentiate purely interface-like contracts from ones you intend to deploy or call as scripts.

Tevm Cache

Compiled artifacts and metadata are stored in a .tevm folder. It is strongly recommended to .gitignore this directory. The cache directory is ephemeral - you can safely delete it if you encounter stale builds or caching issues.

Foundry/Remappings

If you have a Foundry setup or custom remappings, you can enable them in a tevm.config.json. For detailed configuration, see the Bundler Configuration section.

Next.js

Next.js can conflict with the TS plugin's type-checking. If you wish to keep type-checking turned on for Next.js, consider the Codegen Approach. Otherwise, you may disable type-checking in your Next config.

Basic Usage

Once configured, you can import Solidity contracts directly:

// Import a contract directly from a .sol file
import { Counter } from './Counter.sol'
import { createMemoryClient } from 'tevm'
 
// Create a client to interact with the contract
const client = createMemoryClient()
 
// Deploy the contract
const deployed = await client.deployContract(Counter)
 
// Call read methods
const count = await deployed.read.count()
 
// Call write methods
const tx = await deployed.write.increment()
await client.mine({ blocks: 1 })
 
// Check the updated state
const newCount = await deployed.read.count()

The imported Counter object is a Tevm Contract instance that provides:

  • Type-safe access to all contract methods
  • Contract ABI and bytecode
  • Deployment helpers
  • Read and write method interfaces
  • Event filters

Importing Dependencies

You can import contracts from:

  • Local .sol files in your project
  • npm packages like OpenZeppelin contracts
  • External libraries
// Local import
import { MyToken } from './contracts/MyToken.sol'
 
// npm package import
import { ERC20 } from '@openzeppelin/contracts/token/ERC20/ERC20.sol'

Integration with Viem and Ethers

Tevm contracts work seamlessly with popular Ethereum libraries:

Viem Example

import { createPublicClient, http } from 'viem'
import { mainnet } from 'viem/chains'
import { MyToken } from './contracts/MyToken.sol'
 
const client = createPublicClient({
  chain: mainnet,
  transport: http(),
})
 
// Read methods
const balance = await client.readContract({
  ...MyToken.read.balanceOf('0x123...'),
  address: '0x456...',
})
 
// Write methods
const hash = await client.writeContract({
  ...MyToken.write.transfer('0x789...', 1000n),
  address: '0x456...',
})

Ethers Example

import { ethers } from 'ethers'
import { MyToken } from './contracts/MyToken.sol'
 
const provider = new ethers.BrowserProvider(window.ethereum)
const signer = await provider.getSigner()
 
// Create contract instance
const tokenContract = new ethers.Contract(
  '0x456...',
  MyToken.abi,
  signer
)
 
// Call methods
const balance = await tokenContract.balanceOf('0x123...')
const tx = await tokenContract.transfer('0x789...', 1000n)

Bundler Configuration

For complex projects, create a tevm.config.json file in your project root:

{
  "foundryProject": true,
  "libs": ["lib", "node_modules"],
  "remappings": {
    "@openzeppelin/": "node_modules/@openzeppelin/"
  },
  "debug": false,
  "cacheDir": ".tevm",
  "jsonAsConst": ["**/*.abi.json"]
}

Configuration Options

OptionTypeDescription
foundryProjectboolean | stringEnable Foundry integration (true) or path to foundry.toml
libsstring[]Library paths for Solidity imports (used alongside Foundry libs)
remappingsRecord<string, string>Custom import remappings
debugbooleanOutput extra debug logs and files in .tevm
cacheDirstringLocation for compiled artifacts (default: .tevm)
jsonAsConststring | string[]Glob patterns for JSON files to be typed as const in TS

Coming Soon Features

Inline Solidity with sol Tag

For quick prototyping or one-off contracts, you'll soon be able to use the sol tag to define Solidity code inline:

import { sol } from 'tevm'
 
// Define contract inline
const { bytecode, abi } = sol`
  pragma solidity ^0.8.19;
  
  contract Counter {
    uint256 private count = 0;
    
    function increment() public {
      count += 1;
    }
    
    function count() public view returns (uint256) {
      return count;
    }
  }
`
 
// Use with client.readContract, writeContract, etc.

CAIP-10 Contract Imports

Tevm will soon support importing contracts based on the CAIP-10 Account ID Specification, which will allow you to import contracts from any chain using a standardized identifier format:

// Import a contract from Ethereum mainnet using a CAIP-10 identifier
import { WETH } from 'caip10:eip155:1:0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2'

Further Reading