This implementation adds support for storage-seeded symbolic execution, allowing the symbolic analyzer to start from pre-existing storage states rather than just exploring function input combinations. This addresses a critical gap where many real-world bugs depend on ledger state rather than just argument values.
- Added:
storage_seed: Option<PathBuf>field toSymbolicArgsstruct - Purpose: Allows users to specify a JSON file containing initial storage state
- Documentation: Includes clear help text explaining the feature and expected JSON format
- Added:
storage_seed: Option<String>field toSymbolicConfigstruct - Updated: All config builder methods (
fast(),balanced(),deep()) to initialize the new field - Modified:
analyze_with_config()method to apply storage seed before executing each path - Implementation: Uses existing
ContractExecutor::set_initial_storage()method to seed state - Test: Added unit test
analyze_with_storage_seed_uses_initial_state()to verify configuration
- Added imports:
SymbolicConfigandSymbolicProfileto scope - Modified:
symbolic_config_from_args()function to:- Read storage seed file if provided
- Handle file read errors gracefully with user-friendly error messages
- Pass storage JSON to config for use by analyzer
- Created: New test file with comprehensive test coverage
- Tests included:
symbolic_execution_with_storage_seed(): Verifies storage seeding works end-to-endsymbolic_execution_without_storage_seed(): Ensures backward compatibility
- Fixture usage: Uses existing counter contract fixture for realistic testing
- Updated: SYNOPSIS section to include
--storage-seedoption - Added: Complete option description in OPTIONS section
- Enhanced: DESCRIPTION to mention storage state seeding capability
- Created: Automated verification script for the feature
- Checks: All code changes, tests, and documentation updates
- Purpose: Quick validation that all components are present
- User provides a JSON file via
--storage-seed storage.json - CLI reads and parses the file into a JSON string
- Config is updated with the storage seed
- For each symbolic execution path:
- A fresh
ContractExecutoris created - Storage seed is applied via
set_initial_storage() - Function is executed with the generated inputs
- Results include the effect of both storage state and inputs
- A fresh
{
"key1": "value1",
"counter": 42,
"owner": "GABC...DEF"
}The format supports the same typed annotations as the existing --storage parameter:
{
"counter": {"type": "i64", "value": 42},
"balance": {"type": "u64", "value": 1000000}
}- File not found: Clear error message and exit
- Invalid JSON: Propagated from
set_initial_storage()with context - Executor errors: Wrapped with descriptive messages
✅ Symbolic analysis can start from seeded storage/snapshots
- Implemented via
--storage-seedflag - Storage is applied before each path exploration
✅ Tests added/updated
- Unit test in
symbolic.rs - Integration tests in
symbolic_storage_seed_tests.rs
✅ User-facing docs updated
- Manpage updated with new option
- Help text in CLI args
soroban-debug symbolic \
-c my_contract.wasm \
-f transfer \
--storage-seed initial_state.jsonsoroban-debug symbolic \
-c my_contract.wasm \
-f my_function \
--storage-seed state.json \
--profile deep \
--seed 42 \
-o report.toml{
"balances": {
"user1": 1000,
"user2": 500
},
"total_supply": 1500,
"paused": false
}- ✅ No breaking changes to existing API
- ✅
storage_seeddefaults toNone(no change in behavior) - ✅ Existing symbolic execution runs unaffected
- ✅ All existing tests remain valid
src/cli/args.rs- Added storage_seed argumentsrc/analyzer/symbolic.rs- Added storage seed support to analyzersrc/cli/commands.rs- Added storage seed loading and passingman/man1/soroban-debug-symbolic.1- Updated documentationtests/symbolic_storage_seed_tests.rs- New integration teststest_storage_seed_feature.sh- Verification script
- Unit tests: Verify config accepts and stores storage seed
- Integration tests: End-to-end testing with real contracts
- Manual testing: Verified with counter contract example
- Regression testing: Existing tests ensure no breakage
Potential improvements for future iterations:
- Support for loading storage from snapshot files (NetworkSnapshot format)
- Multiple storage seeds in a single run for batch comparison
- Storage state generation/synthesis for edge cases
- Integration with debugger's storage snapshot/restore features
This implementation successfully addresses issue #523 by enabling symbolic execution to explore contract behavior under different storage states, uncovering bugs that depend on ledger state rather than just function inputs. The feature is fully tested, documented, and maintains backward compatibility.