Call API
The Call API covers ~90% of use cases (with mining) and provides an EVM call interface with extensive configuration.
Basic Usage
Two API styles:
Client-based API
import { createMemoryClient } from 'tevm'
const client = createMemoryClient()
const result = await client.tevmCall({
from: '0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266',
to: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', // WETH
data: '0x'
})Tree-shakable API
import { tevmCall } from 'tevm/actions'
import { createTevmTransport } from 'tevm/memory-client'
import { createTevmNode } from 'tevm/node'
import { requestEip1193 } from 'tevm/decorators'
const client = createClient({ transport: createTevmTransport() })
const result = await tevmCall(client, {
from: '0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266',
to: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', // WETH
data: '0x'
})Parameters
type CallParams = {
to?: Address // required except contract deployment
data?: Hex
value?: bigint // wei
gas?: bigint
blockTag?: 'latest' | 'pending' | 'earliest' | number
createTransaction?: 'on-success' | 'always' | 'never' | boolean // DEPRECATED
addToMempool?: 'on-success' | 'always' | 'never' | boolean // requires mining
addToBlockchain?: 'on-success' | 'always' | 'never' | boolean // auto-mines
skipBalance?: boolean
createAccessList?: boolean
createTrace?: boolean
from?: Address // defaults to first account
maxFeePerGas?: bigint
maxPriorityFeePerGas?: bigint
stateOverrideSet?: StateOverrideSet
blockOverrideSet?: BlockOverrideSet
onStep?: (data: InterpreterStep, next?: () => void) => void
onNewContract?: (data: NewContractEvent, next?: () => void) => void
onBeforeMessage?: (data: Message, next?: () => void) => void
onAfterMessage?: (data: EVMResult, next?: () => void) => void
}Return Type
type CallResult = {
rawData: Hex // return data
executionGasUsed: bigint
totalGasSpent?: bigint // includes intrinsic costs
txHash?: Hex
logs?: Log[]
createdAddress?: Address
accessList?: Record<Address, Set<Hex>>
trace?: TraceResult
errors?: TevmCallError[]
}Examples
Simple Contract Call
import { createMemoryClient, PREFUNDED_ACCOUNTS } from 'tevm'
import { ERC20 } from 'tevm/contract'
import { encodeFunctionData, decodeFunctionResult, parseAbi } from 'viem'
const abi = parseAbi(['function balanceOf(address account) view returns (uint256 balance)'])
const client = createMemoryClient()
const result = await client.tevmCall({
to: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', // WETH
from: PREFUNDED_ACCOUNTS[0].address,
deployedBytecode: ERC20.deployedBytecode,
data: encodeFunctionData({
abi,
functionName: 'balanceOf',
args: [PREFUNDED_ACCOUNTS[0].address]
})
})
const balance = decodeFunctionResult({ abi, functionName: 'balanceOf', data: result.rawData })Contract Deployment
import { createMemoryClient, PREFUNDED_ACCOUNTS } from 'tevm'
import { SimpleContract } from 'tevm/contract'
import { encodeDeployData } from 'viem'
const client = createMemoryClient()
const result = await client.tevmCall({
from: PREFUNDED_ACCOUNTS[0].address,
data: encodeDeployData(SimpleContract.deploy(2n)),
addToBlockchain: true // auto-mines
})
console.log('Deployed at:', result.createdAddress)State Override
import { createMemoryClient, PREFUNDED_ACCOUNTS } from 'tevm'
const client = createMemoryClient()
const result = await client.tevmCall({
from: PREFUNDED_ACCOUNTS[0].address,
to: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2',
data: '0x',
stateOverrideSet: {
[PREFUNDED_ACCOUNTS[0].address]: {
balance: 4096n,
nonce: 2n,
state: {}
}
}
})Debug Trace
import { createMemoryClient } from 'tevm'
const client = createMemoryClient()
const result = await client.tevmCall({
from: '0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266',
to: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2',
data: '0x',
createTrace: true
})
if (result.trace) {
result.trace.structLogs.forEach(log => {
console.log(log.op, log.stack, log.memory)
})
}EVM Event Handlers
Monitor execution in real-time:
import { createMemoryClient } from 'tevm'
import { encodeFunctionData } from 'viem'
const client = createMemoryClient()
const result = await client.tevmCall({
from: '0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266',
to: contractAddress,
data: encodeFunctionData({ abi, functionName: 'myFunction', args: [arg1, arg2] }),
onStep: (step, next) => {
console.log(
`${step.opcode.name} at PC=${step.pc}`,
`Gas: ${step.gasLeft.toString()}`,
`Stack depth: ${step.stack.length}`
)
next?.()
},
onNewContract: (data, next) => {
console.log(`New contract: ${data.address.toString()}`)
next?.()
},
onBeforeMessage: (message, next) => {
console.log(`Call to: ${message.to?.toString()}`,
`Value: ${message.value.toString()}`,
`Gas limit: ${message.gasLimit.toString()}`)
next?.()
},
onAfterMessage: (result, next) => {
console.log(`Result: ${result.execResult.returnValue.toString('hex')}`,
`Gas used: ${result.execResult.executionGasUsed.toString()}`)
if (result.execResult.exceptionError) {
console.error(`Error: ${result.execResult.exceptionError.error}`)
}
next?.()
}
})Higher Level APIs
While tevmCall

