Skip to content

Debugging

Debug and trace tools for transaction analysis on the chain.

Terminal window
# Trace a transaction (tree view)
ashen debug trace 0xabc123...
# Interactive replay
ashen debug replay 0xabc123... --step
# Gas analysis
ashen debug gas 0xabc123...

Trace an already-included transaction and display the call tree.

Terminal window
ashen debug trace <TX_HASH> [OPTIONS]
Options:
--max-depth <N> Maximum call depth (default: 8)
--format <FORMAT> Output: "tree" (default), "json", "chrome"
-o, --output <PATH> Write to file instead of stdout
--rpc-url <URL> RPC endpoint (env: NODE_RPC_URL)

Examples:

Terminal window
# Human-readable tree
ashen debug trace 0xabc123
# Full JSON (for programmatic use)
ashen debug trace 0xabc123 --format json -o trace.json
# Chrome Trace Format (open in chrome://tracing)
ashen debug trace 0xabc123 --format chrome -o trace.json

Tree output:

Transaction: 0xabc123...
Block: 42
call 0x1234...5678 -> 0xabcd...ef01 (gas: 45000/100000)
input: 0xa9059cbb000000000000000000000000...
storage.write: 0xbalance:alice (gas: 5000)
storage.write: 0xbalance:bob (gas: 5000)
event: 0xabcd...ef01 topics=3
call 0xabcd...ef01 -> 0x9876...5432 (gas: 12000/50000)
storage.read: 0xallowance (gas: 2100)

Trace a read-only view call without submitting a transaction.

Terminal window
ashen debug trace-call <CONTRACT> <CALLDATA> [OPTIONS]
Options:
--origin <ADDRESS> Caller address (defaults to zero)
--gas-limit <N> Gas limit (default: 1000000)
--value <N> Attached value (default: 0)
--format <FORMAT> Output: "tree", "json", "chrome"
-o, --output <PATH> Write to file

Example:

Terminal window
ashen debug trace-call 0xcontract 0x70a08231000000000000000000000000abcdef

Step through a transaction interactively, inspecting state at each operation.

Terminal window
ashen debug replay <TX_HASH> [OPTIONS]
Options:
--step Single-step mode (pause after each operation)
-b, --breakpoint <BP> Set breakpoint(s), repeatable
--rpc-url <URL> RPC endpoint

Breakpoint formats:

FormatDescriptionExample
step:NBreak at operation N--breakpoint step:5
storage:KEYBreak on storage op matching KEY--breakpoint storage:balance
gas:NBreak when gas exceeds N--breakpoint gas:50000

Interactive commands:

KeyAction
Enter / nStep to next operation
s<N>Seek to step N (e.g., s5)
rRun to next breakpoint (or end)
iInspect current operation (full JSON)
b<spec>Add breakpoint (e.g., bstep:10)
qQuit

Example session:

Terminal window
$ ashen debug replay 0xabc123 --step
Replaying 0xabc123 (6 operations, block 42)
Commands: [enter]=step, [n]=next, [s]=seek N, [b]=add breakpoint, [r]=run, [i]=inspect, [q]=quit
[ 0] call 0x1234... -> 0xabcd... (gas: 45000)
storage.write balance:alice
(step 0/5) >
[ 1] call 0xabcd... -> 0x9876... (gas: 12000)
(step 1/5) > i
{
"step": 1,
"depth": 1,
"op_type": "call",
"from": "0xabcd...",
"to": "0x9876...",
"gas_used": 12000
}
(step 1/5) > r
[ 5] call 0x1234... -> 0xabcd... (gas: 45000)
End of trace.

Show gas breakdown for a transaction.

Terminal window
ashen debug gas <TX_HASH> [OPTIONS]
Options:
--rpc-url <URL> RPC endpoint

Output:

Gas Analysis: 0xabc123...
Block: 42
-----------------------------------
Total gas used: 45000
Gas limit: 100000
Utilization: 45.0%
Storage operations (3):
write 0xbalance:ali... (gas: 5000)
write 0xbalance:bob... (gas: 5000)
read 0xallowance... (gas: 2100)
Total storage gas: 12100
Child calls (1):
call 0x1234...5678 -> 0x9876...5432 (gas: 12000, OK)
Terminal window
# 1. Check the transaction status
ashen tx by-hash --tx-hash 0xfailed... --wait
# 2. Get the full trace to see where it failed
ashen debug trace 0xfailed...
# 3. Inspect storage operations step by step
ashen debug replay 0xfailed... --step
# 4. Check gas usage
ashen debug gas 0xfailed...
Terminal window
# 1. Get gas breakdown
ashen debug gas 0xtx...
# 2. Export full trace for analysis
ashen debug trace 0xtx... --format json -o trace.json
# 3. Open in Chrome for visual inspection
ashen debug trace 0xtx... --format chrome -o chrome-trace.json
# Then open chrome://tracing and load chrome-trace.json
Terminal window
# Export both as JSON
ashen debug trace 0xtx_before... --format json -o before.json
ashen debug trace 0xtx_after... --format json -o after.json
# Diff with your preferred tool
diff before.json after.json
# or: jq for structured comparison

The --format chrome option exports traces in Chrome Trace Format, viewable in:

Each call frame becomes a duration event showing gas usage and call depth.

VariableDescriptionDefault
NODE_RPC_URLRPC endpoint URLhttp://127.0.0.1:3030
NODE_AUTH_TOKENBearer auth token(none)

The debug commands use these RPC methods directly:

RPC MethodCLI Command
NodeRpcV1.chain_traceTransactionashen debug trace
NodeRpcV1.chain_traceCallashen debug trace-call
NodeRpcV1.tx_simulate_trace(simulation with trace)
Terminal window
curl -X POST http://localhost:3030/v2/rpc \
-H 'Content-Type: application/json' \
-d '{
"id": 1,
"method": "NodeRpcV1.chain_traceTransaction",
"params": {
"tx_hash": "0xabc123...",
"max_depth": 8
}
}'

The DAP (Debug Adapter Protocol) adapter enables interactive debugging of contract execution directly in VS Code or any DAP-compatible IDE.

Terminal window
# 1. Build the DAP adapter
cargo build -p dap-adapter
# 2. Build your contract with debug symbols
cd contracts/zig_fixture
zig build
# 3. Open VS Code and start debugging (F5)
target/release/ashen-dap
cargo build -p dap-adapter --release

Create or update .vscode/launch.json:

{
"version": "0.2.0",
"configurations": [
{
"name": "Debug Contract",
"type": "ashen-vm",
"request": "launch",
"program": "${workspaceFolder}/contracts/zig_fixture/zig-out/bin/zig_fixture",
"sourceDir": "${workspaceFolder}/contracts/zig_fixture/src",
"stopOnEntry": true,
"trace": true
}
]
}

In VS Code settings, point to the adapter binary:

{
"ashen-vm.adapterPath": "${workspaceFolder}/target/release/ashen-dap"
}
FeatureDescription
BreakpointsSet breakpoints on source lines
Step Over (F10)Execute next operation
Step Into (F11)Step into function calls
Step OutStep out of current function
Step BackTime-travel to previous operation
VariablesInspect registers, memory, storage
Stack TraceView call stack
Continue (F5)Run to next breakpoint
PausePause execution
OptionTypeDescription
programstringPath to contract ELF binary
sourceDirstringPath to source directory for mapping
stopOnEntrybooleanPause at contract entry point
tracebooleanEnable execution trace recording
modestring"launch" or "replay"
txHashstringTransaction hash (replay mode only)
rpcUrlstringRPC endpoint (replay mode only)
1. Set breakpoint at line 28 in main.zig (click gutter)
2. Press F5 to start debugging
3. Execution pauses at entry (stopOnEntry: true)
4. Press F5 to continue to breakpoint
5. Use Variables panel to inspect state:
- Registers: pc, sp, a0-a7
- Memory: heap, stack contents
- Storage: contract storage slots
6. Press F10 to step over
7. Press Shift+F10 to step back (time-travel)
8. Press F5 to continue or Shift+F5 to stop

Debug a contract from the start with specified calldata:

{
"type": "ashen-vm",
"request": "launch",
"program": "path/to/contract.elf",
"calldata": "0x4543484f48656c6c6f"
}

Debug an already-executed transaction:

{
"type": "ashen-vm",
"request": "launch",
"mode": "replay",
"txHash": "0xabc123...",
"rpcUrl": "http://127.0.0.1:3030"
}

Breakpoints show as unverified (gray)

  • Contract must be built with debug symbols
  • Source paths must match exactly
  • Try rebuilding without optimization

“Session not initialized” error

  • Check that ashen-dap binary is accessible
  • Verify VS Code extension configuration

Step back doesn’t work

  • Set trace: true in launch configuration
  • Trace recording must be enabled for time-travel

Variables panel is empty

  • Click on a stack frame first
  • Expand the Registers/Memory/Storage scopes