Simulate before you send: dry-running transactions with eth_simulateV1

Dry-run multiple transactions and inspect state changes before sending them on-chain using eth_simulateV1. Learn supported chain method policies, execution spec request payloads, CU pricing weights, and AI Agent MCP integration.

Before broadcasting transactions to a blockchain network, dry-running them allows developers to inspect execution results, verify contract state transitions, and observe event logs in advance, avoiding unnecessary gas fees caused by contract reverts.

The Ethereum execution layer provides several ways to evaluate transactions before sending:

  • eth_call: Executes a single read-only message call without state persistence across successive calls.
  • eth_estimateGas: Calculates the gas limit required for execution, but does not provide multi-transaction sequential state transitions or full event logs.
  • eth_simulateV1: Defined in the Ethereum Execution APIs standard specification, this method allows sequential simulation of multiple transactions across blocks, accumulates state changes between transactions, and supports overriding block parameters and account state.

Supported chains and method policy

Network capabilities are published dynamically via GET /v1/chains. Read methods.allow from that response to see which chains allow eth_simulateV1; a chain where it is not listed rejects the call with JSON-RPC error -32601 (method not available, not billed).

Node state conditions

eth_simulateV1 is a state query method:

  • Sync gate (-32010): When the target chain's node is syncing and not yet ready, the call returns -32010 (node is syncing, not billed).
  • State window (-32011): On Robinhood Chain, requests targeting blocks older than the chain's state_window_blocks (GET /v1/chains), or specifying safe, finalized, or earliest block tags, return -32011 (not billed). The default block tag is latest.

Request structure and basic example

According to the execution layer specification (Ethereum Execution APIs eth_simulateV1 definition), eth_simulateV1 accepts two positional parameters:

  1. Payload object:
    • blockStateCalls (required array): An array of simulated block objects. Each object contains an array of transaction calls calls, optional block header overrides blockOverrides, and optional account state overrides stateOverrides.
    • validation (optional boolean, default false): When false, behaves like eth_call; when true, runs all EVM validation except signature checks.
    • traceTransfers (optional boolean): When true, returns event logs for native token transfers.
  2. Block tag (optional string, default 'latest'): Block number, block hash, or block tag.

Basic example: dry-running an ERC-20 transfer

The following example dry-runs an ERC-20 transfer(address,uint256) call on Robinhood Chain. Replace $BLOCKVECTRA_API_KEY with your actual API key:

export BLOCKVECTRA_API_KEY=rgw_your_api_key

curl -s "https://api.blockvectra.com/v1/robinhood_mainnet" \
  -H "Content-Type: application/json" \
  -H "x-api-key: $BLOCKVECTRA_API_KEY" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "eth_simulateV1",
    "params": [
      {
        "blockStateCalls": [
          {
            "calls": [
              {
                "from": "0x1111111111111111111111111111111111111111",
                "to": "0x2222222222222222222222222222222222222222",
                "data": "0xa9059cbb00000000000000000000000033333333333333333333333333333333333333330000000000000000000000000000000000000000000000000de0b6b3a7640000",
                "value": "0x0"
              }
            ]
          }
        ]
      },
      "latest"
    ]
  }'

Inspecting the response structure

Under the Ethereum execution specification, the result field contains an array of simulated block results with the following schema:

Block-level fields

  • number: Block number of the simulated block (hex string).
  • hash: Simulated block hash (32-byte hex string).
  • parentHash: Hash of the parent block.
  • miner: Fee recipient of the simulated block (20-byte hex address prefixed with 0x).
  • timestamp: Block timestamp (hex string).
  • gasLimit: Block gas limit.
  • gasUsed: Total gas consumed across all simulated calls in this block.
  • baseFeePerGas: Base fee per gas for the block.
  • Other block header fields returned by the chain node depend on that node implementation.
  • calls: Array of execution results for each simulated call.

Call-level fields (calls array items)

  • status: Call status as a hex string. 0x1 indicates success, while 0x0 indicates failure or revert.
  • gasUsed: Actual gas consumed by this call (hex string).
  • maxUsedGas (optional): Peak gas used during execution before refunds.
  • returnData: Hex-encoded return data. On a successful ERC-20 transfer, this contains boolean true; on revert, it contains the error selector or revert data.
  • logs: Array of event logs emitted by the call. On success, contains event logs such as Transfer:
    • address: Contract address that emitted the event.
    • topics: Array of 32-byte topic hashes (topics[0] is the event signature hash, such as the Transfer event signature).
    • data: Hex-encoded non-indexed event data.
    • blockNumber, blockHash, transactionHash, transactionIndex, logIndex, removed.
  • error (present on failure): Object containing code (3 for a revert, -32015 for a VM error) and message (such as execution reverted).

Pricing and CU weights

BlockVectra measures consumption in Compute Units (CU). The weight for each JSON-RPC method is published dynamically by GET /v1/plans:

CU weight per call

MethodCU per call
eth_simulateV120
eth_call15
eth_estimateGas20

For unit conversion formulas and top-up details, visit the Pricing page.

Requests rejected — including node syncing (-32010), outside state window (-32011), or method not available (-32601) — are not billed. See Which requests are free for complete billing rules.

Using with AI Agents and MCP

Autonomous AI Agents can invoke eth_simulateV1 directly through BlockVectra's Model Context Protocol (MCP) server.

The keyed rpc_call tool allows executing JSON-RPC methods on supported chains. The API key must be configured in the MCP client HTTP headers (x-api-key: {api_key} or Authorization: Bearer {api_key}), never passed inside tool parameters or conversation prompts.

Example rpc_call tool invocation payload on Robinhood Chain:

{
  "chain": "robinhood_mainnet",
  "method": "eth_simulateV1",
  "params": [
    {
      "blockStateCalls": [
        {
          "calls": [
            {
              "from": "0x1111111111111111111111111111111111111111",
              "to": "0x2222222222222222222222222222222222222222",
              "data": "0xa9059cbb00000000000000000000000033333333333333333333333333333333333333330000000000000000000000000000000000000000000000000de0b6b3a7640000",
              "value": "0x0"
            }
          ]
        }
      ]
    },
    "latest"
  ]
}

Agents can check status === "0x1" to verify contract interaction validity and assess gas consumption before submitting raw transactions. For setup and usage instructions, see the AI Agent integration guide.

Next steps

Last updated:

On this page