From 26d762adc5bb0f4e020c2c4f0c161eeeed8fbbc1 Mon Sep 17 00:00:00 2001 From: antazoey Date: Fri, 2 Aug 2024 12:46:25 -0500 Subject: [PATCH] fix: Show network instead of provider in `ContractNotFoundError` (#2202) --- src/ape/contracts/base.py | 19 +++++--------- src/ape/exceptions.py | 4 +-- src/ape_ethereum/provider.py | 2 +- .../functional/test_contract_call_handler.py | 26 +++++++++++++++++++ tests/functional/test_contracts_cache.py | 4 +-- 5 files changed, 38 insertions(+), 17 deletions(-) diff --git a/src/ape/contracts/base.py b/src/ape/contracts/base.py index 924f4f058c..b8c7bf32ff 100644 --- a/src/ape/contracts/base.py +++ b/src/ape/contracts/base.py @@ -255,16 +255,18 @@ def decode_input(self, calldata: bytes) -> tuple[str, dict[str, Any]]: raise err - -class ContractCallHandler(ContractMethodHandler): - def __call__(self, *args, **kwargs) -> Any: + def _validate_is_contract(self): if not self.contract.is_contract: raise ContractNotFoundError( self.contract.address, self.provider.network.explorer is not None, - self.provider.name, + self.provider.network_choice, ) + +class ContractCallHandler(ContractMethodHandler): + def __call__(self, *args, **kwargs) -> Any: + self._validate_is_contract() selected_abi = _select_method_abi(self.abis, args) arguments = self.conversion_manager.convert_method_args(selected_abi, args) @@ -429,15 +431,8 @@ def __call__(self, *args, **kwargs) -> ReceiptAPI: return contract_transaction(*args, **kwargs) def _as_transaction(self, *args) -> ContractTransaction: - if not self.contract.is_contract: - raise ContractNotFoundError( - self.contract.address, - self.provider.network.explorer is not None, - self.provider.name, - ) - + self._validate_is_contract() selected_abi = _select_method_abi(self.abis, args) - return ContractTransaction( abi=selected_abi, address=self.contract.address, diff --git a/src/ape/exceptions.py b/src/ape/exceptions.py index 773d51669e..9907d4f7f5 100644 --- a/src/ape/exceptions.py +++ b/src/ape/exceptions.py @@ -534,13 +534,13 @@ class ContractNotFoundError(ChainError): Raised when a contract is not found at an address. """ - def __init__(self, address: "AddressType", has_explorer: bool, provider_name: str): + def __init__(self, address: "AddressType", has_explorer: bool, network_name: str): msg = f"Failed to get contract type for address '{address}'." msg += ( " Contract may need verification." if has_explorer else ( - f" Current provider '{provider_name}' has no associated " + f" Current network '{network_name}' has no associated " "explorer plugin. Try installing an explorer plugin using " f"{click.style(text='ape plugins install etherscan', fg='green')}, " "or using a network with explorer support." diff --git a/src/ape_ethereum/provider.py b/src/ape_ethereum/provider.py index 9364bb6706..15f4547669 100644 --- a/src/ape_ethereum/provider.py +++ b/src/ape_ethereum/provider.py @@ -1458,7 +1458,7 @@ def ots_get_contract_creator(self, address: AddressType) -> Optional[dict]: result = self.make_request("ots_getContractCreator", [address]) if result is None: # NOTE: Skip the explorer part of the error message via `has_explorer=True`. - raise ContractNotFoundError(address, has_explorer=True, provider_name=self.name) + raise ContractNotFoundError(address, True, self.network_choice) return result diff --git a/tests/functional/test_contract_call_handler.py b/tests/functional/test_contract_call_handler.py index 9d5f907bb5..14069aaecc 100644 --- a/tests/functional/test_contract_call_handler.py +++ b/tests/functional/test_contract_call_handler.py @@ -1,5 +1,31 @@ +import pytest + +from ape.contracts.base import ContractCallHandler +from ape.exceptions import ContractNotFoundError + + def test_struct_input( call_handler_with_struct_input, struct_input_for_call, output_from_struct_input_call ): actual = call_handler_with_struct_input.encode_input(*struct_input_for_call) assert actual == output_from_struct_input_call + + +def test_call_contract_not_found(mocker, method_abi_with_struct_input): + contract = mocker.MagicMock() + contract.is_contract = False + method = method_abi_with_struct_input + handler = ContractCallHandler(contract=contract, abis=[method]) + expected = ".*Current network 'ethereum:local:test'.*" + with pytest.raises(ContractNotFoundError, match=expected): + handler() + + +def test_transact_contract_not_found(mocker, owner, method_abi_with_struct_input): + contract = mocker.MagicMock() + contract.is_contract = False + method = method_abi_with_struct_input + handler = ContractCallHandler(contract=contract, abis=[method]) + expected = ".*Current network 'ethereum:local:test'.*" + with pytest.raises(ContractNotFoundError, match=expected): + handler.transact(sender=owner) diff --git a/tests/functional/test_contracts_cache.py b/tests/functional/test_contracts_cache.py index a5f1278328..919d828b5e 100644 --- a/tests/functional/test_contracts_cache.py +++ b/tests/functional/test_contracts_cache.py @@ -80,7 +80,7 @@ def test_instance_at_contract_type_not_found(chain, eth_tester_provider): new_address = "0x4a986a6dca6dbF99Bc3D17F8d71aFB0D60E740F9" expected = ( rf"Failed to get contract type for address '{new_address}'. " - r"Current provider 'ethereum:local:test' has no associated explorer plugin. " + r"Current network 'ethereum:local:test' has no associated explorer plugin. " "Try installing an explorer plugin using .*ape plugins install etherscan.*, " r"or using a network with explorer support\." ) @@ -163,7 +163,7 @@ def test_contracts_getitem_contract_not_found(chain, eth_tester_provider): new_address = "0x4a986a6dca6dbF99Bc3D17F8d71aFB0D60E740F9" expected = ( rf"Failed to get contract type for address '{new_address}'. " - r"Current provider 'ethereum:local:test' has no associated explorer plugin. " + r"Current network 'ethereum:local:test' has no associated explorer plugin. " "Try installing an explorer plugin using .*ape plugins install etherscan.*, " r"or using a network with explorer support\." )