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:
| 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 |
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 the tevm generate contract command. The plugins are purely optional if you prefer a different workflow.
# Generate TypeScript types from all Solidity files
tevm generate contract
# Generate types for specific contracts
tevm generate contract "ERC20Token"
# Specify custom include pattern and output directory
tevm generate contract --include "contracts/**/*.sol" --output "types/"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
.solfiles 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
| Option | Type | Description |
|---|---|---|
foundryProject | boolean | string | Enable Foundry integration (true) or path to foundry.toml |
libs | string[] | Library paths for Solidity imports (used alongside Foundry libs) |
remappings | Record<string, string> | Custom import remappings |
debug | boolean | Output extra debug logs and files in .tevm |
cacheDir | string | Location for compiled artifacts (default: .tevm) |
jsonAsConst | string | 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.Network Imports via Macros
Tevm will soon support importing contract ABIs from any blockchain network using macros. This build-time solution offers several advantages over runtime imports, including stronger type safety and better performance:
// Create a contract macro function
// contract-macros.js
import { createMemoryClient } from 'tevm'
import { http } from 'viem'
import { mainnet } from 'viem/chains'
import { loadContract } from 'tevm'
import { SourcifyABILoader, EtherscanABILoader } from 'tevm/whatsabi'
// For hermetic builds, use a memory client with fixed block height
const client = createMemoryClient({
fork: {
transport: http('https://eth-mainnet.g.alchemy.com/v2/YOUR_API_KEY'),
blockNumber: 19000000n // Pin to specific block for reproducible builds
}
})
// Export a function that returns a contract - one function per contract
export async function wethContract() {
// Uses Contract Loader to fetch and analyze contract data
return loadContract(client, {
address: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2',
followProxies: true,
loaders: [
new SourcifyABILoader(),
new EtherscanABILoader({ apiKey: 'YOUR_ETHERSCAN_KEY' })
]
})
}
// Import the contract with import attributes
// app.js
import { wethContract } from './contract-macros.js' with { type: 'macro' }Macros must be enabled in your tevm.config.json file for security reasons:
{
"macros": true,
"foundryProject": true,
"libs": ["lib", "node_modules"]
}For complete documentation about this feature, see the Contract Loader guide.
Further Reading
- Bundler Internals - Learn how the bundler works under the hood
- Methods & Exports - Advanced APIs for custom implementations
- Troubleshooting - Solve common issues with the bundler

