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

fix: decoding issues that affect tracing features such as coverage #1803

Merged
merged 3 commits into from
Jan 3, 2024
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
20 changes: 12 additions & 8 deletions src/ape_ethereum/ecosystem.py
Original file line number Diff line number Diff line change
Expand Up @@ -448,13 +448,13 @@ def decode_calldata(self, abi: Union[ConstructorABI, MethodABI], calldata: bytes
input_types = [parse_type(i.model_dump(mode="json")) for i in abi.inputs]

try:
raw_input_values = decode(raw_input_types, calldata)
input_values = [
self.decode_primitive_value(v, t) for v, t in zip(raw_input_values, input_types)
]
raw_input_values = decode(raw_input_types, calldata, strict=False)
except InsufficientDataBytes as err:
raise DecodingError(str(err)) from err

input_values = [
self.decode_primitive_value(v, t) for v, t in zip(raw_input_values, input_types)
]
arguments = {}
index = 0
for i, v in zip(abi.inputs, input_values):
Expand All @@ -467,10 +467,14 @@ def decode_calldata(self, abi: Union[ConstructorABI, MethodABI], calldata: bytes
def decode_returndata(self, abi: MethodABI, raw_data: bytes) -> Tuple[Any, ...]:
output_types_str_ls = [o.canonical_type for o in abi.outputs]

try:
vm_return_values = decode(output_types_str_ls, raw_data)
except (InsufficientDataBytes, NonEmptyPaddingBytes) as err:
raise DecodingError(str(err)) from err
if raw_data:
try:
vm_return_values = decode(output_types_str_ls, raw_data, strict=False)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

second change: use strict=False here to see if that resolves the problem. I remember having to do this somewhere else because of node oddities (probably hardhat!)

except (InsufficientDataBytes, NonEmptyPaddingBytes) as err:
raise DecodingError(str(err)) from err
else:
# Use all zeroes.
vm_return_values = tuple([0 for _ in output_types_str_ls])
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it seems like the user is getting hardhat to give them empty bytes for a 0 return in some weird case that i havent reproduced


if not vm_return_values:
return vm_return_values
Expand Down
33 changes: 31 additions & 2 deletions tests/functional/test_ecosystem.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from typing import Any, Dict

import pytest
from eth_pydantic_types import HexBytes
from eth_pydantic_types import HashBytes32, HexBytes
from eth_typing import HexAddress, HexStr
from ethpm_types.abi import ABIType, EventABI, MethodABI

Expand Down Expand Up @@ -351,7 +351,22 @@ def test_encode_blueprint_contract(ethereum, vyper_contract_type):
assert actual.data == HexBytes(expected)


def test_decode_return_data_non_empty_padding_bytes(ethereum):
def test_decode_returndata(ethereum):
abi = MethodABI.model_validate(
{
"type": "function",
"name": "doThing",
"stateMutability": "nonpayable",
"inputs": [],
"outputs": [{"name": "", "type": "bool"}],
}
)
data = HashBytes32.__eth_pydantic_validate__(0)
actual = ethereum.decode_returndata(abi, data)
assert actual == (False,)


def test_decode_returndata_non_empty_padding_bytes(ethereum):
raw_data = HexBytes(
"0x08c379a000000000000000000000000000000000000000000000000000000000000000200"
"000000000000000000000000000000000000000000000000000000000000012696e73756666"
Expand All @@ -373,6 +388,20 @@ def test_decode_return_data_non_empty_padding_bytes(ethereum):
ethereum.decode_returndata(abi, raw_data)


def test_decode_returndata_no_bytes_returns_zero(ethereum):
abi = MethodABI.model_validate(
{
"type": "function",
"name": "doThing",
"stateMutability": "nonpayable",
"inputs": [],
"outputs": [{"name": "", "type": "bool"}],
}
)
actual = ethereum.decode_returndata(abi, b"")
assert actual == (0,)


@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
Loading