@@ -324,12 +324,14 @@ impl ProjectInfo {
324324 ) ;
325325 // add base type
326326 if base_identifier. starts_with ( "t_struct" ) {
327- let struct_slots: Vec < ( u64 , U256 , Option < String > ) > = vec ! [ (
328- type_name[ "baseType" ] [ "referencedDeclaration" ]
329- . as_u64( )
330- . unwrap( ) ,
327+ let struct_slots_vec: Vec < ( U256 , ( u64 , Option < String > ) ) > = vec ! [ (
331328 U256 :: from( 0 ) ,
332- None ,
329+ (
330+ type_name[ "baseType" ] [ "referencedDeclaration" ]
331+ . as_u64( )
332+ . unwrap( ) ,
333+ None ,
334+ ) ,
333335 ) ] ;
334336 // we only need the types, so we use a dummy storage vector
335337 let mut storage: Vec < StateVariable > = vec ! [ ] ;
@@ -340,7 +342,7 @@ impl ProjectInfo {
340342 sources,
341343 node,
342344 type_defs,
343- & struct_slots ,
345+ & struct_slots_vec ,
344346 types,
345347 & mut storage,
346348 ) ;
@@ -371,15 +373,17 @@ impl ProjectInfo {
371373 . unwrap ( )
372374 . to_string ( ) ;
373375 if identifier. starts_with ( "t_struct" ) {
374- let struct_slots: Vec < ( u64 , U256 , Option < String > ) > = vec ! [ (
375- type_name
376- . get( "referencedDeclaration" )
377- . unwrap( )
378- . as_u64( )
379- . unwrap( ) ,
376+ let struct_slots_vec: Vec < ( U256 , ( u64 , Option < String > ) ) > = Vec :: from ( [ (
380377 U256 :: from_str ( "0x0" ) . unwrap ( ) , // this won't be used as we only have to add the types
381- None ,
382- ) ] ;
378+ (
379+ type_name
380+ . get ( "referencedDeclaration" )
381+ . unwrap ( )
382+ . as_u64 ( )
383+ . unwrap ( ) ,
384+ None ,
385+ ) ,
386+ ) ] ) ;
383387 let mut storage: Vec < StateVariable > = vec ! [ ] ; // this won't be used as we only have to add the types
384388 for source in sources. values ( ) {
385389 if let Some ( ast) = source. ast . clone ( ) {
@@ -388,7 +392,7 @@ impl ProjectInfo {
388392 sources,
389393 top_node,
390394 type_defs,
391- & struct_slots ,
395+ & struct_slots_vec ,
392396 types,
393397 & mut storage,
394398 ) ;
@@ -485,14 +489,14 @@ impl ProjectInfo {
485489 sources : & BTreeMap < PathBuf , SourceFile > ,
486490 node : & EAstNode ,
487491 type_defs : & Types ,
488- struct_slots : & Vec < ( u64 , U256 , Option < String > ) > ,
492+ struct_slots : & Vec < ( U256 , ( u64 , Option < String > ) ) > ,
489493 types : & mut HashMap < String , TypeDescription > ,
490494 storage : & mut Vec < StateVariable > ,
491495 ) {
492496 if node. node_type == NodeType :: StructDefinition && node. id . is_some ( ) {
493497 let mut storage_var_id: Option < usize > = None ;
494498 // parse all struct definitions for each struct -> slot pair.
495- for ( struct_id , slot , name) in struct_slots {
499+ for ( slot , ( struct_id , name) ) in struct_slots {
496500 let struct_id = * struct_id;
497501 let node_id = node. id . unwrap ( ) as u64 ;
498502 if node_id == struct_id {
@@ -638,7 +642,7 @@ impl ProjectInfo {
638642 types : & mut HashMap < String , TypeDescription > ,
639643 ) {
640644 // Tuple: (struct AST ID, slot, name of variable containing the slot)
641- let mut struct_slots: Vec < ( u64 , U256 , Option < String > ) > = vec ! [ ] ;
645+ let mut struct_slots: HashMap < U256 , ( u64 , Option < String > ) > = HashMap :: new ( ) ;
642646 // find pairs (storage slot => struct AST ID)
643647 for source in sources. values ( ) {
644648 if let Some ( ast) = source. ast . clone ( ) {
@@ -647,6 +651,12 @@ impl ProjectInfo {
647651 }
648652 }
649653 }
654+
655+ // Order struct_slots by key for deterministic results
656+ let mut struct_slots_vec: Vec < ( U256 , ( u64 , Option < String > ) ) > =
657+ struct_slots. iter ( ) . map ( |( k, v) | ( * k, v. clone ( ) ) ) . collect ( ) ;
658+ struct_slots_vec. sort_by ( |a, b| a. 0 . cmp ( & b. 0 ) ) ;
659+
650660 // parse the struct members + types
651661 for source in sources. values ( ) {
652662 if let Some ( ast) = source. ast . clone ( ) {
@@ -655,7 +665,7 @@ impl ProjectInfo {
655665 sources,
656666 node,
657667 type_defs,
658- & struct_slots ,
668+ & struct_slots_vec ,
659669 types,
660670 storage,
661671 ) ;
@@ -671,7 +681,7 @@ impl ProjectInfo {
671681 sources : & BTreeMap < PathBuf , SourceFile > ,
672682 node : & EAstNode ,
673683 exported_ids : & Vec < usize > ,
674- struct_slots : & mut Vec < ( u64 , U256 , Option < String > ) > ,
684+ struct_slots : & mut HashMap < U256 , ( u64 , Option < String > ) > ,
675685 ) {
676686 if node. node_type == NodeType :: ContractDefinition
677687 && node. id . is_some ( )
@@ -745,7 +755,7 @@ impl ProjectInfo {
745755 top_node,
746756 stmt_ref[ "declaration" ] . as_u64 ( ) . unwrap ( )
747757 ) {
748- struct_slots. push ( ( struct_id , var_slot , Some ( var_name) ) ) ;
758+ struct_slots. insert ( var_slot , ( struct_id , Some ( var_name) ) ) ;
749759 // if no variable declaration can be found, try to find
750760 // functions with the variable as parameter.
751761 } else if let Some ( ( _, _, function_id, param_id) )
@@ -799,25 +809,15 @@ impl ProjectInfo {
799809 top_node,
800810 var_ref_id. as_u64 ( ) . unwrap ( )
801811 ) {
802- if !struct_slots. iter ( ) . any ( |( _, slot, _) | slot. eq ( & var_slot) ) {
803- struct_slots. push ( ( struct_id, var_slot, Some ( var_name) ) ) ;
804- }
812+ struct_slots. entry ( var_slot) . or_insert ( ( struct_id, Some ( var_name) ) ) ;
805813 }
806814 }
807815 } else if let Some ( slot_value) = arg[ param_id] . get ( "value" ) {
808816 // if a value is passed, use it as slot.
809817 // as we have no associated variable for the slot,
810818 // we use the name of the outer function.
811819 let var_slot = U256 :: from_str ( slot_value. as_str ( ) . unwrap ( ) ) . unwrap ( ) ;
812- if !struct_slots. iter ( ) . any ( |( _, slot, _) | slot. eq ( & var_slot) ) {
813- struct_slots. push (
814- (
815- struct_id,
816- var_slot,
817- Some ( format ! ( "[{}]" , outer_function) )
818- )
819- ) ;
820- }
820+ struct_slots. entry ( var_slot) . or_insert ( ( struct_id, Some ( outer_function) ) ) ;
821821 }
822822 }
823823 }
@@ -855,16 +855,18 @@ impl ProjectInfo {
855855 } else {
856856 function_name = None ;
857857 }
858- struct_slots. push ( (
859- struct_id,
860- U256 :: from_str (
861- slot_value
862- . as_str ( )
863- . unwrap ( ) ,
864- )
865- . unwrap ( ) ,
866- function_name,
867- ) ) ;
858+ let var_slot = U256 :: from_str (
859+ slot_value
860+ . as_str ( )
861+ . unwrap ( ) ,
862+ )
863+ . unwrap ( ) ;
864+ struct_slots
865+ . entry ( var_slot)
866+ . or_insert ( (
867+ struct_id,
868+ function_name,
869+ ) ) ;
868870 }
869871 }
870872 }
0 commit comments