Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for new C{value:1} syntax #498

Merged
merged 1 commit into from
Jun 7, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 13 additions & 6 deletions slither/core/expressions/call_expression.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ def __init__(self, called, arguments, type_call):
# And converted later to the correct info (convert.py)
self._gas = None
self._value = None
self._salt = None

@property
def call_value(self):
Expand All @@ -31,6 +32,14 @@ def call_gas(self):
def call_gas(self, gas):
self._gas = gas

@property
def call_salt(self):
return self._salt

@call_salt.setter
def call_salt(self, salt):
self._salt = salt

@property
def called(self):
return self._called
Expand All @@ -48,10 +57,8 @@ def __str__(self):
if self.call_gas or self.call_value:
gas = f'gas: {self.call_gas}' if self.call_gas else ''
value = f'value: {self.call_value}' if self.call_value else ''
if gas and value:
txt += '{' + f'{gas}, {value}' + '}'
elif gas:
txt += '{' + f'{gas}' + '}'
else:
txt += '{' + f'{value}' + '}'
salt = f'salt: {self.call_salt}' if self.call_salt else ''
if gas or value or salt:
options = [gas, value, salt]
txt += '{' + ','.join([o for o in options if o != '']) + '}'
return txt + '(' + ','.join([str(a) for a in self._arguments]) + ')'
21 changes: 21 additions & 0 deletions slither/core/expressions/new_contract.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,32 @@ class NewContract(Expression):
def __init__(self, contract_name):
super(NewContract, self).__init__()
self._contract_name = contract_name
self._gas = None
self._value = None
self._salt = None


@property
def contract_name(self):
return self._contract_name

@property
def call_value(self):
return self._value

@call_value.setter
def call_value(self, v):
self._value = v

@property
def call_salt(self):
return self._salt

@call_salt.setter
def call_salt(self, salt):
self._salt = salt


def __str__(self):
return 'new ' + str(self._contract_name)

4 changes: 4 additions & 0 deletions slither/slithir/convert.py
Original file line number Diff line number Diff line change
Expand Up @@ -668,6 +668,10 @@ def extract_tmp_call(ins, contract):
op = NewContract(Constant(ins.ori.contract_name), ins.lvalue)
op.set_expression(ins.expression)
op.call_id = ins.call_id
if ins.call_value:
op.call_value = ins.call_value
if ins.call_salt:
op.call_salt = ins.call_salt
return op

if isinstance(ins.ori, TmpNewArray):
Expand Down
17 changes: 14 additions & 3 deletions slither/slithir/operations/new_contract.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ def __init__(self, contract_name, lvalue):
self._lvalue = lvalue
self._callid = None # only used if gas/value != 0
self._call_value = None
self._call_salt = None

@property
def call_value(self):
Expand All @@ -31,6 +32,14 @@ def call_id(self):
def call_id(self, c):
self._callid = c

@property
def call_salt(self):
return self._call_salt

@call_salt.setter
def call_salt(self, s):
self._call_salt = s

@property
def contract_name(self):
return self._contract_name
Expand Down Expand Up @@ -78,8 +87,10 @@ def can_send_eth(self):
# endregion

def __str__(self):
value = ''
options = ''
if self.call_value:
value = 'value:{}'.format(self.call_value)
options = 'value:{} '.format(self.call_value)
if self.call_salt:
options += 'salt:{} '.format(self.call_salt)
args = [str(a) for a in self.arguments]
return '{} = new {}({}) {}'.format(self.lvalue, self.contract_name, ','.join(args), value)
return '{} = new {}({}) {}'.format(self.lvalue, self.contract_name, ','.join(args), options)
9 changes: 9 additions & 0 deletions slither/slithir/tmp_operations/tmp_call.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ def __init__(self, called, nbr_arguments, result, type_call):
self._callid = None
self._gas = None
self._value = None
self._salt = None

@property
def call_value(self):
Expand All @@ -38,6 +39,14 @@ def call_gas(self):
def call_gas(self, gas):
self._gas = gas

@property
def call_salt(self):
return self._salt

@call_salt.setter
def call_salt(self, salt):
self._salt = salt

@property
def call_id(self):
return self._callid
Expand Down
18 changes: 18 additions & 0 deletions slither/slithir/tmp_operations/tmp_new_contract.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,29 @@ def __init__(self, contract_name, lvalue):
super(TmpNewContract, self).__init__()
self._contract_name = contract_name
self._lvalue = lvalue
self._call_value = None
self._call_salt = None

@property
def contract_name(self):
return self._contract_name

@property
def call_value(self):
return self._call_value

@call_value.setter
def call_value(self, v):
self._call_value = v

@property
def call_salt(self):
return self._call_salt

@call_salt.setter
def call_salt(self, s):
self._call_salt = s

@property
def read(self):
return []
Expand Down
2 changes: 2 additions & 0 deletions slither/slithir/utils/ssa.py
Original file line number Diff line number Diff line change
Expand Up @@ -613,6 +613,8 @@ def copy_ir(ir, *instances):
lvalue = get_variable(ir, lambda x: x.lvalue, *instances)
new_ir = NewContract(contract_name, lvalue)
new_ir.arguments = get_arguments(ir, *instances)
new_ir.call_value = get_variable(ir, lambda x: x.call_value, *instances)
new_ir.call_salt = get_variable(ir, lambda x: x.call_salt, *instances)
return new_ir
elif isinstance(ir, NewStructure):
structure = ir.structure
Expand Down
8 changes: 5 additions & 3 deletions slither/solc_parsing/expressions/expression_parsing.py
Original file line number Diff line number Diff line change
Expand Up @@ -267,9 +267,9 @@ def parse_call(expression, caller_context):

call_gas = None
call_value = None
call_salt = None
if caller_context.is_compact_ast:
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: }
Expand All @@ -283,7 +283,8 @@ def parse_call(expression, caller_context):
call_value = option
if name == 'gas':
call_gas = option

if name == 'salt':
call_salt = option
arguments = []
if expression['arguments']:
arguments = [parse_expression(a, caller_context) for a in expression['arguments']]
Expand All @@ -302,6 +303,7 @@ def parse_call(expression, caller_context):
# Only available if the syntax {gas:, value:} was used
call_expression.call_gas = call_gas
call_expression.call_value = call_value
call_expression.call_salt = call_salt
return call_expression


Expand Down Expand Up @@ -419,7 +421,7 @@ def parse_expression(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)
assert isinstance(called, (MemberAccess, NewContract))
return called

elif name == 'TupleExpression':
Expand Down
2 changes: 2 additions & 0 deletions slither/visitors/expression/expression.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,8 @@ def _visit_call_expression(self, expression):
self._visit_expression(expression.call_value)
if expression.call_gas:
self._visit_expression(expression.call_gas)
if expression.call_salt:
self._visit_expression(expression.call_salt)

def _visit_conditional_expression(self, expression):
self._visit_expression(expression.if_expression)
Expand Down
10 changes: 10 additions & 0 deletions slither/visitors/slithir/expression_to_slithir.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,9 @@ def _post_call_expression(self, expression):
if expression.call_value:
call_value = get(expression.call_value)
message_call.call_value = call_value
if expression.call_salt:
call_salt = get(expression.call_salt)
message_call.call_salt = call_salt
self._result.append(message_call)
set_val(expression, val)

Expand Down Expand Up @@ -221,6 +224,13 @@ def _post_new_contract(self, expression):
val = TemporaryVariable(self._node)
operation = TmpNewContract(expression.contract_name, val)
operation.set_expression(expression)
if expression.call_value:
call_value = get(expression.call_value)
operation.call_value = call_value
if expression.call_salt:
call_salt = get(expression.call_salt)
operation.call_salt = call_salt

self._result.append(operation)
set_val(expression, val)

Expand Down