Bundler Overview
Key Benefits
- Direct imports: import
.solfiles like any TS module. - Type safety: full type checking for methods, args, and return values.
- IDE integration: go-to-definition, auto-completion, hover docs.
- NatSpec: contract docs appear in your editor.
- HMR: Solidity changes update during development.
- Framework support: Vite, Webpack, Next.js, Bun, and more.
Available Plugins
| Bundler | Plugin Import Path | Repository |
|---|---|---|
| Vite | tevm/bundler/vite-plugin | @tevm/vite-plugin |
| Webpack | tevm/bundler/webpack-plugin | @tevm/webpack-plugin |
| Rollup | tevm/bundler/rollup-plugin | @tevm/rollup-plugin |
| ESBuild | tevm/bundler/esbuild-plugin | @tevm/esbuild-plugin |
| Bun | tevm/bundler/bun-plugin | @tevm/bun-plugin |
| Rspack | tevm/bundler/rspack-plugin | @tevm/rspack-plugin |
For plugin configuration, see the Quickstart Guide.
Prerequisites & Key Points
-
Optional: use
tevm generate contractif you don't want a bundler hook.tevm generate contract tevm generate contract "ERC20Token" tevm generate contract --include "contracts/**/*.sol" --output "types/" -
TypeScript: add
@tevm/ts-pluginto tsconfig for editor support. -
.s.solfor bytecode:.solproduces ABI only;.s.solincludes deployable bytecode. -
Cache: artifacts live in
.tevm/— add it to.gitignore. The directory is ephemeral. -
Foundry/remappings: configure in
tevm.config.json(see below). -
Next.js: type-checker conflicts; use codegen or disable Next typechecking.
Basic Usage
import { Counter } from './Counter.sol'
import { createMemoryClient } from 'tevm'
const client = createMemoryClient()
const deployed = await client.deployContract(Counter)
const count = await deployed.read.count()
await deployed.write.increment()
await client.mine({ blocks: 1 })
const newCount = await deployed.read.count()The imported value is a Tevm Contract instance with abi, optional bytecode, deployment helpers, .read / .write methods, and event filters.
Importing Dependencies
import { MyToken } from './contracts/MyToken.sol'
import { ERC20 } from '@openzeppelin/contracts/token/ERC20/ERC20.sol'Integration with Viem and Ethers
import { createPublicClient, http } from 'viem'
import { mainnet } from 'viem/chains'
import { MyToken } from './contracts/MyToken.sol'
const client = createPublicClient({ chain: mainnet, transport: http() })
const balance = await client.readContract({
...MyToken.read.balanceOf('0x123...'),
address: '0x456...',
})
const hash = await client.writeContract({
...MyToken.write.transfer('0x789...', 1000n),
address: '0x456...',
})Bundler Configuration
{
"foundryProject": true,
"libs": ["lib", "node_modules"],
"remappings": {
"@openzeppelin/": "node_modules/@openzeppelin/"
},
"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<string, string> | 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 |
Coming Soon Features
Inline Solidity with sol Tag
import { sol } from 'tevm'
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;
}
}
`Network Imports via Macros
Build-time contract imports from any chain, offering stronger type safety than runtime imports.
// contract-macros.js
import { createMemoryClient, loadContract } from 'tevm'
import { http } from 'viem'
import { SourcifyABILoader, EtherscanABILoader } from 'tevm/whatsabi'
const client = createMemoryClient({
fork: {
transport: http('https://eth-mainnet.g.alchemy.com/v2/YOUR_API_KEY'),
blockNumber: 19000000n,
},
})
export async function wethContract() {
return loadContract(client, {
address: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2',
followProxies: true,
loaders: [new SourcifyABILoader(), new EtherscanABILoader({ apiKey: 'YOUR_ETHERSCAN_KEY' })],
})
}
// app.js
import { wethContract } from './contract-macros.js' with { type: 'macro' }Enable macros in tevm.config.json for security:
{
"macros": true,
"foundryProject": true,
"libs": ["lib", "node_modules"]
}Full documentation: Contract Loader.

