diff --git a/docs/changelog.rst b/docs/changelog.rst index 11d1833..cbf6fc1 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -9,9 +9,11 @@ Added ^^^^^ - Support for contract errors with anonymous fields. (PR_90_) +- Support for partially named method arguments. (PR_91_) .. _PR_90: https://github.com/fjarri-eth/pons/pull/90 +.. _PR_91: https://github.com/fjarri-eth/pons/pull/91 0.10.0 (2025-10-19) diff --git a/pons/_abi_types.py b/pons/_abi_types.py index 33917f0..5faa786 100644 --- a/pons/_abi_types.py +++ b/pons/_abi_types.py @@ -512,13 +512,13 @@ def dispatch_types(abi_entry: ABI_JSON) -> list[Type] | dict[str, Type]: names = [entry["name"] for entry in abi_entry_typed] - # Unnamed arguments; treat as positional arguments - if names and all(not name for name in names): + # In Solidity, it is possible to have have an argument list like `(address x, uint256)` + # (that is, only some of the arguments are unnamed). + # This cannot be mapped to Python function signatures, + # so we have to treat this as if all the arguments were unnamed. + if names and any(not name for name in names): return [dispatch_type(entry) for entry in abi_entry_typed] - if any(not name for name in names): - raise ValueError("Arguments must be either all named or all unnamed") - # Since we are returning a dictionary, need to be sure we don't silently merge entries if len(names) != len(set(names)): raise ValueError("All ABI entries must have distinct names") diff --git a/tests/test_abi_types.py b/tests/test_abi_types.py index 4da4e59..7555fbf 100644 --- a/tests/test_abi_types.py +++ b/tests/test_abi_types.py @@ -256,8 +256,11 @@ def test_dispatch_types() -> None: # For an empty argument list we choose to resolve it as an empty dictionary, for certainty. assert dispatch_types([]) == {} - with pytest.raises(ValueError, match="Arguments must be either all named or all unnamed"): - dispatch_types([dict(name="foo", type="uint8"), dict(name="", type="uint16[2]")]) + # Partially named arguments + assert dispatch_types([dict(name="x", type="uint8"), dict(name="", type="uint16[2]")]) == [ + abi.uint(8), + abi.uint(16)[2], + ] with pytest.raises(ValueError, match="All ABI entries must have distinct names"): dispatch_types([dict(name="foo", type="uint8"), dict(name="foo", type="uint16[2]")])