Skip to content

SimulateTransactions

Simulates a given sequence of transactions on the requested state and generates execution traces. Each transaction is simulated on the state resulting from applying all the previous ones.

Method Signature

func (provider *Provider) SimulateTransactions(ctx context.Context, blockID BlockID, txns []BroadcastTxn, simulationFlags []SimulationFlag) ([]SimulatedTransaction, error)

Parameters

  • ctx - Context for request cancellation and timeout
  • blockID - Block identifier to simulate against (number, hash, or tag)
  • txns - Array of transactions to simulate
  • simulationFlags - Flags describing what parts of the transaction should be executed

Transaction Reverts and Error Handling

Important: SimulateTransactions has special error handling behavior:

Reverted Transactions

  • No error is thrown when transactions revert during simulation
  • Revert details are captured in the revert_error property of the trace
  • The simulation continues and returns results with revert information
  • Check the is_reverted field and revert_reason in execution traces

Error Types

  1. Transaction Reverts: Included in results with revert details
  2. Validation Failures: Result in TRANSACTION_EXECUTION_ERROR
  3. Unexpected Errors: Result in TRANSACTION_EXECUTION_ERROR

Sequential Simulation

When simulating multiple transactions, each transaction runs on the state resulting from applying all previous ones in the array.

Simulation Flags

const (
    SKIP_FEE_CHARGE SimulationFlag = "SKIP_FEE_CHARGE"  // Skip fee charging
    SKIP_VALIDATE   SimulationFlag = "SKIP_VALIDATE"    // Skip signature validation
)

Returns

  • []SimulatedTransaction - Array of simulation results containing traces and fee estimates
  • error - Error if the request fails

Usage Example

package main
 
import (
    "context"
    "encoding/json"
    "fmt"
    "log"
	"os"
 
    "github.com/NethermindEth/starknet.go/rpc"
    "github.com/NethermindEth/juno/core/felt"
)
 
func main() {
    // Create RPC client
	// Get RPC URL from environment variable
	rpcURL := os.Getenv("STARKNET_RPC_URL")
	if rpcURL == "" {
		log.Fatal("STARKNET_RPC_URL not set in environment")
	}
 
	ctx := context.Background()
    client, err := rpc.NewProvider(ctx, rpcURL)
    if err != nil {
        log.Fatal("Failed to create client:", err)
    }
 
    // Create transaction for simulation
    contractAddress, _ := new(felt.Felt).SetString("0x07065cf1a38963beb3ae30198a9aea599c29eed2078130bbab45470ad876f48a")
    selectorFelt, _ := new(felt.Felt).SetString("0x1a35984e05126dbecb7c3bb9929e7dd9106d460c59b1633739a5c733a5fb13b")
    
    invokeTxn := rpc.InvokeTxnV3{
        Type:          rpc.TransactionType_Invoke,
        SenderAddress: contractAddress,
        Calldata: []*felt.Felt{
            new(felt.Felt).SetUint64(1),
            contractAddress,
            selectorFelt,
            new(felt.Felt).SetUint64(0),
        },
        Version: rpc.TransactionV3,
        Nonce:   new(felt.Felt).SetUint64(3),
        ResourceBounds: &rpc.ResourceBoundsMapping{
            L1Gas: rpc.ResourceBounds{
                MaxAmount:       rpc.U64("0x0"),
                MaxPricePerUnit: rpc.U128("0x51ecf881cce4"),
            },
            L2Gas: rpc.ResourceBounds{
                MaxAmount:       rpc.U64("0x15c2a0"),
                MaxPricePerUnit: rpc.U128("0x10c388d00"),
            },
            L1DataGas: rpc.ResourceBounds{
                MaxAmount:       rpc.U64("0xc0"),
                MaxPricePerUnit: rpc.U128("0xdb61"),
            },
        },
        Tip:                     rpc.U64("0x0"),
        PayMasterData:           []*felt.Felt{},
        AccountDeploymentData:   []*felt.Felt{},
        NonceDataMode:           rpc.DAModeL1,
        FeeMode:                 rpc.DAModeL1,
        Signature:               []*felt.Felt{},
    }
 
    // Simulate transaction with SKIP_VALIDATE flag
    simResult, err := client.SimulateTransactions(
        context.Background(),
        rpc.WithBlockTag("latest"),
        []rpc.BroadcastTxn{invokeTxn},
        []rpc.SimulationFlag{rpc.SKIP_VALIDATE},
    )
    if err != nil {
        log.Fatal("Failed to simulate transaction:", err)
    }
 
    // Print simulation results
    resultJSON, _ := json.MarshalIndent(simResult, "", "  ")
    fmt.Printf("Simulation Result:\n%s\n", resultJSON)
}

Expected Output Structure

The response contains an array of SimulatedTransaction objects, each with:

Transaction Trace

Detailed execution flow of the transaction:

{
  "transaction_trace": {
    "execute_invocation": {
      "contract_address": "0x7065cf1a38963beb3ae30198a9aea599c29eed2078130bbab45470ad876f48a",
      "entry_point_selector": "0x15d40a3d6ca2ac30f4031e42be28da9b056fef9bb7357ac5e85627ee876e5ad",
      "calldata": [...],
      "result": ["0x1", "0x1", "0x79e27ef8b5e0a716b77dd2015329ce74b4b9b1628b546fe89298bc42db08808"],
      "calls": [...],
      "execution_resources": {
        "l1_gas": 0,
        "l2_gas": 280000
      },
      "is_reverted": false
    },
    "fee_transfer_invocation": {
      "contract_address": "0x4718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d",
      "calldata": ["0x1176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8", "0x8beaaa91c9c00", "0x0"],
      "execution_resources": {
        "l1_gas": 0,
        "l2_gas": 189030
      }
    },
    "state_diff": {
      "storage_diffs": [...],
      "nonces": [
        {
          "contract_address": "0x7065cf1a38963beb3ae30198a9aea599c29eed2078130bbab45470ad876f48a",
          "nonce": "0x4"
        }
      ]
    },
    "execution_resources": {
      "l1_gas": 0,
      "l1_data_gas": 128,
      "l2_gas": 820480
    }
  }
}

Fee Estimation

Comprehensive fee breakdown:

{
  "fee_estimation": {
    "l1_gas_consumed": "0x0",
    "l1_gas_price": "0x35955904c193",
    "l2_gas_consumed": "0xc8500",
    "l2_gas_price": "0xb2d05e00",
    "l1_data_gas_consumed": "0x80",
    "l1_data_gas_price": "0x8d38",
    "overall_fee": "0x8beaaa91c9c00",
    "unit": "FRI"
  }
}

Error Handling

SimulateTransactions has unique error handling behavior:

Transaction Reverts:
// Reverted transactions don't cause method errors
simResult, err := client.SimulateTransactions(ctx, blockID, txns, flags)
if err != nil {
    // Only validation failures or unexpected errors reach here
    log.Printf("Simulation failed: %v", err)
    return
}
 
// Check individual transactions for reverts
for i, result := range simResult {
    if result.TxnTrace.ExecuteInvocation.IsReverted {
        fmt.Printf("Transaction %d reverted: %s\n", i, result.TxnTrace.ExecuteInvocation.RevertReason)
    }
}
Error Categories:
  • Method errors (err != nil): Validation failures, unexpected errors
  • Transaction reverts: Captured in trace with is_reverted: true and revert_reason
  • Execution success: Normal completion with is_reverted: false

Related Methods