Skip to content

Commit

Permalink
Merge pull request #386 from DavidKnott/improve-external-contract-calls
Browse files Browse the repository at this point in the history
External contract calls cannot be used internally
  • Loading branch information
DavidKnott authored Oct 9, 2017
2 parents 375d004 + a27236f commit 26e5b94
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 1 deletion.
53 changes: 53 additions & 0 deletions tests/parser/features/test_external_contract_calls.py
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,59 @@ def __init__(arg1: address):
print('Successfully executed a multiple external contract calls')


def test_invalid_external_contract_call_to_the_same_contract(assert_tx_failed):
contract_1 = """
def bar() -> num:
return 1
"""

contract_2 = """
class Bar():
def bar() -> num: pass
def bar() -> num:
return 1
def _stmt(x: address):
Bar(x).bar()
def _expr(x: address) -> num:
return Bar(x).bar()
"""

t.s = t.Chain()
c1 = get_contract(contract_1)
c2 = get_contract(contract_2)

c2._stmt(c1.address)
c2._expr(c1.address)
assert_tx_failed(t, lambda: c2._stmt(c2.address))
assert_tx_failed(t, lambda: c2._expr(c2.address))


def test_invalid_nonexistent_contract_call(assert_tx_failed):
contract_1 = """
def bar() -> num:
return 1
"""

contract_2 = """
class Bar():
def bar() -> num: pass
def foo(x: address) -> num:
return Bar(x).bar()
"""

c1 = get_contract(contract_1)
c2 = get_contract(contract_2)
t.s = s

assert c2.foo(c1.address) == 1
assert_tx_failed(t, lambda: c2.foo(t.a1))
assert_tx_failed(t, lambda: c2.foo(t.a7))


def test_invalid_contract_reference_declaration(assert_tx_failed):
contract = """
class Bar():
Expand Down
7 changes: 6 additions & 1 deletion viper/parser/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -460,7 +460,10 @@ def external_contract_call_stmt(stmt, context):
sig = context.sigs[contract_name][method_name]
contract_address = parse_expr(stmt.func.value.args[0], context)
inargs, inargsize = pack_arguments(sig, [parse_expr(arg, context) for arg in stmt.args], context)
o = LLLnode.from_list(['assert', ['call', ['gas'], ['mload', contract_address], 0, inargs, inargsize, 0, 0]],
o = LLLnode.from_list(['seq',
['assert', ['extcodesize', ['mload', contract_address]]],
['assert', ['ne', 'address', ['mload', contract_address]]],
['assert', ['call', ['gas'], ['mload', contract_address], 0, inargs, inargsize, 0, 0]]],
typ=None, location='memory', pos=getpos(stmt))
return o

Expand All @@ -484,6 +487,8 @@ def external_contract_call_expr(expr, context):
else:
raise TypeMismatchException("Invalid output type: %r" % sig.output_type, expr)
o = LLLnode.from_list(['seq',
['assert', ['extcodesize', ['mload', contract_address]]],
['assert', ['ne', 'address', ['mload', contract_address]]],
['assert', ['call', ['gas'], ['mload', contract_address], 0,
inargs, inargsize,
output_placeholder, get_size_of_type(sig.output_type) * 32]],
Expand Down

0 comments on commit 26e5b94

Please sign in to comment.