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 timeoutblockID- Block identifier to simulate against (number, hash, or tag)txns- Array of transactions to simulatesimulationFlags- 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_errorproperty of the trace - The simulation continues and returns results with revert information
- Check the
is_revertedfield andrevert_reasonin execution traces
Error Types
- Transaction Reverts: Included in results with revert details
- Validation Failures: Result in
TRANSACTION_EXECUTION_ERROR - 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 estimateserror- 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)
}
}- Method errors (
err != nil): Validation failures, unexpected errors - Transaction reverts: Captured in trace with
is_reverted: trueandrevert_reason - Execution success: Normal completion with
is_reverted: false
Related Methods
- TraceTransaction - Get execution trace of a submitted transaction
- EstimateFee - Estimate fees for transactions
- AddInvokeTransaction - Submit transactions to the network

