Skip to content

Commit

Permalink
fix: array of structs or tuples when only 1 element would be weird (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
antazoey authored Jan 31, 2024
1 parent 80df7a4 commit 52f431b
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 1 deletion.
16 changes: 15 additions & 1 deletion src/ape_ethereum/ecosystem.py
Original file line number Diff line number Diff line change
Expand Up @@ -634,7 +634,21 @@ def decode_returndata(self, abi: MethodABI, raw_data: bytes) -> Tuple[Any, ...]:
and isinstance(output_values, (list, tuple))
and len(output_values) == 1
):
return ([o for o in output_values[0]],)
# Array of structs or tuples: don't convert to list
# Array of anything else: convert to single list
return (
(
[
output_values[0],
],
)
if issubclass(type(output_values[0]), Struct)
else ([o for o in output_values[0]],)
)

elif returns_array(abi):
# Tuple with single item as the array.
return (output_values,)

return tuple(output_values)

Expand Down
41 changes: 41 additions & 0 deletions tests/functional/test_ecosystem.py
Original file line number Diff line number Diff line change
Expand Up @@ -566,6 +566,47 @@ def test_decode_returndata_no_bytes_returns_zero(ethereum):
assert actual == (0,)


def test_decode_returndata_list_with_1_struct(ethereum):
"""
Tests a condition where an array of a list with 1 struct
would be turned into a raw tuple instead of the Struct class.
"""
abi = MethodABI(
type="function",
name="getArrayOfStructs",
stateMutability="view",
inputs=[],
outputs=[
ABIType(
name="",
type="tuple[]",
components=[
ABIType(name="a", type="address", components=None, internal_type=None),
ABIType(name="b", type="bytes32", components=None, internal_type=None),
],
internal_type=None,
)
],
)
raw_data = HexBytes(
"0x000000000000000000000000000000000000000000000000000000000000002"
"00000000000000000000000000000000000000000000000000000000000000001"
"000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266f"
"d91dc47b758f65fd0f6fe511566770c0ae3f94ff9999ceb23bfec3ac9fdc168"
)
actual = ethereum.decode_returndata(abi, raw_data)

assert len(actual) == 1
# The result should still be a list.
# There was also a bug where it was mistakenly a tuple!
assert isinstance(actual[0], list)
assert len(actual[0]) == 1
assert actual[0][0].a == "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"
assert actual[0][0].b == HexBytes(
"0xfd91dc47b758f65fd0f6fe511566770c0ae3f94ff9999ceb23bfec3ac9fdc168"
)


@pytest.mark.parametrize("tx_type", TransactionType)
def test_create_transaction_uses_network_gas_limit(tx_type, ethereum, eth_tester_provider, owner):
tx = ethereum.create_transaction(type=tx_type.value, sender=owner.address)
Expand Down

0 comments on commit 52f431b

Please sign in to comment.