Skip to content

Commit

Permalink
fix: Show network instead of provider in ContractNotFoundError (#2202)
Browse files Browse the repository at this point in the history
  • Loading branch information
antazoey authored Aug 2, 2024
1 parent 9e211ab commit 26d762a
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 17 deletions.
19 changes: 7 additions & 12 deletions src/ape/contracts/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down Expand Up @@ -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,
Expand Down
4 changes: 2 additions & 2 deletions src/ape/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -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."
Expand Down
2 changes: 1 addition & 1 deletion src/ape_ethereum/provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
26 changes: 26 additions & 0 deletions tests/functional/test_contract_call_handler.py
Original file line number Diff line number Diff line change
@@ -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)
4 changes: 2 additions & 2 deletions tests/functional/test_contracts_cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -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\."
)
Expand Down Expand Up @@ -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\."
)
Expand Down

0 comments on commit 26d762a

Please sign in to comment.