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
28 changes: 25 additions & 3 deletions slither/solc_parsing/solidity_types/type_parsing.py
Original file line number Diff line number Diff line change
Expand Up @@ -295,13 +295,24 @@ def parse_type(
all_structuress = [c.structures for c in scope.contracts.values()]
all_structures = [item for sublist in all_structuress for item in sublist]
all_structures += structures_direct_access
# Include types from accessible (imported) scopes
for accessible in scope.accessible_scopes:
all_structures += list(accessible.structures.values())
for c in accessible.contracts.values():
all_structures += c.structures

enums_direct_access = []
all_enumss = [c.enums for c in scope.contracts.values()]
all_enums = [item for sublist in all_enumss for item in sublist]
all_enums += scope.enums.values()

contracts = scope.contracts.values()
for accessible in scope.accessible_scopes:
all_enums += list(accessible.enums.values())
for c in accessible.contracts.values():
all_enums += c.enums

contracts = list(scope.contracts.values())
for accessible in scope.accessible_scopes:
contracts += list(accessible.contracts.values())
functions = list(scope.functions)

renaming = scope.renaming
Expand All @@ -326,12 +337,23 @@ def parse_type(
all_structuress = [c.structures for c in scope.contracts.values()]
all_structures = [item for sublist in all_structuress for item in sublist]
all_structures += scope.structures.values()
# Include types from accessible (imported) scopes
for accessible in scope.accessible_scopes:
all_structures += list(accessible.structures.values())
for c in accessible.contracts.values():
all_structures += c.structures
enums_direct_access += contract.enums
enums_direct_access += scope.enums.values()
all_enumss = [c.enums for c in scope.contracts.values()]
all_enums = [item for sublist in all_enumss for item in sublist]
all_enums += scope.enums.values()
contracts = scope.contracts.values()
for accessible in scope.accessible_scopes:
all_enums += list(accessible.enums.values())
for c in accessible.contracts.values():
all_enums += c.enums
contracts = list(scope.contracts.values())
for accessible in scope.accessible_scopes:
contracts += list(accessible.contracts.values())
functions = contract.functions + contract.modifiers

renaming = scope.renaming
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {Structs} from "./Structs.sol";

contract Consumer {
Structs.ShiftChanges public currentChanges;
Structs.Nested public nestedData;

function updateShift(uint256 oldShift, uint256 newShift) external {
currentChanges = Structs.ShiftChanges(oldShift, newShift);
}

function getChanges() external view returns (uint256, uint256) {
return (currentChanges.oldShift, currentChanges.newShift);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

library Structs {
struct ShiftChanges {
uint256 oldShift;
uint256 newShift;
}

struct Nested {
ShiftChanges changes;
address updater;
}
}
24 changes: 24 additions & 0 deletions tests/unit/core/test_imported_struct.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
from pathlib import Path
from crytic_compile import CryticCompile
from crytic_compile.platform.solc_standard_json import SolcStandardJson

from slither import Slither

TEST_DATA_DIR = Path(__file__).resolve().parent / "test_data"
IMPORTED_STRUCT_TEST_DATA_DIR = Path(TEST_DATA_DIR, "imported_struct_in_library")


# https://github.com/crytic/slither/issues/2954
def test_imported_struct_from_library(solc_binary_path) -> None:
"""Test that structs defined in an imported library are resolved correctly."""
solc_path = solc_binary_path("0.8.0")
standard_json = SolcStandardJson()
for source_file in IMPORTED_STRUCT_TEST_DATA_DIR.rglob("**/*.sol"):
standard_json.add_source_file(Path(source_file).as_posix())
compilation = CryticCompile(standard_json, solc=solc_path)
sl = Slither(compilation, disallow_partial=True)

# Verify the struct types were resolved correctly
consumer = next(c for c in sl.contracts if c.name == "Consumer")
changes_var = next(v for v in consumer.state_variables if v.name == "currentChanges")
assert "ShiftChanges" in str(changes_var.type)