diff --git a/genlayer_py/contracts/actions.py b/genlayer_py/contracts/actions.py index b40f9c6..b448419 100644 --- a/genlayer_py/contracts/actions.py +++ b/genlayer_py/contracts/actions.py @@ -884,6 +884,13 @@ def _encode_add_transaction_data( use_fee_aware_transaction = ( transaction_fees["requires_fee_aware_transaction"] or abi_version == "fees" ) + argument_count = len(contract_fn.argument_types) + if abi_version != "fees" and argument_count not in (5, 6): + raise ValueError( + "Unsupported addTransaction ABI: expected 5 or 6 arguments, " + f"got {argument_count}" + ) + normalized_valid_until = to_uint( valid_until, "valid_until", @@ -909,8 +916,13 @@ def _encode_add_transaction_data( consensus_max_rotations, self.w3.to_bytes(hexstr=data), ] - if len(contract_fn.argument_types) >= 6: + if argument_count == 6: add_transaction_args.append(normalized_valid_until) + elif argument_count != 5: + raise ValueError( + "Unsupported addTransaction ABI: expected 5 or 6 arguments, " + f"got {argument_count}" + ) params = abi_encode( contract_fn.argument_types, diff --git a/tests/unit/contracts/test_contract_actions.py b/tests/unit/contracts/test_contract_actions.py index 5a9e298..4d8bec6 100644 --- a/tests/unit/contracts/test_contract_actions.py +++ b/tests/unit/contracts/test_contract_actions.py @@ -70,6 +70,23 @@ } ] +ADD_TRANSACTION_ABI_V7 = [ + { + "type": "function", + "name": "addTransaction", + "stateMutability": "nonpayable", + "inputs": [ + {"name": "_sender", "type": "address"}, + {"name": "_recipient", "type": "address"}, + {"name": "_numOfInitialValidators", "type": "uint256"}, + {"name": "_maxRotations", "type": "uint256"}, + {"name": "_calldata", "type": "bytes"}, + {"name": "_validUntil", "type": "uint256"}, + {"name": "_futureField", "type": "uint256"}, + ], + "outputs": [], + } +] ADD_TRANSACTION_ABI_WITH_FEES = [ { "type": "function", @@ -632,6 +649,33 @@ def test_encode_add_transaction_uses_v6_signature_when_abi_has_6_inputs(): assert encoded.startswith(f"0x{selector}") +def test_encode_add_transaction_rejects_unknown_argument_count(): + client = _make_client(ADD_TRANSACTION_ABI_V7) + + with pytest.raises(ValueError, match="expected 5 or 6 arguments, got 7"): + contract_actions._encode_add_transaction_data( + self=client, + sender_account=client.local_account, + recipient=RECIPIENT, + consensus_max_rotations=3, + data="0x", + ) + + +def test_encode_add_transaction_rejects_v7_abi_when_fee_aware_transaction_is_requested(): + client = _make_client(ADD_TRANSACTION_ABI_V7) + + with pytest.raises(ValueError, match="expected 5 or 6 arguments, got 7"): + contract_actions._encode_add_transaction_data( + self=client, + sender_account=client.local_account, + recipient=RECIPIENT, + consensus_max_rotations=3, + data="0x", + transaction_fees={"requires_fee_aware_transaction": True}, + ) + + def test_encode_add_transaction_uses_fee_signature_when_abi_has_tuple_input(): client = _make_client(ADD_TRANSACTION_ABI_WITH_FEES)