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
50 changes: 49 additions & 1 deletion lib/bytecode_verification/parse_json.rs
Original file line number Diff line number Diff line change
Expand Up @@ -598,7 +598,7 @@ impl ProjectInfo {
TypeDescription {
encoding: String::from("inplace"),
label: node.other["canonicalName"].as_str().unwrap().to_string(),
number_of_bytes: (slots + 1) * 32,
number_of_bytes: (slots + usize::from(current_offset != 0)) * 32,
base: None,
key: None,
value: None,
Expand Down Expand Up @@ -1756,3 +1756,51 @@ impl std::fmt::Display for Environment {
.fmt(f)
}
}

#[cfg(test)]
mod tests {
use super::*;
use crate::state::forge_inspect::ForgeInspectLayoutStorage;

#[test]
fn nested_storage_struct_matches_compiler_layout() {
let output: Value =
serde_json::from_str(include_str!("../../tests/fixtures/namespaced_nested.json"))
.unwrap();
let sources: BTreeMap<PathBuf, SourceFile> =
serde_json::from_value(output["sources"].clone()).unwrap();
let expected: ForgeInspectLayoutStorage = serde_json::from_value(
output["contracts"]["NamespacedNested.sol"]["NamespacedNested"]["storageLayout"]
.clone(),
)
.unwrap();
let mut exported_ids = vec![];
ProjectInfo::find_exported_ids(
&sources,
&"NamespacedNested".to_string(),
&mut exported_ids,
);
let mut storage = vec![];
let mut types = HashMap::new();
ProjectInfo::find_storage_structs(
&sources,
&Types::new(),
&exported_ids,
&mut storage,
&mut types,
);

assert_eq!(storage.len(), 1);
let actual = &types[&storage[0].var_type];
let expected = &expected.types[&expected.storage[0].var_type];
assert_eq!(actual.number_of_bytes, expected.number_of_bytes);
let actual_members = actual.members.as_ref().unwrap();
let expected_members = expected.members.as_ref().unwrap();
assert_eq!(actual_members.len(), expected_members.len());
for (actual, expected) in actual_members.iter().zip(expected_members) {
assert_eq!(actual.label, expected.label);
assert_eq!(actual.slot, expected.slot);
assert_eq!(actual.offset, expected.offset);
}
}
}
10 changes: 10 additions & 0 deletions tests/fixtures/NamespacedNested.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.35;
contract NamespacedNested {
struct Inner { uint256[] values; }
struct Layout { Inner inner; uint256 marker; }
Layout private compilerReference;
function layout() internal pure returns (Layout storage s) {
assembly { s.slot := 0 }
}
}
Loading