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: Show network instead of provider in ContractNotFoundError #2202

Merged
merged 4 commits into from
Aug 2, 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
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
Loading