@@ -143,6 +143,11 @@ impl PathState {
143143 . and_then ( |cheats| cheats. gas_price )
144144 . unwrap_or_else ( || executor. tx_env ( ) . gas_price ( ) ) ;
145145 self . gas_price = SymExpr :: constant ( cx, U256 :: from ( gas_price) ) ;
146+ if let Some ( cheats) = executor. inspector ( ) . cheatcodes . as_ref ( ) {
147+ for target in cheats. arbitrary_storage_targets ( ) {
148+ self . world . enable_arbitrary_storage ( target) ;
149+ }
150+ }
146151 }
147152
148153 pub ( crate ) fn child ( & self , frame : CallFrame ) -> Self {
@@ -1475,6 +1480,7 @@ struct SymbolicWorldSnapshot {
14751480 arbitrary_storage_all : bool ,
14761481 zero_init_symbolic_storage : bool ,
14771482 symbolic_address_aliases : HashMap < SymExpr , Address > ,
1483+ replay_storage_slots : HashMap < Symbol , SymbolicReplayStorageSlot > ,
14781484}
14791485
14801486impl From < & SymbolicWorld > for SymbolicWorldSnapshot {
@@ -1494,10 +1500,17 @@ impl From<&SymbolicWorld> for SymbolicWorldSnapshot {
14941500 arbitrary_storage_all : world. arbitrary_storage_all ,
14951501 zero_init_symbolic_storage : world. zero_init_symbolic_storage ,
14961502 symbolic_address_aliases : world. symbolic_address_aliases . clone ( ) ,
1503+ replay_storage_slots : world. replay_storage_slots . clone ( ) ,
14971504 }
14981505 }
14991506}
15001507
1508+ #[ derive( Clone , Debug ) ]
1509+ struct SymbolicReplayStorageSlot {
1510+ address : Address ,
1511+ slot : U256 ,
1512+ }
1513+
15011514#[ derive( Clone , Debug , Default ) ]
15021515pub ( crate ) struct SymbolicWorld {
15031516 storage : Vec < StorageWrite > ,
@@ -1512,6 +1525,7 @@ pub(crate) struct SymbolicWorld {
15121525 arbitrary_storage_all : bool ,
15131526 zero_init_symbolic_storage : bool ,
15141527 symbolic_address_aliases : HashMap < SymExpr , Address > ,
1528+ replay_storage_slots : HashMap < Symbol , SymbolicReplayStorageSlot > ,
15151529 snapshots : HashMap < U256 , SymbolicWorldSnapshot > ,
15161530 next_snapshot_id : u64 ,
15171531}
@@ -1547,7 +1561,7 @@ impl SymbolicWorld {
15471561 }
15481562
15491563 pub ( crate ) fn sload < FEN : FoundryEvmNetwork > (
1550- & self ,
1564+ & mut self ,
15511565 cx : & mut SymCx ,
15521566 executor : & Executor < FEN > ,
15531567 address : Address ,
@@ -1591,6 +1605,22 @@ impl SymbolicWorld {
15911605 self . arbitrary_storage_accounts . insert ( address) ;
15921606 }
15931607
1608+ pub ( crate ) fn replay_storage_assignments (
1609+ & self ,
1610+ model : & SymbolicModel ,
1611+ ) -> Vec < SymbolicStorageAssignment > {
1612+ self . replay_storage_slots
1613+ . iter ( )
1614+ . filter_map ( |( symbol, slot) | {
1615+ model. get ( symbol) . copied ( ) . map ( |value| SymbolicStorageAssignment {
1616+ address : slot. address ,
1617+ slot : slot. slot ,
1618+ value,
1619+ } )
1620+ } )
1621+ . collect ( )
1622+ }
1623+
15941624 pub ( crate ) fn resolve_address ( & self , expr : & SymExpr ) -> Option < Address > {
15951625 expr. as_const ( ) . map ( word_to_address) . or_else ( || {
15961626 self . symbolic_address_aliases . get ( expr) . copied ( ) . or_else ( || {
@@ -1639,6 +1669,7 @@ impl SymbolicWorld {
16391669 self . arbitrary_storage_all = snapshot. arbitrary_storage_all ;
16401670 self . zero_init_symbolic_storage = snapshot. zero_init_symbolic_storage ;
16411671 self . symbolic_address_aliases = snapshot. symbolic_address_aliases ;
1672+ self . replay_storage_slots = snapshot. replay_storage_slots ;
16421673 true
16431674 }
16441675
@@ -1651,15 +1682,21 @@ impl SymbolicWorld {
16511682 }
16521683
16531684 pub ( crate ) fn storage_base < FEN : FoundryEvmNetwork > (
1654- & self ,
1685+ & mut self ,
16551686 cx : & mut SymCx ,
16561687 executor : & Executor < FEN > ,
16571688 address : Address ,
16581689 key : & SymExpr ,
16591690 concrete_key : Option < U256 > ,
16601691 ) -> Result < SymExpr , SymbolicError > {
1661- if self . arbitrary_storage_all || self . arbitrary_storage_accounts . contains ( & address) {
1662- let name = stable_symbol ( "storage" , format ! ( "{address:?}:{key:?}" ) . as_bytes ( ) ) ;
1692+ let has_arbitrary_storage = self . arbitrary_storage_accounts . contains ( & address) ;
1693+ if self . arbitrary_storage_all || has_arbitrary_storage {
1694+ let name = symbolic_storage_symbol ( address, key) ;
1695+ if has_arbitrary_storage && let Some ( slot) = concrete_key. or_else ( || key. as_const ( ) ) {
1696+ self . replay_storage_slots
1697+ . entry ( name. clone ( ) )
1698+ . or_insert ( SymbolicReplayStorageSlot { address, slot } ) ;
1699+ }
16631700 return Ok ( SymExpr :: var_symbol ( cx, name) ) ;
16641701 }
16651702 if let Some ( key) = concrete_key {
@@ -1678,7 +1715,7 @@ impl SymbolicWorld {
16781715 } else if self . zero_init_symbolic_storage {
16791716 Ok ( SymExpr :: zero ( cx) )
16801717 } else {
1681- let name = stable_symbol ( "storage" , format ! ( "{address:?}:{ key:?}" ) . as_bytes ( ) ) ;
1718+ let name = symbolic_storage_symbol ( address , key) ;
16821719 Ok ( SymExpr :: var_symbol ( cx, name) )
16831720 }
16841721 }
@@ -2092,6 +2129,10 @@ impl SymbolicWorld {
20922129 }
20932130}
20942131
2132+ fn symbolic_storage_symbol ( address : Address , key : & SymExpr ) -> Symbol {
2133+ stable_symbol ( "storage" , format ! ( "{address:?}:{key:?}" ) . as_bytes ( ) )
2134+ }
2135+
20952136#[ derive( Clone , Debug ) ]
20962137pub ( crate ) struct SymbolicBlock {
20972138 pub ( crate ) chain_id : SymExpr ,
0 commit comments