|
|
@ -61,7 +61,6 @@ def get_pointer_name(variable): |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def find_variable(var_name, caller_context, referenced_declaration=None, is_super=False): |
|
|
|
def find_variable(var_name, caller_context, referenced_declaration=None, is_super=False): |
|
|
|
|
|
|
|
|
|
|
|
# variable are looked from the contract declarer |
|
|
|
# variable are looked from the contract declarer |
|
|
|
# functions can be shadowed, but are looked from the contract instance, rather than the contract declarer |
|
|
|
# functions can be shadowed, but are looked from the contract instance, rather than the contract declarer |
|
|
|
# the difference between function and variable come from the fact that an internal call, or an variable access |
|
|
|
# the difference between function and variable come from the fact that an internal call, or an variable access |
|
|
@ -119,7 +118,8 @@ def find_variable(var_name, caller_context, referenced_declaration=None, is_supe |
|
|
|
if is_super: |
|
|
|
if is_super: |
|
|
|
getter_available = lambda f: f.functions_declared |
|
|
|
getter_available = lambda f: f.functions_declared |
|
|
|
d = {f.canonical_name: f for f in contract.functions} |
|
|
|
d = {f.canonical_name: f for f in contract.functions} |
|
|
|
functions = {f.full_name:f for f in contract_declarer.available_elements_from_inheritances(d, getter_available).values()} |
|
|
|
functions = {f.full_name: f for f in |
|
|
|
|
|
|
|
contract_declarer.available_elements_from_inheritances(d, getter_available).values()} |
|
|
|
else: |
|
|
|
else: |
|
|
|
functions = contract.available_functions_as_dict() |
|
|
|
functions = contract.available_functions_as_dict() |
|
|
|
if var_name in functions: |
|
|
|
if var_name in functions: |
|
|
@ -128,7 +128,8 @@ def find_variable(var_name, caller_context, referenced_declaration=None, is_supe |
|
|
|
if is_super: |
|
|
|
if is_super: |
|
|
|
getter_available = lambda m: m.modifiers_declared |
|
|
|
getter_available = lambda m: m.modifiers_declared |
|
|
|
d = {m.canonical_name: m for m in contract.modifiers} |
|
|
|
d = {m.canonical_name: m for m in contract.modifiers} |
|
|
|
modifiers = {m.full_name: m for m in contract_declarer.available_elements_from_inheritances(d, getter_available).values()} |
|
|
|
modifiers = {m.full_name: m for m in |
|
|
|
|
|
|
|
contract_declarer.available_elements_from_inheritances(d, getter_available).values()} |
|
|
|
else: |
|
|
|
else: |
|
|
|
modifiers = contract.available_modifiers_as_dict() |
|
|
|
modifiers = contract.available_modifiers_as_dict() |
|
|
|
if var_name in modifiers: |
|
|
|
if var_name in modifiers: |
|
|
@ -178,6 +179,7 @@ def find_variable(var_name, caller_context, referenced_declaration=None, is_supe |
|
|
|
|
|
|
|
|
|
|
|
raise VariableNotFound('Variable not found: {} (context {})'.format(var_name, caller_context)) |
|
|
|
raise VariableNotFound('Variable not found: {} (context {})'.format(var_name, caller_context)) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# endregion |
|
|
|
# endregion |
|
|
|
################################################################################### |
|
|
|
################################################################################### |
|
|
|
################################################################################### |
|
|
|
################################################################################### |
|
|
@ -219,6 +221,7 @@ def filter_name(value): |
|
|
|
value = value[:idx + 1] |
|
|
|
value = value[:idx + 1] |
|
|
|
return value |
|
|
|
return value |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# endregion |
|
|
|
# endregion |
|
|
|
|
|
|
|
|
|
|
|
################################################################################### |
|
|
|
################################################################################### |
|
|
@ -242,9 +245,7 @@ def parse_call(expression, caller_context): |
|
|
|
if type_conversion: |
|
|
|
if type_conversion: |
|
|
|
type_call = parse_type(UnknownType(type_return), caller_context) |
|
|
|
type_call = parse_type(UnknownType(type_return), caller_context) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if caller_context.is_compact_ast: |
|
|
|
if caller_context.is_compact_ast: |
|
|
|
type_info = expression['expression'] |
|
|
|
|
|
|
|
assert len(expression['arguments']) == 1 |
|
|
|
assert len(expression['arguments']) == 1 |
|
|
|
expression_to_parse = expression['arguments'][0] |
|
|
|
expression_to_parse = expression['arguments'][0] |
|
|
|
else: |
|
|
|
else: |
|
|
@ -264,8 +265,25 @@ def parse_call(expression, caller_context): |
|
|
|
t.set_offset(src, caller_context.slither) |
|
|
|
t.set_offset(src, caller_context.slither) |
|
|
|
return t |
|
|
|
return t |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
call_gas = None |
|
|
|
|
|
|
|
call_value = None |
|
|
|
if caller_context.is_compact_ast: |
|
|
|
if caller_context.is_compact_ast: |
|
|
|
called = parse_expression(expression['expression'], caller_context) |
|
|
|
called = parse_expression(expression['expression'], caller_context) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# If the next expression is a FunctionCallOptions |
|
|
|
|
|
|
|
# We can here the gas/value information |
|
|
|
|
|
|
|
# This is only available if the syntax is {gas: , value: } |
|
|
|
|
|
|
|
# For the .gas().value(), the member are considered as function call |
|
|
|
|
|
|
|
# And converted later to the correct info (convert.py) |
|
|
|
|
|
|
|
if expression['expression'][caller_context.get_key()] == 'FunctionCallOptions': |
|
|
|
|
|
|
|
call_with_options = expression['expression'] |
|
|
|
|
|
|
|
for idx, name in enumerate(call_with_options.get('names', [])): |
|
|
|
|
|
|
|
option = parse_expression(call_with_options['options'][idx], caller_context) |
|
|
|
|
|
|
|
if name == 'value': |
|
|
|
|
|
|
|
call_value = option |
|
|
|
|
|
|
|
if name == 'gas': |
|
|
|
|
|
|
|
call_gas = option |
|
|
|
|
|
|
|
|
|
|
|
arguments = [] |
|
|
|
arguments = [] |
|
|
|
if expression['arguments']: |
|
|
|
if expression['arguments']: |
|
|
|
arguments = [parse_expression(a, caller_context) for a in expression['arguments']] |
|
|
|
arguments = [parse_expression(a, caller_context) for a in expression['arguments']] |
|
|
@ -280,12 +298,16 @@ def parse_call(expression, caller_context): |
|
|
|
return sp |
|
|
|
return sp |
|
|
|
call_expression = CallExpression(called, arguments, type_return) |
|
|
|
call_expression = CallExpression(called, arguments, type_return) |
|
|
|
call_expression.set_offset(src, caller_context.slither) |
|
|
|
call_expression.set_offset(src, caller_context.slither) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Only available if the syntax {gas:, value:} was used |
|
|
|
|
|
|
|
call_expression.call_gas = call_gas |
|
|
|
|
|
|
|
call_expression.call_value = call_value |
|
|
|
return call_expression |
|
|
|
return call_expression |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def parse_super_name(expression, is_compact_ast): |
|
|
|
def parse_super_name(expression, is_compact_ast): |
|
|
|
if is_compact_ast: |
|
|
|
if is_compact_ast: |
|
|
|
assert expression['nodeType'] == 'MemberAccess' |
|
|
|
assert expression['nodeType'] == 'MemberAccess' |
|
|
|
attributes = expression |
|
|
|
|
|
|
|
base_name = expression['memberName'] |
|
|
|
base_name = expression['memberName'] |
|
|
|
arguments = expression['typeDescriptions']['typeString'] |
|
|
|
arguments = expression['typeDescriptions']['typeString'] |
|
|
|
else: |
|
|
|
else: |
|
|
@ -304,6 +326,7 @@ def parse_super_name(expression, is_compact_ast): |
|
|
|
|
|
|
|
|
|
|
|
return base_name + arguments |
|
|
|
return base_name + arguments |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _parse_elementary_type_name_expression(expression, is_compact_ast, caller_context): |
|
|
|
def _parse_elementary_type_name_expression(expression, is_compact_ast, caller_context): |
|
|
|
# nop exression |
|
|
|
# nop exression |
|
|
|
# uint; |
|
|
|
# uint; |
|
|
@ -318,6 +341,7 @@ def _parse_elementary_type_name_expression(expression, is_compact_ast, caller_co |
|
|
|
e.set_offset(expression['src'], caller_context.slither) |
|
|
|
e.set_offset(expression['src'], caller_context.slither) |
|
|
|
return e |
|
|
|
return e |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def parse_expression(expression, caller_context): |
|
|
|
def parse_expression(expression, caller_context): |
|
|
|
""" |
|
|
|
""" |
|
|
|
|
|
|
|
|
|
|
@ -387,9 +411,15 @@ def parse_expression(expression, caller_context): |
|
|
|
binary_op.set_offset(src, caller_context.slither) |
|
|
|
binary_op.set_offset(src, caller_context.slither) |
|
|
|
return binary_op |
|
|
|
return binary_op |
|
|
|
|
|
|
|
|
|
|
|
elif name == 'FunctionCall': |
|
|
|
elif name in 'FunctionCall': |
|
|
|
return parse_call(expression, caller_context) |
|
|
|
return parse_call(expression, caller_context) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
elif name == 'FunctionCallOptions': |
|
|
|
|
|
|
|
# call/gas info are handled in parse_call |
|
|
|
|
|
|
|
called = parse_expression(expression['expression'], caller_context) |
|
|
|
|
|
|
|
assert isinstance(called, MemberAccess) |
|
|
|
|
|
|
|
return called |
|
|
|
|
|
|
|
|
|
|
|
elif name == 'TupleExpression': |
|
|
|
elif name == 'TupleExpression': |
|
|
|
""" |
|
|
|
""" |
|
|
|
For expression like |
|
|
|
For expression like |
|
|
@ -671,4 +701,3 @@ def parse_expression(expression, caller_context): |
|
|
|
return call |
|
|
|
return call |
|
|
|
|
|
|
|
|
|
|
|
raise ParsingError('Expression not parsed %s' % name) |
|
|
|
raise ParsingError('Expression not parsed %s' % name) |
|
|
|
|
|
|
|
|
|
|
|