Skip to content

Commit

Permalink
Merge pull request #59 from pipermerriam/piper/fix-how-empty-response…
Browse files Browse the repository at this point in the history
…s-are-handled

change populus handling of empty responses to function calls
  • Loading branch information
pipermerriam committed Dec 31, 2015
2 parents 17d6404 + af387a8 commit 48450d2
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 8 deletions.
18 changes: 16 additions & 2 deletions populus/contracts/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@
)


class EmptyDataError(Exception):
"""
Raised when a call to a function unexpectedly returns empty data `0x` when
a response was expected.
"""
pass


class ContractBound(object):
_contract = None

Expand Down Expand Up @@ -60,7 +68,13 @@ def output_types(self):

def cast_return_data(self, outputs):
if len(self.output_types) != 1:
return decode_multi(self.output_types, outputs)
try:
return decode_multi(self.output_types, outputs)
except AssertionError:
raise EmptyDataError("call to {0} unexpectedly returned no data".format(self))
output_type = self.output_types[0]

return decode_single(output_type, outputs)
try:
return decode_single(output_type, outputs)
except AssertionError:
raise EmptyDataError("call to {0} unexpectedly returned no data".format(self))
5 changes: 3 additions & 2 deletions populus/contracts/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@
def decode_single(typ, data):
base, sub, _ = abi.process_type(typ)

# ensure that we aren't trying to decode an empty response.
assert len(data) > 2

if base == 'address':
if data == "0x":
return "0x" + "0" * 40
return '0x' + strip_0x_prefix(data[-40:])
elif base == 'string' or base == 'bytes' or base == 'hash':
if sub:
Expand Down
5 changes: 5 additions & 0 deletions tests/contracts/test_decode_multi.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ def test_decode_two_uint32(input, expected):
assert output == expected


def test_empty_data_raises():
with pytest.raises(AssertionError):
decode_multi(['uint32', 'uint32'], '0x')


def test_decode_various():
data = ('0x00000000000000000000000082a978b3f5962a5b0957d9ee9eef472ee55b42f10000000000000'
'0000000000000000000000000000000000000000000000000017374757069642070696e6b20616e69'
Expand Down
10 changes: 6 additions & 4 deletions tests/contracts/test_decode_single_type.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,6 @@ def test_decode_bytes():
@pytest.mark.parametrize(
'input,expected',
(
(
'0x',
'0x0000000000000000000000000000000000000000',
),
(
'0x0000000000000000000000000000000000000000000000000000000000000000',
'0x0000000000000000000000000000000000000000',
Expand All @@ -105,3 +101,9 @@ def test_decode_bytes():
def test_decode_address(input, expected):
output = decode_single('address', input)
assert output == expected


@pytest.mark.parametrize('_type', ('address', 'bytes32', 'uint256', 'int256', 'bool'))
def test_raises_on_empty_data(_type):
with pytest.raises(AssertionError):
decode_single(_type, '0x')

0 comments on commit 48450d2

Please sign in to comment.