Overview
Local WASM replay:- Loads WASM files directly from your filesystem
- Executes contracts in a local Soroban environment
- Uses mock state (no real ledger data)
- Captures diagnostic events and logs
- Supports basic argument types
- Enforces Soroban VM compatibility
Local replay uses mock state, not mainnet or testnet data. This mode is intended for rapid contract development and testing, not production debugging.
Quick start
Run a local WASM file:Building contracts for replay
#![no_std]
use soroban_sdk::{contract, contractimpl, symbol_short, Env, Symbol};
#[contract]
pub struct HelloContract;
#[contractimpl]
impl HelloContract {
pub fn hello(env: Env, name: Symbol) -> Symbol {
symbol_short!("Hello")
}
}
Arguments
Local WASM replay supports basic Soroban argument types:Integer arguments
u32 or i32 depending on contract signature.
Symbol/String arguments
Symbol type.
Multiple arguments
Pass multiple--args flags in order:
Complex types (Maps, Vectors, Addresses) are not yet supported. Use integers and symbols for testing.
Example output
Running local WASM replay:Mock state warning
When using--wasm, you’ll always see:
- No real ledger data is available
- Contract storage is empty
- External contract calls may fail
- Token balances are zero
- Authorization checks use mock identities
- Testing pure functions (no storage access)
- Validating computation logic
- Checking WASM compatibility
- Rapid iteration during development
- Unit testing without deployment
- Debugging production failures (use real transaction hash)
- Testing storage interactions (use testnet)
- Validating cross-contract calls (use network)
- Analyzing real user transactions
Soroban compatibility
Erst enforces Soroban VM restrictions:Floating-point detection
The simulator rejects WASM binaries containing floating-point instructions:f32 and f64 usage from your contract:
Determinism enforcement
Erst ensures your contract produces deterministic results:- No floating-point operations
- No system calls (time, random)
- Consistent execution across runs
- Predictable resource consumption
Diagnostic logging
Standard output
By default, Erst shows:- Execution status (success/failure)
- Function result
- Summary of logs and events
- Performance metrics (CPU, memory)
Verbose mode
Enable detailed diagnostics:- Detailed host budget breakdown
- Full event data structures
- WASM module information
- Instruction-level traces
- Memory allocation details
Performance profiling
Generate flamegraphs for local execution:contract.flamegraph.html showing:
- Function call hierarchy
- CPU time per function
- Memory allocation patterns
- Hot paths in execution
Common workflows
Rapid iteration loop
// Modify contract logic
pub fn transfer(env: Env, amount: i128) -> i128 {
// New implementation
amount * 2
}
Pre-deployment validation
Catch issues locally before wasting testnet transactions.
Regression testing
Create a test suite:Compare local vs network
# Deploy
CONTRACT_ID=$(soroban contract deploy --wasm contract.wasm --network testnet)
# Invoke
soroban contract invoke \
--id $CONTRACT_ID \
--network testnet \
-- function_name --arg input
Limitations
Mock state restrictions
Local WASM replay cannot test:- Contract storage reads/writes (storage is empty)
- Cross-contract invocations (no other contracts exist)
- Token transfers (no token contracts)
- Authorization (uses mock signers)
- Time-dependent logic (fixed timestamp)
- Network-specific state
Argument type limitations
Currently supported:- Integers (
u32,i32,u64,i64) - Symbols (short strings)
- Addresses
- Maps
- Vectors
- Custom types
- Bytes
No state persistence
Each replay starts with empty state:Advanced usage
Custom function invocation
By default, Erst invokes the first exported function. To call a specific function:Direct function selection is not yet implemented. Deploy to testnet and use
soroban contract invoke to call specific functions.Batch testing
Test multiple WASM files:Integration with CI/CD
Add to GitHub Actions:Troubleshooting
WASM file not found
- Check file path:
ls -la ./contract.wasm - Use absolute path:
erst debug --wasm /full/path/to/contract.wasm - Verify file exists and is readable
Invalid WASM format
- Rebuild contract:
cargo build --target wasm32-unknown-unknown --release - Verify WASM magic bytes:
hexdump -C contract.wasm | head -n 1 - Check file isn’t corrupted:
file contract.wasm
Execution failed
- Check contract expects the arguments you provided
- Verify contract doesn’t require storage (not available locally)
- Test with
--verbosefor detailed error info - Deploy to testnet for full environment
Floating-point error
- Remove all
f32/f64types from contract - Use fixed-point integer math instead
- Check dependencies don’t use floating-point
- Rebuild with
--release(some debug code uses floats)
Implementation details
Architecture
CLI Layer (Go):internal/cmd/debug.go- Handles--wasmflaginternal/simulator/schema.go- Extended withwasm_path,mock_args
simulator/src/main.rs- Containsrun_local_wasm_replay()- Loads WASM from disk
- Initializes Soroban Host
- Deploys contract to host
- Parses arguments
- Invokes contract function
- Captures diagnostic events
Source files
Local WASM replay implementation:internal/cmd/debug.go- CLI integrationsimulator/src/main.rs- Core replay logicsimulator/src/wasm.rs- WASM loading and validation
Next steps
Debugging failed transactions
Debug real transactions with full network state
Using flamegraphs
Profile local WASM execution performance
Working with sessions
Save local test results for later review