Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 37 additions & 37 deletions lib/bytecode_verification/parse_json.rs
Original file line number Diff line number Diff line change
Expand Up @@ -344,15 +344,17 @@ impl ProjectInfo {
.unwrap()
.to_string();
if identifier.starts_with("t_struct") {
let struct_slots: Vec<(u64, U256, Option<String>)> = vec![(
type_name
.get("referencedDeclaration")
.unwrap()
.as_u64()
.unwrap(),
let struct_slots_vec: Vec<(U256, (u64, Option<String>))> = Vec::from([(
U256::from_str("0x0").unwrap(), // this won't be used as we only have to add the types
None,
)];
(
type_name
.get("referencedDeclaration")
.unwrap()
.as_u64()
.unwrap(),
None,
),
)]);
let mut storage: Vec<StateVariable> = vec![]; // this won't be used as we only have to add the types
for source in sources.values() {
if let Some(ast) = source.ast.clone() {
Expand All @@ -361,7 +363,7 @@ impl ProjectInfo {
sources,
top_node,
type_defs,
&struct_slots,
&struct_slots_vec,
types,
&mut storage,
);
Expand Down Expand Up @@ -458,14 +460,14 @@ impl ProjectInfo {
sources: &BTreeMap<PathBuf, SourceFile>,
node: &EAstNode,
type_defs: &Types,
struct_slots: &Vec<(u64, U256, Option<String>)>,
struct_slots: &Vec<(U256, (u64, Option<String>))>,
types: &mut HashMap<String, TypeDescription>,
storage: &mut Vec<StateVariable>,
) {
if node.node_type == NodeType::StructDefinition && node.id.is_some() {
let mut storage_var_id: Option<usize> = None;
// parse all struct definitions for each struct -> slot pair.
for (struct_id, slot, name) in struct_slots {
for (slot, (struct_id, name)) in struct_slots {
let struct_id = *struct_id;
let node_id = node.id.unwrap() as u64;
if node_id == struct_id {
Expand Down Expand Up @@ -611,7 +613,7 @@ impl ProjectInfo {
types: &mut HashMap<String, TypeDescription>,
) {
// Tuple: (struct AST ID, slot, name of variable containing the slot)
let mut struct_slots: Vec<(u64, U256, Option<String>)> = vec![];
let mut struct_slots: HashMap<U256, (u64, Option<String>)> = HashMap::new();
// find pairs (storage slot => struct AST ID)
for source in sources.values() {
if let Some(ast) = source.ast.clone() {
Expand All @@ -620,6 +622,12 @@ impl ProjectInfo {
}
}
}

// Order struct_slots by key for deterministic results
let mut struct_slots_vec: Vec<(U256, (u64, Option<String>))> =
struct_slots.iter().map(|(k, v)| (*k, v.clone())).collect();
struct_slots_vec.sort_by(|a, b| a.0.cmp(&b.0));

// parse the struct members + types
for source in sources.values() {
if let Some(ast) = source.ast.clone() {
Expand All @@ -628,7 +636,7 @@ impl ProjectInfo {
sources,
node,
type_defs,
&struct_slots,
&struct_slots_vec,
types,
storage,
);
Expand All @@ -644,7 +652,7 @@ impl ProjectInfo {
sources: &BTreeMap<PathBuf, SourceFile>,
node: &EAstNode,
exported_ids: &Vec<usize>,
struct_slots: &mut Vec<(u64, U256, Option<String>)>,
struct_slots: &mut HashMap<U256, (u64, Option<String>)>,
) {
if node.node_type == NodeType::ContractDefinition
&& node.id.is_some()
Expand Down Expand Up @@ -718,7 +726,7 @@ impl ProjectInfo {
top_node,
stmt_ref["declaration"].as_u64().unwrap()
) {
struct_slots.push((struct_id, var_slot, Some(var_name)));
struct_slots.insert(var_slot, (struct_id, Some(var_name)));
// if no variable declaration can be found, try to find
// functions with the variable as parameter.
} else if let Some((_, _, function_id, param_id))
Expand Down Expand Up @@ -772,25 +780,15 @@ impl ProjectInfo {
top_node,
var_ref_id.as_u64().unwrap()
) {
if !struct_slots.iter().any(|(_, slot, _)| slot.eq(&var_slot)) {
struct_slots.push((struct_id, var_slot, Some(var_name)));
}
struct_slots.entry(var_slot).or_insert((struct_id, Some(var_name)));
}
}
} else if let Some(slot_value) = arg[param_id].get("value") {
// if a value is passed, use it as slot.
// as we have no associated variable for the slot,
// we use the name of the outer function.
let var_slot = U256::from_str(slot_value.as_str().unwrap()).unwrap();
if !struct_slots.iter().any(|(_, slot, _)| slot.eq(&var_slot)) {
struct_slots.push(
(
struct_id,
var_slot,
Some(format!("[{}]", outer_function))
)
);
}
struct_slots.entry(var_slot).or_insert((struct_id, Some(outer_function)));
}
}
}
Expand Down Expand Up @@ -828,16 +826,18 @@ impl ProjectInfo {
} else {
function_name = None;
}
struct_slots.push((
struct_id,
U256::from_str(
slot_value
.as_str()
.unwrap(),
)
.unwrap(),
function_name,
));
let var_slot = U256::from_str(
slot_value
.as_str()
.unwrap(),
)
.unwrap();
struct_slots
.entry(var_slot)
.or_insert((
struct_id,
function_name,
));
}
}
}
Expand Down
10 changes: 9 additions & 1 deletion lib/dvf/discovery.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,15 @@ pub fn discover_storage_and_events(
);
contract_state.add_forge_inspect(&fi_impl_layout, &fi_impl_ir);

storage_layout.extend(tmp_project_info.storage.clone());
// Extend storage with implementation storage variables, ensuring unique slots
for storage_var in &tmp_project_info.storage {
if !storage_layout
.iter()
.any(|existing| existing.slot == storage_var.slot)
{
storage_layout.push(storage_var.clone());
}
}
types.extend(tmp_project_info.types.clone());
imp_project_info = Some(tmp_project_info);
}
Expand Down
4 changes: 2 additions & 2 deletions tests/expected_dvfs/CrazyHiddenStruct.dvf.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"version": "0.9.1",
"id": "0x71f27bd042cf53e6783d03336d86171f7d728e61f867e60071ae32818de10da2",
"id": "0x294a145622ea4fa416a4fe6395b3a307e7d692e6956c2fd0e2192831c7e776fa",
"contract_name": "CrazyHiddenStruct",
"address": "0x5fbdb2315678afecb367f032d93f642f64180aa3",
"chain_id": 1337,
Expand Down Expand Up @@ -484,7 +484,7 @@
{
"slot": "0xa83659c989cfe332581a2ed207e0e6d23d9199b0de773442a1e23a9b8c5138f0",
"offset": 0,
"var_name": "CrazyHiddenStruct.[_setOwner].AddressSlot.value",
"var_name": "CrazyHiddenStruct._setOwner.AddressSlot.value",
"var_type": "t_address",
"value": "0x5fbdb2315678afecb367f032d93f642f64180aa3",
"comparison_operator": "Equal"
Expand Down
Loading