Repository: crytic/slither

Issue:
ERROR: unresolved reference to identifier _BITMASK_ADDRESS on ERC721A contracts
### Describe the issue:

When using slither to check contracts that inherit from ERC721A we are getting the following error:

```
slither.exceptions.SlitherException: unresolved reference to identifier _BITMASK_ADDRESS
Error:
unresolved reference to identifier _BITMASK_ADDRESS
```

### Code example to reproduce the issue:

```
// SPDX-License-Identifier: MIT
pragma solidity 0.8.16;

import "ERC721A/ERC721A.sol";

contract SlitherERC721AExample is ERC721A {
    constructor() ERC721A("SlitherERC721AExample", "o") {
    }
}
```

### Version:

```
slither --version
0.9.2
```

```
solc --version
solc, the solidity compiler commandline interface
Version: 0.8.16+commit.07a7930e.Linux.g++
```

`forge-std v1.2.0`

### Relevant log output:

```shell
`slither ./src/SlitherERC721AExample.sol 
Traceback (most recent call last):
  File "/usr/lib/python3.10/site-packages/slither/__main__.py", line 834, in main_impl
    ) = process_all(filename, args, detector_classes, printer_classes)
  File "/usr/lib/python3.10/site-packages/slither/__main__.py", line 98, in process_all
    ) = process_single(compilation, args, detector_classes, printer_classes)
  File "/usr/lib/python3.10/site-packages/slither/__main__.py", line 76, in process_single
    slither = Slither(target, ast_format=ast, **vars(args))
  File "/usr/lib/python3.10/site-packages/slither/slither.py", line 133, in __init__
    self._init_parsing_and_analyses(kwargs.get("skip_analyze", False))
  File "/usr/lib/python3.10/site-packages/slither/slither.py", line 143, in _init_parsing_and_analyses
    raise e
  File "/usr/lib/python3.10/site-packages/slither/slither.py", line 139, in _init_parsing_and_analyses
    parser.parse_contracts()
  File "/usr/lib/python3.10/site-packages/slither/solc_parsing/slither_compilation_unit_solc.py", line 519, in parse_contracts
    self._analyze_third_part(contracts_to_be_analyzed, libraries)
  File "/usr/lib/python3.10/site-packages/slither/solc_parsing/slither_compilation_unit_solc.py", line 629, in _analyze_third_part
    self._analyze_variables_modifiers_functions(contract)
  File "/usr/lib/python3.10/site-packages/slither/solc_parsing/slither_compilation_unit_solc.py", line 728, in _analyze_variables_modifiers_functions
    contract.analyze_content_functions()
  File "/usr/lib/python3.10/site-packages/slither/solc_parsing/declarations/contract.py", line 416, in analyze_content_functions
    function_parser.analyze_content()
  File "/usr/lib/python3.10/site-packages/slither/solc_parsing/declarations/function.py", line 312, in analyze_content
    node_parser.analyze_expressions()
  File "/usr/lib/python3.10/site-packages/slither/solc_parsing/yul/parse_yul.py", line 332, in analyze_expressions
    node.analyze_expressions()
  File "/usr/lib/python3.10/site-packages/slither/solc_parsing/yul/parse_yul.py", line 65, in analyze_expressions
    expression = parse_yul(self._scope, self, self._unparsed_expression)
  File "/usr/lib/python3.10/site-packages/slither/solc_parsing/yul/parse_yul.py", line 857, in parse_yul
    op: Expression = parsers.get(ast["nodeType"], parse_yul_unsupported)(root, node, ast)
  File "/usr/lib/python3.10/site-packages/slither/solc_parsing/yul/parse_yul.py", line 698, in parse_yul_assignment
    return _parse_yul_assignment_common(root, node, ast, "variableNames")
  File "/usr/lib/python3.10/site-packages/slither/solc_parsing/yul/parse_yul.py", line 676, in _parse_yul_assignment_common
    rhs = parse_yul(root, node, ast["value"])
  File "/usr/lib/python3.10/site-packages/slither/solc_parsing/yul/parse_yul.py", line 857, in parse_yul
    op: Expression = parsers.get(ast["nodeType"], parse_yul_unsupported)(root, node, ast)
  File "/usr/lib/python3.10/site-packages/slither/solc_parsing/yul/parse_yul.py", line 702, in parse_yul_function_call
    args = [parse_yul(root, node, arg) for arg in ast["arguments"]]
  File "/usr/lib/python3.10/site-packages/slither/solc_parsing/yul/parse_yul.py", line 702, in <listcomp>
    args = [parse_yul(root, node, arg) for arg in ast["arguments"]]
  File "/usr/lib/python3.10/site-packages/slither/solc_parsing/yul/parse_yul.py", line 857, in parse_yul
    op: Expression = parsers.get(ast["nodeType"], parse_yul_unsupported)(root, node, ast)
  File "/usr/lib/python3.10/site-packages/slither/solc_parsing/yul/parse_yul.py", line 819, in parse_yul_identifier
    raise SlitherException(f"unresolved reference to identifier {name}")
slither.exceptions.SlitherException: unresolved reference to identifier _BITMASK_ADDRESS
Error:
unresolved reference to identifier _BITMASK_ADDRESS`
```



Discussion:
For additional info, going back to v0.9.1 resolves the issue
Same issue. Repro [here](https://github.com/nori-dot-eco/contracts/blob/master/contracts/Certificate.sol). 

```bash
slither --version
0.9.2
```

```bash
solc-select versions
0.8.17 (current, set by /home/ubuntu/.solc-select/global-version)
```

```bash
solc --version
solc, the solidity compiler commandline interface
Version: 0.8.17+commit.8df45f5f.Linux.g++
```

```
Traceback (most recent call last):
  File "/home/ubuntu/.pyenv/versions/3.12.0a4/lib/python3.12/site-packages/slither/__main__.py", line 834, in main_impl
    ) = process_all(filename, args, detector_classes, printer_classes)
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/ubuntu/.pyenv/versions/3.12.0a4/lib/python3.12/site-packages/slither/__main__.py", line 98, in process_all
    ) = process_single(compilation, args, detector_classes, printer_classes)
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/ubuntu/.pyenv/versions/3.12.0a4/lib/python3.12/site-packages/slither/__main__.py", line 76, in process_single
    slither = Slither(target, ast_format=ast, **vars(args))
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/ubuntu/.pyenv/versions/3.12.0a4/lib/python3.12/site-packages/slither/slither.py", line 133, in __init__
    self._init_parsing_and_analyses(kwargs.get("skip_analyze", False))
  File "/home/ubuntu/.pyenv/versions/3.12.0a4/lib/python3.12/site-packages/slither/slither.py", line 143, in _init_parsing_and_analyses
    raise e
  File "/home/ubuntu/.pyenv/versions/3.12.0a4/lib/python3.12/site-packages/slither/slither.py", line 139, in _init_parsing_and_analyses
    parser.parse_contracts()
  File "/home/ubuntu/.pyenv/versions/3.12.0a4/lib/python3.12/site-packages/slither/solc_parsing/slither_compilation_unit_solc.py", line 519, in parse_contracts
    self._analyze_third_part(contracts_to_be_analyzed, libraries)
  File "/home/ubuntu/.pyenv/versions/3.12.0a4/lib/python3.12/site-packages/slither/solc_parsing/slither_compilation_unit_solc.py", line 629, in _analyze_third_part
    self._analyze_variables_modifiers_functions(contract)
  File "/home/ubuntu/.pyenv/versions/3.12.0a4/lib/python3.12/site-packages/slither/solc_parsing/slither_compilation_unit_solc.py", line 728, in _analyze_variables_modifiers_functions
    contract.analyze_content_functions()
  File "/home/ubuntu/.pyenv/versions/3.12.0a4/lib/python3.12/site-packages/slither/solc_parsing/declarations/contract.py", line 416, in analyze_content_functions
    function_parser.analyze_content()
  File "/home/ubuntu/.pyenv/versions/3.12.0a4/lib/python3.12/site-packages/slither/solc_parsing/declarations/function.py", line 312, in analyze_content
    node_parser.analyze_expressions()
  File "/home/ubuntu/.pyenv/versions/3.12.0a4/lib/python3.12/site-packages/slither/solc_parsing/yul/parse_yul.py", line 332, in analyze_expressions
    node.analyze_expressions()
  File "/home/ubuntu/.pyenv/versions/3.12.0a4/lib/python3.12/site-packages/slither/solc_parsing/yul/parse_yul.py", line 65, in analyze_expressions
    expression = parse_yul(self._scope, self, self._unparsed_expression)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/ubuntu/.pyenv/versions/3.12.0a4/lib/python3.12/site-packages/slither/solc_parsing/yul/parse_yul.py", line 857, in parse_yul
    op: Expression = parsers.get(ast["nodeType"], parse_yul_unsupported)(root, node, ast)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/ubuntu/.pyenv/versions/3.12.0a4/lib/python3.12/site-packages/slither/solc_parsing/yul/parse_yul.py", line 698, in parse_yul_assignment
    return _parse_yul_assignment_common(root, node, ast, "variableNames")
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/ubuntu/.pyenv/versions/3.12.0a4/lib/python3.12/site-packages/slither/solc_parsing/yul/parse_yul.py", line 676, in _parse_yul_assignment_common
    rhs = parse_yul(root, node, ast["value"])
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/ubuntu/.pyenv/versions/3.12.0a4/lib/python3.12/site-packages/slither/solc_parsing/yul/parse_yul.py", line 857, in parse_yul
    op: Expression = parsers.get(ast["nodeType"], parse_yul_unsupported)(root, node, ast)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/ubuntu/.pyenv/versions/3.12.0a4/lib/python3.12/site-packages/slither/solc_parsing/yul/parse_yul.py", line 702, in parse_yul_function_call
    args = [parse_yul(root, node, arg) for arg in ast["arguments"]]
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/ubuntu/.pyenv/versions/3.12.0a4/lib/python3.12/site-packages/slither/solc_parsing/yul/parse_yul.py", line 702, in <listcomp>
    args = [parse_yul(root, node, arg) for arg in ast["arguments"]]
            ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/ubuntu/.pyenv/versions/3.12.0a4/lib/python3.12/site-packages/slither/solc_parsing/yul/parse_yul.py", line 857, in parse_yul
    op: Expression = parsers.get(ast["nodeType"], parse_yul_unsupported)(root, node, ast)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/ubuntu/.pyenv/versions/3.12.0a4/lib/python3.12/site-packages/slither/solc_parsing/yul/parse_yul.py", line 819, in parse_yul_identifier
    raise SlitherException(f"unresolved reference to identifier {name}")
slither.exceptions.SlitherException: unresolved reference to identifier _BITMASK_ADDRESS
Error:
unresolved reference to identifier _BITMASK_ADDRESS
Please report an issue to https://github.com/crytic/slither/issues


```
Hi. Thank you for reporting this. We will investigate this issue asap

Resolving patch:
diff --git a/slither/solc_parsing/yul/parse_yul.py b/slither/solc_parsing/yul/parse_yul.py
--- a/slither/solc_parsing/yul/parse_yul.py
+++ b/slither/solc_parsing/yul/parse_yul.py
@@ -792,8 +792,9 @@ def parse_yul_identifier(root: YulScope, _node: YulNode, ast: Dict) -> Optional[
             return Identifier(local_variable)
 
         if isinstance(parent_func, FunctionContract):
-            assert parent_func.contract
-            state_variable = parent_func.contract.get_state_variable_from_name(name)
+            # Variables must be looked from the contract declarer
+            assert parent_func.contract_declarer
+            state_variable = parent_func.contract_declarer.get_state_variable_from_name(name)
             if state_variable:
                 return Identifier(state_variable)
 


Test patch:
diff --git a/tests/ast-parsing/compile/yul-state-constant-access.sol-0.8.16-compact.zip b/tests/ast-parsing/compile/yul-state-constant-access.sol-0.8.16-compact.zip
new file mode 100644
Binary files /dev/null and b/tests/ast-parsing/compile/yul-state-constant-access.sol-0.8.16-compact.zip differ
diff --git a/tests/ast-parsing/expected/yul-state-constant-access.sol-0.8.16-compact.json b/tests/ast-parsing/expected/yul-state-constant-access.sol-0.8.16-compact.json
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/expected/yul-state-constant-access.sol-0.8.16-compact.json
@@ -0,0 +1,12 @@
+{
+  "A": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n",
+    "f2()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n}\n",
+    "f3()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n"
+  },
+  "B": {
+    "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n",
+    "f2()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n}\n",
+    "f3()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/ast-parsing/yul-state-constant-access.sol b/tests/ast-parsing/yul-state-constant-access.sol
new file mode 100644
--- /dev/null
+++ b/tests/ast-parsing/yul-state-constant-access.sol
@@ -0,0 +1,25 @@
+contract A{
+	uint private constant a = 10;
+
+	function f() public returns(uint){
+		return a;
+	}
+
+	function f2() public returns(uint){
+		uint ret;
+		assembly{
+			ret := a
+		}
+	}
+
+	function f3() public returns(uint){
+		uint ret;
+		unchecked{
+			ret = a;
+		}
+	}
+}
+
+contract B is A{
+
+}
\ No newline at end of file
diff --git a/tests/test_ast_parsing.py b/tests/test_ast_parsing.py
--- a/tests/test_ast_parsing.py
+++ b/tests/test_ast_parsing.py
@@ -443,6 +443,7 @@ def make_version(minor: int, patch_min: int, patch_max: int) -> List[str]:
     Test("top-level-struct-0.8.0.sol", ["0.8.0"]),
     Test("yul-top-level-0.8.0.sol", ["0.8.0"]),
     Test("complex_imports/import_aliases_issue_1319/test.sol", ["0.5.12"]),
+    Test("yul-state-constant-access.sol", ["0.8.16"]),
 ]
 # create the output folder if needed
 try: