Simulate
The simulator performs eth_call dry runs with optional debug_traceCall tracing. It resolves chain profiles, dials RPC, and returns structured results with gas estimates and revert reasons.
Source file: internal/simulate/simulate.go
The simulator performs eth_call dry runs with optional debug_traceCall tracing. It is the backend for both the simulate verb and the call verb when simulate_only: true.
Design decisions
Chain resolution
The simulator resolves the target chain from three sources, in priority order:
- Inline
rpc_urlon the request (anonymous inline chain) chain_idon the request (matched against presets or custom profiles by id or numeric chain-id)- Active chain from the registry
Timeout
All calls use a 30-second context timeout. This prevents hung RPC calls from blocking the daemon.
Gas estimation alongside eth_call
The simulator runs EstimateGas in parallel with CallMessage. The gas estimate is returned even when the call reverts, giving agents insight into the cost of a reverted call.
Trace support
When req.Trace is true, the simulator calls debug_traceCall with disableStorage: true to reduce trace size. The trace is returned as raw JSON (any). If tracing fails (node does not support it), the trace is silently omitted.
SimulateRequest
type SimulateRequest struct {
ChainID string `json:"chain_id,omitempty"`
RPCURL string `json:"rpc_url,omitempty"`
From string `json:"from,omitempty"`
To string `json:"to"`
Data string `json:"data,omitempty"`
Value string `json:"value,omitempty"`
Block string `json:"block,omitempty"`
Trace bool `json:"trace,omitempty"`
}
SimulateResponse
type SimulateResponse struct {
Result string `json:"result,omitempty"`
GasEstimate uint64 `json:"gas_estimate,omitempty"`
Revert string `json:"revert,omitempty"`
Trace any `json:"trace,omitempty"`
}
Error handling
| Code | Meaning |
|---|---|
SIMULATE_FAILED | eth_call returned an error (revert reason captured in data.revert) |
INVALID_REQUEST | Missing to field |
CHAIN_NOT_FOUND | Could not resolve chain profile |
CHAIN_RPC_FAILED | RPC dial error |
Modifying the simulator
| What to change | Where |
|---|---|
| Change timeout | internal/simulate/simulate.go - context.WithTimeout (30s) |
| Add state override support | internal/evm/client.go - CallMessage signature |
| Add access list generation | internal/evm/client.go - new CreateAccessList method |
