diff --git a/slither/solc_parsing/yul/parse_yul.py b/slither/solc_parsing/yul/parse_yul.py index 8657947eaf..cf942ea59c 100644 --- a/slither/solc_parsing/yul/parse_yul.py +++ b/slither/solc_parsing/yul/parse_yul.py @@ -748,7 +748,7 @@ def parse_yul_function_call(root: YulScope, node: YulNode, ast: Dict) -> Optiona def _check_for_state_variable_name(root: YulScope, potential_name: str) -> Optional[Identifier]: root_function = root.function if isinstance(root_function, FunctionContract): - var = root_function.contract.get_state_variable_from_name(potential_name) + var = root_function.contract_declarer.get_state_variable_from_name(potential_name) if var: return Identifier(var) return None diff --git a/tests/unit/slithir/test_data/assembly_storage_slot.sol b/tests/unit/slithir/test_data/assembly_storage_slot.sol new file mode 100644 index 0000000000..244f24fe6c --- /dev/null +++ b/tests/unit/slithir/test_data/assembly_storage_slot.sol @@ -0,0 +1,18 @@ +contract YYY { + mapping(address => uint256) private _counters; + function _getPackedBucketGlobalState(uint256 bucketId) internal view returns (uint256 packedGlobalState) { + assembly { + mstore(0x0, bucketId) + mstore(0x20, _counters.slot) + let slot := keccak256(0x0, 0x40) + packedGlobalState := sload(slot) + } + } +} + + +contract XXX is YYY { + function getPackedBucketGlobalState(uint256 bucketId) external { + _getPackedBucketGlobalState(bucketId); + } +} \ No newline at end of file diff --git a/tests/unit/slithir/test_yul_parser_assembly_slot.py b/tests/unit/slithir/test_yul_parser_assembly_slot.py new file mode 100644 index 0000000000..da800b55e0 --- /dev/null +++ b/tests/unit/slithir/test_yul_parser_assembly_slot.py @@ -0,0 +1,40 @@ +from pathlib import Path +from slither import Slither + +from slither.core.expressions import CallExpression +from slither.core.expressions.identifier import Identifier +from slither.core.expressions.literal import Literal +from slither.core.variables.state_variable import StateVariable +from slither.core.variables.local_variable import LocalVariable + + +TEST_DATA_DIR = Path(__file__).resolve().parent / "test_data" + + +def test_yul_parser_assembly_slot(solc_binary_path) -> None: + # mstore(0x0, bucketId) + # mstore(0x20, _counters.slot) + data = {"0x0": "bucketId", "0x20": "_counters"} + + solc_path = solc_binary_path("0.8.18") + slither = Slither(Path(TEST_DATA_DIR, "assembly_storage_slot.sol").as_posix(), solc=solc_path) + + contract = slither.get_contract_from_name("XXX")[0] + func = contract.get_function_from_full_name("getPackedBucketGlobalState(uint256)") + calls = [ + node.expression + for node in func.all_nodes() + if node.expression and "mstore" in str(node.expression) + ] + + for call in calls: + assert isinstance(call, CallExpression) + memory_location = call.arguments[0] + value = call.arguments[1] + assert isinstance(memory_location, Literal) + assert isinstance(value, Identifier) + assert value.value.name == data[memory_location.value] + if value.value.name == "_counters": + assert isinstance(value.value, StateVariable) + elif value.value.name == "bucketId": + assert isinstance(value.value, LocalVariable)