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