Bundler-generated contracts
The Tevm bundler lets you import a Solidity file directly from TypeScript:
import { MyToken } from './MyToken.sol'What you get back is a Contract from this package — the same object createContract returns,
with bytecode and deployedBytecode already filled in from the compiler.
This is why @tevm/contract is a standalone package: the bundler runs inside tsc, ESLint,
Vite, and your editor's language server, and it needs to emit this type without depending on
an EVM. See How it fits into Tevm.
What the bundler emits
For a MyToken.sol containing an ERC-20, the bundler generates roughly this module:
import { createContract } from '@tevm/contract'
const _MyToken = {
name: 'MyToken',
humanReadableAbi: [
'constructor(string name, string symbol)',
'function balanceOf(address account) view returns (uint256)',
'function transfer(address to, uint256 value) returns (bool)',
'event Transfer(address indexed from, address indexed to, uint256 value)',
],
bytecode: '0x60806040...',
deployedBytecode: '0x60806040...',
} as const
export const MyToken = createContract(_MyToken)Note as const. It is load-bearing: without it the humanReadableAbi array widens to
string[] and every action creator degrades to any. If you hand-write a contract module,
copy this shape.
Using an imported contract
Once imported, it behaves exactly like any other contract on this site:
import { MyToken } from './MyToken.sol'
import { createMemoryClient, PREFUNDED_ACCOUNTS } from 'tevm'
const client = createMemoryClient()
await client.tevmReady()
const result = await client.tevmDeploy({
from: PREFUNDED_ACCOUNTS[0].address,
...MyToken.deploy('My Token', 'MTK'),
addToMempool: true,
})
await client.tevmMine({ blockCount: 1 })
if (!result.createdAddress) throw new Error('deployment failed')
const token = MyToken.withAddress(result.createdAddress)
const { data } = await client.tevmContract(
token.read.balanceOf(PREFUNDED_ACCOUNTS[0].address),
)
console.log(data)Setting it up
The bundler ships as a set of plugins, plus a TypeScript language-service plugin so your editor
resolves .sol imports too.
import { vitePluginTevm } from '@tevm/bundler/vite-plugin'
import { defineConfig } from 'vite'
export default defineConfig({
plugins: [vitePluginTevm()],
}){
"compilerOptions": {
"strict": true,
"plugins": [{ "name": "@tevm/ts-plugin" }]
}
}Full setup instructions, including the other bundlers and the @tevm/ts-plugin options, live in
the Tevm bundler documentation.
Without the bundler
The bundler is a convenience, not a requirement. Any pipeline that gets you an ABI and bytecode
works — read forge build artifacts, import a JSON ABI, or write the human-readable ABI by
hand:
import { createContract } from '@tevm/contract'
import artifact from './out/MyToken.sol/MyToken.json' with { type: 'json' }
export const MyToken = createContract({
name: 'MyToken',
abi: artifact.abi,
bytecode: artifact.bytecode.object as `0x${string}`,
deployedBytecode: artifact.deployedBytecode.object as `0x${string}`,
})
