Repository: crytic/slither

Issue:
Error running Slither 0.7.1: ValueError: invalid literal for int() with base 10: '1.1e18'
I have tried Slither 0.7.0 & 0.7.1 on VSCode and Terminal , still hit this problem..

```
Python 3.9.2
Solc Version: 0.6.9+commit.3e3065ac.Darwin.appleclang
Slither: 0.7.1
```
--------
Here is the log :

```
⸻ Slither: Solidity static analysis framework by Trail of Bits ⸻
Using slither version: 0.7.1
Refreshing explorer...
Loaded 0 issues, displaying 0
⸻ Starting analysis ⸻
Error: Error in workspace "/Users/myname/Documents/-code/code.nosync/projectname/contract-exchange-main":
Traceback (most recent call last):
  File "/usr/local/lib/python3.9/site-packages/slither_analyzer-0.7.1-py3.9.egg/slither/__main__.py", line 721, in main_impl
    ) = process_all(filename, args, detector_classes, printer_classes)
  File "/usr/local/lib/python3.9/site-packages/slither_analyzer-0.7.1-py3.9.egg/slither/__main__.py", line 82, in process_all
    ) = process_single(compilation, args, detector_classes, printer_classes)
  File "/usr/local/lib/python3.9/site-packages/slither_analyzer-0.7.1-py3.9.egg/slither/__main__.py", line 65, in process_single
    slither = Slither(target, ast_format=ast, **vars(args))
  File "/usr/local/lib/python3.9/site-packages/slither_analyzer-0.7.1-py3.9.egg/slither/slither.py", line 102, in __init__
    self._parser.parse_contracts()
  File "/usr/local/lib/python3.9/site-packages/slither_analyzer-0.7.1-py3.9.egg/slither/solc_parsing/slitherSolc.py", line 384, in parse_contracts
    self._analyze_third_part(contracts_to_be_analyzed, libraries)
  File "/usr/local/lib/python3.9/site-packages/slither_analyzer-0.7.1-py3.9.egg/slither/solc_parsing/slitherSolc.py", line 490, in _analyze_third_part
    self._analyze_variables_modifiers_functions(contract)
  File "/usr/local/lib/python3.9/site-packages/slither_analyzer-0.7.1-py3.9.egg/slither/solc_parsing/slitherSolc.py", line 553, in _analyze_variables_modifiers_functions
    contract.analyze_state_variables()
  File "/usr/local/lib/python3.9/site-packages/slither_analyzer-0.7.1-py3.9.egg/slither/solc_parsing/declarations/contract.py", line 519, in analyze_state_variables
    var_parser.analyze(self)
  File "/usr/local/lib/python3.9/site-packages/slither_analyzer-0.7.1-py3.9.egg/slither/solc_parsing/variables/variable_declaration.py", line 181, in analyze
    self._variable.type = parse_type(self._elem_to_parse, caller_context)
  File "/usr/local/lib/python3.9/site-packages/slither_analyzer-0.7.1-py3.9.egg/slither/solc_parsing/solidity_types/type_parsing.py", line 312, in parse_type
    mappingTo = parse_type(t["valueType"], next_context)
  File "/usr/local/lib/python3.9/site-packages/slither_analyzer-0.7.1-py3.9.egg/slither/solc_parsing/solidity_types/type_parsing.py", line 312, in parse_type
    mappingTo = parse_type(t["valueType"], next_context)
  File "/usr/local/lib/python3.9/site-packages/slither_analyzer-0.7.1-py3.9.egg/slither/solc_parsing/solidity_types/type_parsing.py", line 306, in parse_type
    return ArrayType(array_type, length)
  File "/usr/local/lib/python3.9/site-packages/slither_analyzer-0.7.1-py3.9.egg/slither/core/solidity_types/array_type.py", line 22, in __init__
    cf = ConstantFolding(length, "uint256")
  File "/usr/local/lib/python3.9/site-packages/slither_analyzer-0.7.1-py3.9.egg/slither/visitors/expression/constants_folding.py", line 26, in __init__
    super().__init__(expression)
  File "/usr/local/lib/python3.9/site-packages/slither_analyzer-0.7.1-py3.9.egg/slither/visitors/expression/expression.py", line 30, in __init__
    self._visit_expression(self.expression)
  File "/usr/local/lib/python3.9/site-packages/slither_analyzer-0.7.1-py3.9.egg/slither/visitors/expression/expression.py", line 95, in _visit_expression
    self._post_visit(expression)
  File "/usr/local/lib/python3.9/site-packages/slither_analyzer-0.7.1-py3.9.egg/slither/visitors/expression/expression.py", line 280, in _post_visit
    self._post_identifier(expression)
  File "/usr/local/lib/python3.9/site-packages/slither_analyzer-0.7.1-py3.9.egg/slither/visitors/expression/constants_folding.py", line 37, in _post_identifier
    cf = ConstantFolding(expr, self._type)
  File "/usr/local/lib/python3.9/site-packages/slither_analyzer-0.7.1-py3.9.egg/slither/visitors/expression/constants_folding.py", line 26, in __init__
    super().__init__(expression)
  File "/usr/local/lib/python3.9/site-packages/slither_analyzer-0.7.1-py3.9.egg/slither/visitors/expression/expression.py", line 30, in __init__
    self._visit_expression(self.expression)
  File "/usr/local/lib/python3.9/site-packages/slither_analyzer-0.7.1-py3.9.egg/slither/visitors/expression/expression.py", line 48, in _visit_expression
    self._visit_binary_operation(expression)
  File "/usr/local/lib/python3.9/site-packages/slither_analyzer-0.7.1-py3.9.egg/slither/visitors/expression/expression.py", line 104, in _visit_binary_operation
    self._visit_expression(expression.expression_left)
  File "/usr/local/lib/python3.9/site-packages/slither_analyzer-0.7.1-py3.9.egg/slither/visitors/expression/expression.py", line 48, in _visit_expression
    self._visit_binary_operation(expression)
  File "/usr/local/lib/python3.9/site-packages/slither_analyzer-0.7.1-py3.9.egg/slither/visitors/expression/expression.py", line 104, in _visit_binary_operation
    self._visit_expression(expression.expression_left)
  File "/usr/local/lib/python3.9/site-packages/slither_analyzer-0.7.1-py3.9.egg/slither/visitors/expression/expression.py", line 81, in _visit_expression
    self._visit_tuple_expression(expression)
  File "/usr/local/lib/python3.9/site-packages/slither_analyzer-0.7.1-py3.9.egg/slither/visitors/expression/expression.py", line 152, in _visit_tuple_expression
    self._visit_expression(e)
  File "/usr/local/lib/python3.9/site-packages/slither_analyzer-0.7.1-py3.9.egg/slither/visitors/expression/expression.py", line 48, in _visit_expression
    self._visit_binary_operation(expression)
  File "/usr/local/lib/python3.9/site-packages/slither_analyzer-0.7.1-py3.9.egg/slither/visitors/expression/expression.py", line 104, in _visit_binary_operation
    self._visit_expression(expression.expression_left)
  File "/usr/local/lib/python3.9/site-packages/slither_analyzer-0.7.1-py3.9.egg/slither/visitors/expression/expression.py", line 95, in _visit_expression
    self._post_visit(expression)
  File "/usr/local/lib/python3.9/site-packages/slither_analyzer-0.7.1-py3.9.egg/slither/visitors/expression/expression.py", line 280, in _post_visit
    self._post_identifier(expression)
  File "/usr/local/lib/python3.9/site-packages/slither_analyzer-0.7.1-py3.9.egg/slither/visitors/expression/constants_folding.py", line 39, in _post_identifier
    set_val(expression, int(expr.value))
ValueError: invalid literal for int() with base 10: '1.1e18'


⸻ Analysis: 0 succeeded, 1 failed, 0 skipped ⸻
Refreshing explorer...
Loaded 0 issues, displaying 0
```


Discussion:
Hi @jsmjsm 

Thanks for reporting this.  

It seems to be happening in our constant propagation if the constant is used later as the size of an array. Minimal testcase:
```solidity
contract C{
    uint constant test = 1.1e18;
    uint[test] arrays;
}
```
> Hi @jsmjsm
> 
> Thanks for reporting this.
> 
> It seems to be happening in our constant propagation if the constant is used later as the size of an array. Minimal testcase:
> 
> ```solidity
> contract C{
>     uint constant test = 1.1e18;
>     uint[test] arrays;
> }
> ```

I have checked my code, there is no code written in this style.

🎆 I changed the value of constant the  `1.1e18` to `1.1*10**18` and the problem has been solved. 

Resolving patch:
diff --git a/slither/slithir/variables/constant.py b/slither/slithir/variables/constant.py
--- a/slither/slithir/variables/constant.py
+++ b/slither/slithir/variables/constant.py
@@ -1,10 +1,10 @@
-from functools import total_ordering
 from decimal import Decimal
+from functools import total_ordering
 
-from slither.slithir.variables.variable import SlithIRVariable
-from slither.slithir.exceptions import SlithIRError
 from slither.core.solidity_types.elementary_type import ElementaryType, Int, Uint
+from slither.slithir.variables.variable import SlithIRVariable
 from slither.utils.arithmetic import convert_subdenomination
+from slither.utils.integer_conversion import convert_string_to_int
 
 
 @total_ordering
@@ -25,26 +25,7 @@ def __init__(
             assert isinstance(constant_type, ElementaryType)
             self._type = constant_type
             if constant_type.type in Int + Uint + ["address"]:
-                if val.startswith("0x") or val.startswith("0X"):
-                    self._val = int(val, 16)
-                else:
-                    if "e" in val or "E" in val:
-                        base, expo = val.split("e") if "e" in val else val.split("E")
-                        base, expo = Decimal(base), int(expo)
-                        # The resulting number must be < 2**256-1, otherwise solc
-                        # Would not be able to compile it
-                        # 10**77 is the largest exponent that fits
-                        # See https://github.com/ethereum/solidity/blob/9e61f92bd4d19b430cb8cb26f1c7cf79f1dff380/libsolidity/ast/Types.cpp#L1281-L1290
-                        if expo > 77:
-                            if base != Decimal(0):
-                                raise SlithIRError(
-                                    f"{base}e{expo} is too large to fit in any Solidity integer size"
-                                )
-                            self._val = 0
-                        else:
-                            self._val = int(Decimal(base) * Decimal(10 ** expo))
-                    else:
-                        self._val = int(Decimal(val))
+                self._val = convert_string_to_int(val)
             elif constant_type.type == "bool":
                 self._val = (val == "true") | (val == "True")
             else:
diff --git a/slither/utils/integer_conversion.py b/slither/utils/integer_conversion.py
new file mode 100644
--- /dev/null
+++ b/slither/utils/integer_conversion.py
@@ -0,0 +1,25 @@
+from decimal import Decimal
+
+from slither.exceptions import SlitherError
+
+
+def convert_string_to_int(val: str) -> int:
+    if val.startswith("0x") or val.startswith("0X"):
+        return int(val, 16)
+
+    if "e" in val or "E" in val:
+        base, expo = val.split("e") if "e" in val else val.split("E")
+        base, expo = Decimal(base), int(expo)
+        # The resulting number must be < 2**256-1, otherwise solc
+        # Would not be able to compile it
+        # 10**77 is the largest exponent that fits
+        # See https://github.com/ethereum/solidity/blob/9e61f92bd4d19b430cb8cb26f1c7cf79f1dff380/libsolidity/ast/Types.cpp#L1281-L1290
+        if expo > 77:
+            if base != Decimal(0):
+                raise SlitherError(
+                    f"{base}e{expo} is too large to fit in any Solidity integer size"
+                )
+            return 0
+        return int(Decimal(base) * Decimal(10 ** expo))
+
+    return int(Decimal(val))
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,5 @@
 from slither.core.expressions import BinaryOperationType, Literal
+from slither.utils.integer_conversion import convert_string_to_int
 from slither.visitors.expression.expression import ExpressionVisitor
 
 
@@ -36,7 +37,7 @@ def _post_identifier(self, expression):
         if not isinstance(expr, Literal):
             cf = ConstantFolding(expr, self._type)
             expr = cf.result()
-        set_val(expression, int(expr.value))
+        set_val(expression, convert_string_to_int(expr.value))
 
     def _post_binary_operation(self, expression):
         left = get_val(expression.expression_left)


Test patch: