diff --git a/populus/contracts/common.py b/populus/contracts/common.py index 4fbd0ec0..de90bdc9 100644 --- a/populus/contracts/common.py +++ b/populus/contracts/common.py @@ -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 @@ -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)) diff --git a/populus/contracts/utils.py b/populus/contracts/utils.py index 62edf2ca..0004ef52 100644 --- a/populus/contracts/utils.py +++ b/populus/contracts/utils.py @@ -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: diff --git a/tests/contracts/test_decode_multi.py b/tests/contracts/test_decode_multi.py index 0ae36edf..63742f9f 100644 --- a/tests/contracts/test_decode_multi.py +++ b/tests/contracts/test_decode_multi.py @@ -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' diff --git a/tests/contracts/test_decode_single_type.py b/tests/contracts/test_decode_single_type.py index ecd89711..6cb01487 100644 --- a/tests/contracts/test_decode_single_type.py +++ b/tests/contracts/test_decode_single_type.py @@ -76,10 +76,6 @@ def test_decode_bytes(): @pytest.mark.parametrize( 'input,expected', ( - ( - '0x', - '0x0000000000000000000000000000000000000000', - ), ( '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000', @@ -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')