Unify parsing of integers with convert_string_to_int/fraction

pull/1377/head
Emilio López 2 years ago
parent 036f7d62f4
commit ce801942ab
  1. 3
      slither/slithir/variables/constant.py
  2. 29
      slither/utils/arithmetic.py
  3. 16
      slither/utils/integer_conversion.py
  4. 9
      slither/visitors/expression/constants_folding.py

@ -1,4 +1,3 @@
from fractions import Fraction
from functools import total_ordering
from slither.core.solidity_types.elementary_type import ElementaryType, Int, Uint
@ -33,7 +32,7 @@ class Constant(SlithIRVariable):
else:
if val.isdigit():
self._type = ElementaryType("uint256")
self._val = int(Fraction(val))
self._val = convert_string_to_int(val)
else:
self._type = ElementaryType("string")
self._val = val

@ -1,38 +1,35 @@
from fractions import Fraction
from slither.exceptions import SlitherException
from slither.utils.integer_conversion import convert_string_to_int
# pylint: disable=too-many-branches
def convert_subdenomination(
value: str, sub: str
) -> int: # pylint: disable=too-many-return-statements
# to allow 0.1 ether conversion
if value[0:2] == "0x":
decimal_value = Fraction(int(value, 16))
else:
decimal_value = Fraction(value)
decimal_value = convert_string_to_int(value)
if sub == "wei":
return int(decimal_value)
return decimal_value
if sub == "gwei":
return int(decimal_value * int(1e9))
return decimal_value * 1e9
if sub == "szabo":
return int(decimal_value * int(1e12))
return decimal_value * 1e12
if sub == "finney":
return int(decimal_value * int(1e15))
return decimal_value * 1e15
if sub == "ether":
return int(decimal_value * int(1e18))
return decimal_value * 1e18
if sub == "seconds":
return int(decimal_value)
return decimal_value
if sub == "minutes":
return int(decimal_value * 60)
return decimal_value * 60
if sub == "hours":
return int(decimal_value * 60 * 60)
return decimal_value * 60 * 60
if sub == "days":
return int(decimal_value * 60 * 60 * 24)
return decimal_value * 60 * 60 * 24
if sub == "weeks":
return int(decimal_value * 60 * 60 * 24 * 7)
return decimal_value * 60 * 60 * 24 * 7
if sub == "years":
return int(decimal_value * 60 * 60 * 24 * 7 * 365)
return decimal_value * 60 * 60 * 24 * 7 * 365
raise SlitherException(f"Subdemonination conversion impossible {decimal_value} {sub}")

@ -4,11 +4,14 @@ from typing import Union
from slither.exceptions import SlitherError
def convert_string_to_int(val: Union[str, int]) -> int:
def convert_string_to_fraction(val: Union[str, int]) -> Fraction:
if isinstance(val, int):
return val
return Fraction(val)
if val.startswith(("0x", "0X")):
return int(val, 16)
return Fraction(int(val, 16))
# Fractions do not support underscore separators (on Python <3.11)
val = val.replace('_', '')
if "e" in val or "E" in val:
base, expo = val.split("e") if "e" in val else val.split("E")
@ -23,6 +26,9 @@ def convert_string_to_int(val: Union[str, int]) -> int:
f"{base}e{expo} is too large to fit in any Solidity integer size"
)
return 0
return int(Fraction(base) * Fraction(10**expo))
return Fraction(base) * Fraction(10**expo)
return int(Fraction(val))
return Fraction(val)
def convert_string_to_int(val: Union[str, int]) -> int:
return int(convert_string_to_fraction(val))

@ -1,6 +1,5 @@
from fractions import Fraction
from slither.core.expressions import BinaryOperationType, Literal, UnaryOperationType
from slither.utils.integer_conversion import convert_string_to_int
from slither.utils.integer_conversion import convert_string_to_fraction, convert_string_to_int
from slither.visitors.expression.expression import ExpressionVisitor
@ -73,13 +72,13 @@ class ConstantFolding(ExpressionVisitor):
cf = ConstantFolding(expr, self._type)
expr = cf.result()
assert isinstance(expr, Literal)
set_val(expression, int(expr.value))
set_val(expression, -convert_string_to_fraction(expr.value))
else:
raise NotConstant
def _post_literal(self, expression):
try:
set_val(expression, Fraction(expression.value))
set_val(expression, convert_string_to_fraction(expression.value))
except ValueError:
raise NotConstant
@ -116,7 +115,7 @@ class ConstantFolding(ExpressionVisitor):
cf = ConstantFolding(expression.expressions[0], self._type)
expr = cf.result()
assert isinstance(expr, Literal)
set_val(expression, int(expr.value))
set_val(expression, convert_string_to_fraction(expr.value))
return
raise NotConstant

Loading…
Cancel
Save