> **Can't find what you're looking for?** Use `search_docs` on the docs MCP server at `https://viem-21dgls9k9-wevm.vercel.app/api/mcp` to find what you need.

# simulateCalls

Simulates a set of calls for a block, and optionally provides asset changes. Internally uses the [`eth_simulateV1` JSON-RPC method](https://github.com/ethereum/execution-apis/pull/484).

## Usage

:::code-group
```ts twoslash [example.ts]
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)
// @log: [
// @log:   {
// @log:     gasUsed: 21000n,
// @log:     logs: [],
// @log:     status: "success",
// @log:   },
// @log:   {
// @log:     gasUsed: 21000n,
// @log:     logs: [],
// @log:     status: "success",
// @log:   },
// @log: ]
```

```ts twoslash [config.ts] filename="config.ts"
import { createPublicClient, http } from 'viem'
import { mainnet } from 'viem/chains'

export const client = createPublicClient({
  chain: mainnet,
  transport: http(),
})
```
:::

### Contract Calls

The `calls` property also accepts **Contract Calls**, and can be used via the `abi`, `functionName`, and `args` properties.

:::code-group
```ts twoslash [example.ts]
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)
// @log: [
// @log:   {
// @log:     gasUsed: 21000n,
// @log:     logs: [],
// @log:     result: undefined,
// @log:     status: "success",
// @log:   },
// @log:   {
// @log:     gasUsed: 78394n,
// @log:     logs: [...],
// @log:     result: undefined,
// @log:     status: "success",
// @log:   },
// @log:   {
// @log:     gasUsed: 51859n,
// @log:     logs: [...],
// @log:     result: true,
// @log:     status: "success",
// @log:   },
// @log: ]
```

```ts twoslash [config.ts] filename="config.ts"
import { createPublicClient, http } from 'viem'
import { mainnet } from 'viem/chains'

export const client = createPublicClient({
  chain: mainnet,
  transport: http(),
})
```
:::

### Asset Changes

Providing the `traceAssetChanges` parameter (with an `account`) will return asset balance changes for the calls.

:::code-group
```ts twoslash [example.ts]
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, // [!code hl]
})

console.log(assetChanges)
// @log: [
// @log:   {
// @log:     token: {
// @log:       address: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
// @log:       decimals: 18,
// @log:       symbol: "ETH",
// @log:     },
// @log:     value: {
// @log:       diff: -1500000000000000000n,
// @log:       post: 9850000000000000000000n,
// @log:       pre: 10000000000000000000000n,
// @log:     },
// @log:   }
// @log:   {
// @log:     token: {
// @log:       address: "0xfba3912ca04dd458c843e2ee08967fc04f3579c2",
// @log:       decimals: 1,
// @log:       symbol: "WAGMI",
// @log:     },
// @log:     value: {
// @log:       diff: 1n,
// @log:       post: 1n,
// @log:       pre: 0n,
// @log:     },
// @log:   },
// @log:   {
// @log:     token: {
// @log:       address: "0x95ad61b0a150d79219dcf64e1e6cc01f0b64c4ce",
// @log:       decimals: 18,
// @log:       symbol: "SHIB",
// @log:     },
// @log:     value: {
// @log:       diff: -1000000000000000000n,
// @log:       post: 410429569258816445970930282571360n,
// @log:       pre: 410429569258817445970930282571360n,
// @log:     },
// @log:   }
// @log: ]
```

```ts twoslash [config.ts] filename="config.ts"
import { createPublicClient, http } from 'viem'
import { mainnet } from 'viem/chains'

export const client = createPublicClient({
  chain: mainnet,
  transport: http(),
})
```
:::

### Reading Contracts

It is also worth noting that `simulateCalls` also supports "reading" contracts.

:::code-group
```ts twoslash [example.ts]
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)
// @log: [
// @log:   {
// @log:     result: 424122n,
// @log:     status: "success",
// @log:   },
// @log:   {
// @log:     result: "0xc961145a54C96E3aE9bAA048c4F4D6b04C13916b",
// @log:     status: "success",
// @log:   },
// @log:   {
// @log:     error: [ContractFunctionExecutionError: token has no owner],
// @log:     status: "failure",
// @log:   },
// @log: ]
```

```ts twoslash [config.ts] filename="config.ts"
import { createPublicClient, http } from 'viem'
import { mainnet } from 'viem/chains'

export const client = createPublicClient({
  chain: mainnet,
  transport: http(),
})
```
:::

## Return Value

`SimulateCallsReturnType`

Simulation results.

## Parameters

### calls

* **Type:** `Calls`

Calls to simulate.

```ts twoslash
import { parseEther } from 'viem'
import { client } from './config'
// ---cut---
const { results } = await client.simulateCalls({
  account: '0x5a0b54d5dc17e482fe8b0bdca5320161b95fb929',
  calls: [ // [!code focus]
    { // [!code focus]
      to: '0xcb98643b8786950F0461f3B0edf99D88F274574D', // [!code focus]
      value: parseEther('2'), // [!code focus]
    }, // [!code focus] 
    { // [!code focus]
      to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8', // [!code focus]
      value: parseEther('1'), // [!code focus]
    }, // [!code focus]
  ], // [!code focus]
})
```

### calls.data

* **Type:** `Hex`

Calldata to broadcast (typically a contract function selector with encoded arguments, or contract deployment bytecode).

```ts twoslash
import { parseEther } from 'viem'
import { client } from './config'
// ---cut---
const { results } = await client.simulateCalls({
  account: '0x5a0b54d5dc17e482fe8b0bdca5320161b95fb929',
  calls: [ 
    { 
      data: '0xdeadbeef', // [!code focus]
      to: '0xcb98643b8786950F0461f3B0edf99D88F274574D', 
      value: parseEther('2'), 
    },  
  ], 
})
```

### calls.to

* **Type:** `Address`

The recipient address.

```ts twoslash
import { parseEther } from 'viem'
import { client } from './config'
// ---cut---
const { results } = await client.simulateCalls({
  account: '0x5a0b54d5dc17e482fe8b0bdca5320161b95fb929',
  calls: [ 
    { 
      to: '0xcb98643b8786950F0461f3B0edf99D88F274574D', // [!code focus]
      value: parseEther('2'),
    },  
  ], 
})
```

### calls.value

* **Type:** `Address`

Value to send with the call.

```ts twoslash
import { parseEther } from 'viem'
import { client } from './config'
// ---cut---
const { results } = await client.simulateCalls({
  account: '0x5a0b54d5dc17e482fe8b0bdca5320161b95fb929',
  calls: [ 
    { 
      to: '0xcb98643b8786950F0461f3B0edf99D88F274574D',
      value: parseEther('2'), // [!code focus]
    },  
  ], 
})
```

#### calls.dataSuffix

* **Type:** Hex

Data to append to the end of the calldata.

```ts twoslash [example.ts]
import { parseAbi } from 'viem'
import { client } from './config'

const abi = parseAbi([
  'function approve(address, uint256) returns (bool)',
])
 // ---cut---
const { id } = await client.simulateCalls({
  calls: [
    {
      to: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2',
      abi,
      functionName: 'approve',
      args: [
        '0xa5cc3c03994DB5b0d9A5eEdD10CabaB0813678AC', 
        100n
      ],
      dataSuffix: '0xdeadbeef' // [!code focus]
    }
  ],
})
```

### account (optional)

* **Type:** `Account | Address`

The account to simulate the calls from.

```ts twoslash
import { parseEther } from 'viem'
import { client } from './config'
// ---cut---
const { results } = await client.simulateCalls({
  account: '0x5a0b54d5dc17e482fe8b0bdca5320161b95fb929', // [!code focus]
  calls: [ 
    { 
      to: '0xcb98643b8786950F0461f3B0edf99D88F274574D',
      value: parseEther('2'),
    },  
  ], 
})
```

### blockNumber (optional)

* **Type:** `bigint`

The block number to simulate the calls at.

```ts twoslash
import { parseEther } from 'viem'
import { client } from './config'
// ---cut---
const { results } = await client.simulateCalls({
  blockNumber: 17030000n, // [!code focus]
  calls: [ 
    { 
      to: '0xcb98643b8786950F0461f3B0edf99D88F274574D',
      value: parseEther('2'),
    },  
  ], 
})
```

### blockTag (optional)

* **Type:** `BlockTag`

The block tag to simulate the calls at.

```ts twoslash
import { parseEther } from 'viem'
import { client } from './config'
// ---cut---
const { results } = await client.simulateCalls({
  blockTag: 'pending', // [!code focus]
  calls: [ 
    { 
      to: '0xcb98643b8786950F0461f3B0edf99D88F274574D',
      value: parseEther('2'),
    },  
  ], 
})
```

### stateOverrides (optional)

* **Type:** `StateOverride`

The state overrides to simulate the calls with.

```ts twoslash
import { parseEther } from 'viem'
import { client } from './config'
// ---cut---
const { results } = await client.simulateCalls({
  account: '0x5a0b54d5dc17e482fe8b0bdca5320161b95fb929',
  calls: [ 
    { 
      to: '0xcb98643b8786950F0461f3B0edf99D88F274574D',
      value: parseEther('2'),
    },  
  ], 
  stateOverrides: [{ // [!code focus]
    address: '0x5a0b54d5dc17e482fe8b0bdca5320161b95fb929', // [!code focus]
    balance: parseEther('10000'), // [!code focus]
  }], // [!code focus]
})
```

### traceAssetChanges (optional)

* **Type:** `boolean`

Whether to trace asset changes. Requires an `account`.

The `pending` block tag is supported, but discovery and balance measurement use
separate requests. Pending state can change between them, so the results are not pinned
to one pending snapshot.

Assets are discovered by simulating the batch and inspecting the `Transfer` logs it
emits, along with the `to` address of each call. Discovery therefore accounts for your
`stateOverrides`, runs at the requested block, and sees state produced by earlier calls
in the batch.

Two kinds of balance are not traced:

* ERC1155. Its `balanceOf` takes a token id, so those balances cannot be read by the same
  probe.
* Tokens whose balance changes without emitting a `Transfer` that the account
  participates in (some rebasing and non-standard tokens).

```ts twoslash
import { parseEther } from 'viem'
import { client } from './config'
// ---cut---
const { results } = await client.simulateCalls({
  account: '0x5a0b54d5dc17e482fe8b0bdca5320161b95fb929',
  calls: [ 
    { 
      to: '0xcb98643b8786950F0461f3B0edf99D88F274574D',
      value: parseEther('2'),
    },  
  ], 
  traceAssetChanges: true, // [!code focus]
})
```

### traceTransfers (optional)

* **Type:** `boolean`

Whether to trace transfers.

```ts twoslash
import { parseEther } from 'viem'
import { client } from './config'
// ---cut---
const { results } = await client.simulateCalls({
  account: '0x5a0b54d5dc17e482fe8b0bdca5320161b95fb929',
  calls: [ 
    { 
      to: '0xcb98643b8786950F0461f3B0edf99D88F274574D',
      value: parseEther('2'),
    },  
  ], 
  traceTransfers: true, // [!code focus]
})
```

### validation (optional)

* **Type:** `boolean`

Whether to enable validation mode.

```ts twoslash
import { parseEther } from 'viem'
import { client } from './config'
// ---cut---
const { results } = await client.simulateCalls({
  account: '0x5a0b54d5dc17e482fe8b0bdca5320161b95fb929',
  calls: [ 
    { 
      to: '0xcb98643b8786950F0461f3B0edf99D88F274574D',
      value: parseEther('2'),
    },  
  ], 
  validation: true, // [!code focus]
})
```
