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'), 
    },  
  ], 
})calls.dataSuffix
- Type: Hex
Data to append to the end of the calldata.
const { id } = await client.simulateCalls({
  calls: [
    {
      to: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2',
      abi,
      functionName: 'approve',
      args: [
        '0xa5cc3c03994DB5b0d9A5eEdD10CabaB0813678AC', 
        100n
      ],
      dataSuffix: '0xdeadbeef'
    }
  ],
})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, 
})
