Anatomy of simulateTransaction

Anatomy of simulateTransaction


Starting from scratch

What is it?

Basically, an RPC method that allows us to simulate a transaction before actually sending it. It is used to estimate the cost of a transaction and to check if the transaction is valid.

It is a POST request to simulateTransaction with the following body:

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "simulateTransaction",
  "params": [
    "AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAEDArczbMia1tLmq7zz4DinMNN0pJ1JtLdqIJPUw3YrGCzYAMHBsgN27lcgB6H2WQvFgyZuJYHa46puOQo9yQ8CVQbd9uHXZaGT2cvhRs7reawctIXtX1s3kTqM9YV"
    {
      "encoding": "base64",
    },
  ]
}

And the response being something similar to:

{
  "jsonrpc": "2.0",
  "result": {
      "context": {
          "apiVersion": "1.18.21",
          "slot": 288109610
      },
      "value": {
          "accounts": null,
          "err": "BlockhashNotFound", // Can be an object on InstructionError
          "innerInstructions": null,
          "logs": [],
          "returnData": null,
          "unitsConsumed": 0
      }
  }
}

Although simulateTransaction behaves similarly to sendTransaction, it is not the same. The difference is that simulateTransaction does not commit the transaction to the network, but rather simulates it, thus not carrying any spend.

Additionally, the response coming from simulateTransaction differs from the one coming from sendTransaction as, even for a failed simulatedTransaction, the response will have the RPC success response format, carrying the error inside the result field.

How does it work?

When the tx is sent, the Solana node, creates a temporary simulated environment that executes the tx's instructions. All state changes, CU consumed and logs are generated and tracked, to be later returned in the response.

Can there be different simulateTransaction outcomes for the same transaction on different RPC nodes?

Short answer: Yes, there can be different outcomes for the same transaction.

There are several reasons why this can happen:

  • State differences: RPC nodes are not in sync with the latest state and are falling behind or the account state they have for involved accounts is outdated
  • Latency: latency can affect how recent each nodes info is
  • Node config: Nodes can have different configurations, for example: different compute unit budget limits
  • Timing-depended: If tx depends on oracles different executions can lead to different outcomes

Links

SolDocs issue on Sol