Repository: crytic/slither

Issue:
[Bug]: constant folding is failing on negated negatives (array slicing?)
### What happened?

Slither fails to parse the constants in the below code, but it is considered valid solidity syntax.

### Can you share code with us to reproduce this bug?

https://github.com/ethereum/solidity/blob/develop/test/libsolidity/syntaxTests/constantEvaluator/unary_fine.sol
```
contract C {
    int8 constant a = -7;
    function f() public pure {
        uint[-a] memory x;
        x[0] = 2;
    }
}
```

### Version

0.8.2

### Relevant log output

```shell
Traceback (most recent call last):
  File "/Users/alpharush/solidity/test/libsolidity/syntaxTests/test.py", line 17, in <module>
    Slither(test, disallow_partial=True)
  File "/Users/alpharush/Desktop/slither/slither/slither.py", line 120, in __init__
    parser.parse_contracts()
  File "/Users/alpharush/Desktop/slither/slither/solc_parsing/slither_compilation_unit_solc.py", line 435, in parse_contracts
    self._analyze_third_part(contracts_to_be_analyzed, libraries)
  File "/Users/alpharush/Desktop/slither/slither/solc_parsing/slither_compilation_unit_solc.py", line 541, in _analyze_third_part
    self._analyze_variables_modifiers_functions(contract)
  File "/Users/alpharush/Desktop/slither/slither/solc_parsing/slither_compilation_unit_solc.py", line 614, in _analyze_variables_modifiers_functions
    contract.analyze_content_functions()
  File "/Users/alpharush/Desktop/slither/slither/solc_parsing/declarations/contract.py", line 378, in analyze_content_functions
    function_parser.analyze_content()
  File "/Users/alpharush/Desktop/slither/slither/solc_parsing/declarations/function.py", line 302, in analyze_content
    local_var_parser.analyze(self)
  File "/Users/alpharush/Desktop/slither/slither/solc_parsing/variables/variable_declaration.py", line 190, in analyze
    self._variable.type = parse_type(self._elem_to_parse, caller_context)
  File "/Users/alpharush/Desktop/slither/slither/solc_parsing/solidity_types/type_parsing.py", line 367, in parse_type
    return ArrayType(array_type, length)
  File "/Users/alpharush/Desktop/slither/slither/core/solidity_types/array_type.py", line 22, in __init__
    cf = ConstantFolding(length, "uint256")
  File "/Users/alpharush/Desktop/slither/slither/visitors/expression/constants_folding.py", line 27, in __init__
    super().__init__(expression)
  File "/Users/alpharush/Desktop/slither/slither/visitors/expression/expression.py", line 30, in __init__
    self._visit_expression(self.expression)
  File "/Users/alpharush/Desktop/slither/slither/visitors/expression/expression.py", line 87, in _visit_expression
    self._visit_unary_operation(expression)
  File "/Users/alpharush/Desktop/slither/slither/visitors/expression/expression.py", line 158, in _visit_unary_operation
    self._visit_expression(expression.expression)
  File "/Users/alpharush/Desktop/slither/slither/visitors/expression/expression.py", line 95, in _visit_expression
    self._post_visit(expression)
  File "/Users/alpharush/Desktop/slither/slither/visitors/expression/expression.py", line 280, in _post_visit
    self._post_identifier(expression)
  File "/Users/alpharush/Desktop/slither/slither/visitors/expression/constants_folding.py", line 38, in _post_identifier
    cf = ConstantFolding(expr, self._type)
  File "/Users/alpharush/Desktop/slither/slither/visitors/expression/constants_folding.py", line 27, in __init__
    super().__init__(expression)
  File "/Users/alpharush/Desktop/slither/slither/visitors/expression/expression.py", line 30, in __init__
    self._visit_expression(self.expression)
  File "/Users/alpharush/Desktop/slither/slither/visitors/expression/expression.py", line 95, in _visit_expression
    self._post_visit(expression)
  File "/Users/alpharush/Desktop/slither/slither/visitors/expression/expression.py", line 307, in _post_visit
    self._post_unary_operation(expression)
  File "/Users/alpharush/Desktop/slither/slither/visitors/expression/constants_folding.py", line 68, in _post_unary_operation
    raise NotConstant
slither.visitors.expression.constants_folding.NotConstant
```



Discussion:

Resolving patch:
diff --git a/slither/visitors/expression/constants_folding.py b/slither/visitors/expression/constants_folding.py
--- a/slither/visitors/expression/constants_folding.py
+++ b/slither/visitors/expression/constants_folding.py
@@ -1,4 +1,4 @@
-from slither.core.expressions import BinaryOperationType, Literal
+from slither.core.expressions import BinaryOperationType, Literal, UnaryOperationType
 from slither.utils.integer_conversion import convert_string_to_int
 from slither.visitors.expression.expression import ExpressionVisitor
 
@@ -65,7 +65,16 @@ def _post_binary_operation(self, expression):
             raise NotConstant
 
     def _post_unary_operation(self, expression):
-        raise NotConstant
+        # Case of uint a = -7; uint[-a] arr;
+        if expression.type == UnaryOperationType.MINUS_PRE:
+            expr = expression.expression
+            if not isinstance(expr, Literal):
+                cf = ConstantFolding(expr, self._type)
+                expr = cf.result()
+            assert isinstance(expr, Literal)
+            set_val(expression, int(expr.value))
+        else:
+            raise NotConstant
 
     def _post_literal(self, expression):
         if expression.value.isdigit():


Test patch:
diff --git a/tests/constant_folding_unary.sol b/tests/constant_folding_unary.sol
new file mode 100644
--- /dev/null
+++ b/tests/constant_folding_unary.sol
@@ -0,0 +1,7 @@
+contract C {
+    int8 constant a = -7;
+    function f() public pure {
+        uint[-a] memory x;
+        x[0] = 2;
+    }
+}
\ No newline at end of file
diff --git a/tests/test_constant_folding_unary.py b/tests/test_constant_folding_unary.py
new file mode 100644
--- /dev/null
+++ b/tests/test_constant_folding_unary.py
@@ -0,0 +1,5 @@
+from slither import Slither
+
+
+def test_constant_folding_unary():
+    Slither("./tests/constant_folding_unary.sol")