simulateCalls
Simulates a set of calls for a block, and optionally provides asset changes. Internally uses the eth_simulateV1
JSON-RPC method.
Usage
import { parseEther } from 'viem'
import { client } from './config'
const { results } = await client.simulateCalls({
account: '0x5a0b54d5dc17e482fe8b0bdca5320161b95fb929',
calls: [
{
to: '0xcb98643b8786950F0461f3B0edf99D88F274574D',
value: parseEther('2'),
},
{
to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
value: parseEther('1'),
},
],
})
console.log(results)
[ { gasUsed: 21000n, logs: [], status: "success", }, { gasUsed: 21000n, logs: [], status: "success", }, ]
Contract Calls
The calls
property also accepts Contract Calls, and can be used via the abi
, functionName
, and args
properties.
import { parseAbi, parseEther } from 'viem'
import { client } from './config'
const abi = parseAbi([
'function mint()',
'function transfer(address, uint256) returns (bool)',
])
const { results } = await client.simulateCalls({
account: '0x5a0b54d5dc17e482fe8b0bdca5320161b95fb929',
calls: [
{
to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
value: parseEther('1')
},
{
to: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2',
abi,
functionName: 'mint',
},
{
to: '0x95aD61b0a150d79219dCF64E1E6Cc01f0B64C4cE',
abi,
functionName: 'transfer',
args: [
'0xa5cc3c03994DB5b0d9A5eEdD10CabaB0813678AC',
100n
],
},
],
})
console.log(results)
[ { gasUsed: 21000n, logs: [], result: undefined, status: "success", }, { gasUsed: 78394n, logs: [...], result: undefined, status: "success", }, { gasUsed: 51859n, logs: [...], result: true, status: "success", }, ]
Asset Changes
Providing the traceAssetChanges
parameter (with an account
) will return asset balance changes for the calls.
import { parseAbi, parseEther } from 'viem'
import { client } from './config'
const abi = parseAbi([
'function mint()',
'function transfer(address, uint256) returns (bool)',
])
const { assetChanges, results } = await client.simulateCalls({
account: '0x5a0b54d5dc17e482fe8b0bdca5320161b95fb929',
calls: [
{
to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
value: parseEther('1.5')
},
{
to: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2',
abi,
functionName: 'mint',
},
{
to: '0x95aD61b0a150d79219dCF64E1E6Cc01f0B64C4cE',
abi,
functionName: 'transfer',
args: [
'0xa5cc3c03994DB5b0d9A5eEdD10CabaB0813678AC',
100n
],
},
],
traceAssetChanges: true,
})
console.log(assetChanges)
[ { token: { address: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", decimals: 18, symbol: "ETH", }, value: { diff: -1500000000000000000n, post: 9850000000000000000000n, pre: 10000000000000000000000n, }, } { token: { address: "0xfba3912ca04dd458c843e2ee08967fc04f3579c2", decimals: 1, symbol: "WAGMI", }, value: { diff: 1n, post: 1n, pre: 0n, }, }, { token: { address: "0x95ad61b0a150d79219dcf64e1e6cc01f0b64c4ce", decimals: 18, symbol: "SHIB", }, value: { diff: -1000000000000000000n, post: 410429569258816445970930282571360n, pre: 410429569258817445970930282571360n, }, } ]
Reading Contracts
It is also worth noting that simulateCalls
also supports "reading" contracts.
import { parseAbi } from 'viem'
import { client } from './config'
const abi = parseAbi([
'function totalSupply() returns (uint256)',
'function ownerOf(uint256) returns (address)',
])
const { results } = await client.simulateCalls({
calls: [
{
to: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2',
abi,
functionName: 'totalSupply',
},
{
to: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2',
abi,
functionName: 'ownerOf',
args: [69420n],
},
{
to: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2',
abi,
functionName: 'ownerOf',
args: [13371337n],
},
],
})
console.log(results)
[ { result: 424122n, status: "success", }, { result: "0xc961145a54C96E3aE9bAA048c4F4D6b04C13916b", status: "success", }, { error: [ContractFunctionExecutionError: token has no owner], status: "failure", }, ]
Return Value
SimulateCallsReturnType
Simulation results.
Parameters
calls
- Type:
Calls
Calls to simulate.
const { results } = await client.simulateCalls({
account: '0x5a0b54d5dc17e482fe8b0bdca5320161b95fb929',
calls: [
{
to: '0xcb98643b8786950F0461f3B0edf99D88F274574D',
value: parseEther('2'),
},
{
to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
value: parseEther('1'),
},
],
})
calls.data
- Type:
Hex
Calldata to broadcast (typically a contract function selector with encoded arguments, or contract deployment bytecode).
const { results } = await client.simulateCalls({
account: '0x5a0b54d5dc17e482fe8b0bdca5320161b95fb929',
calls: [
{
data: '0xdeadbeef',
to: '0xcb98643b8786950F0461f3B0edf99D88F274574D',
value: parseEther('2'),
},
],
})
calls.to
- Type:
Address
The recipient address.
const { results } = await client.simulateCalls({
account: '0x5a0b54d5dc17e482fe8b0bdca5320161b95fb929',
calls: [
{
to: '0xcb98643b8786950F0461f3B0edf99D88F274574D',
value: parseEther('2'),
},
],
})
calls.value
- Type:
Address
Value to send with the call.
const { results } = await client.simulateCalls({
account: '0x5a0b54d5dc17e482fe8b0bdca5320161b95fb929',
calls: [
{
to: '0xcb98643b8786950F0461f3B0edf99D88F274574D',
value: parseEther('2'),
},
],
})
account (optional)
- Type:
Account | Address
The account to simulate the calls from.
const { results } = await client.simulateCalls({
account: '0x5a0b54d5dc17e482fe8b0bdca5320161b95fb929',
calls: [
{
to: '0xcb98643b8786950F0461f3B0edf99D88F274574D',
value: parseEther('2'),
},
],
})
blockNumber (optional)
- Type:
bigint
The block number to simulate the calls at.
const { results } = await client.simulateCalls({
blockNumber: 17030000n,
calls: [
{
to: '0xcb98643b8786950F0461f3B0edf99D88F274574D',
value: parseEther('2'),
},
],
})
blockTag (optional)
- Type:
BlockTag
The block tag to simulate the calls at.
const { results } = await client.simulateCalls({
blockTag: 'pending',
calls: [
{
to: '0xcb98643b8786950F0461f3B0edf99D88F274574D',
value: parseEther('2'),
},
],
})
stateOverrides (optional)
- Type:
StateOverride
The state overrides to simulate the calls with.
const { results } = await client.simulateCalls({
account: '0x5a0b54d5dc17e482fe8b0bdca5320161b95fb929',
calls: [
{
to: '0xcb98643b8786950F0461f3B0edf99D88F274574D',
value: parseEther('2'),
},
],
stateOverrides: [{
address: '0x5a0b54d5dc17e482fe8b0bdca5320161b95fb929',
balance: parseEther('10000'),
}],
})
traceAssetChanges (optional)
- Type:
boolean
Whether to trace asset changes.
const { results } = await client.simulateCalls({
account: '0x5a0b54d5dc17e482fe8b0bdca5320161b95fb929',
calls: [
{
to: '0xcb98643b8786950F0461f3B0edf99D88F274574D',
value: parseEther('2'),
},
],
traceAssetChanges: true,
})
traceTransfers (optional)
- Type:
boolean
Whether to trace transfers.
const { results } = await client.simulateCalls({
account: '0x5a0b54d5dc17e482fe8b0bdca5320161b95fb929',
calls: [
{
to: '0xcb98643b8786950F0461f3B0edf99D88F274574D',
value: parseEther('2'),
},
],
traceTransfers: true,
})
validation (optional)
- Type:
boolean
Whether to enable validation mode.
const { results } = await client.simulateCalls({
account: '0x5a0b54d5dc17e482fe8b0bdca5320161b95fb929',
calls: [
{
to: '0xcb98643b8786950F0461f3B0edf99D88F274574D',
value: parseEther('2'),
},
],
validation: true,
})