From f939082b37e88d6afc9b2cbb3ddd6eeec12f46a0 Mon Sep 17 00:00:00 2001 From: Juliya Smith Date: Thu, 12 Dec 2024 11:01:06 -0600 Subject: [PATCH] fix: make always work when getting 1st time --- tests/functional/geth/conftest.py | 6 ++ tests/functional/geth/test_contracts_cache.py | 55 +++++++++++++++++++ tests/functional/geth/test_proxy.py | 6 +- tests/functional/test_proxy.py | 5 +- 4 files changed, 67 insertions(+), 5 deletions(-) create mode 100644 tests/functional/geth/test_contracts_cache.py diff --git a/tests/functional/geth/conftest.py b/tests/functional/geth/conftest.py index 97bdffb6e5..f7f7e30ad4 100644 --- a/tests/functional/geth/conftest.py +++ b/tests/functional/geth/conftest.py @@ -8,6 +8,12 @@ from tests.functional.data.python import TRACE_RESPONSE +@pytest.fixture(scope="session") +def safe_proxy_container(get_contract_type): + proxy_type = get_contract_type("SafeProxy") + return ContractContainer(proxy_type) + + @pytest.fixture def parity_trace_response(): return TRACE_RESPONSE diff --git a/tests/functional/geth/test_contracts_cache.py b/tests/functional/geth/test_contracts_cache.py new file mode 100644 index 0000000000..1c3cb5a6de --- /dev/null +++ b/tests/functional/geth/test_contracts_cache.py @@ -0,0 +1,55 @@ +import pytest + +from ape.exceptions import ContractNotFoundError +from tests.conftest import geth_process_test + + +@geth_process_test +def test_get_proxy_from_explorer( + mock_explorer, + create_mock_sepolia, + safe_proxy_container, + geth_account, + vyper_contract_container, + geth_provider, + chain, +): + """ + Simulated when you get a contract from Etherscan for the first time + but that contract is a proxy. We expect both proxy and target ABIs + to be cached under the proxy's address. + """ + target_contract = geth_account.deploy(vyper_contract_container, 10011339315) + proxy_contract = geth_account.deploy(safe_proxy_container, target_contract.address) + + # Ensure both of these are not cached so we have to rely on our fake explorer. + del chain.contracts[target_contract.address] + del chain.contracts[proxy_contract.address] + # Sanity check. + with pytest.raises(ContractNotFoundError): + _ = chain.contracts.instance_at(proxy_contract.address) + + def get_contract_type(address, *args, **kwargs): + # Mock etherscan backend. + if address == target_contract.address: + return target_contract.contract_type + elif address == proxy_contract.address: + return proxy_contract.contract_type + + raise ValueError("Fake explorer only knows about proxy and target contracts.") + + with create_mock_sepolia() as network: + # Setup our network to use our fake explorer. + mock_explorer.get_contract_type.side_effect = get_contract_type + network.__dict__["explorer"] = mock_explorer + + # Typical flow: user attempts to get an un-cached contract type from Etherscan. + # That contract may be a proxy, in which case we should get a type + # w/ both proxy ABIs and the target ABIs. + contract_from_explorer = chain.contracts.instance_at(proxy_contract.address) + + # Ensure we can call proxy methods! + assert contract_from_explorer.masterCopy # No attr error! + + # Ensure we can call target methods! + assert contract_from_explorer.myNumber # No attr error! diff --git a/tests/functional/geth/test_proxy.py b/tests/functional/geth/test_proxy.py index f185711094..336294bef8 100644 --- a/tests/functional/geth/test_proxy.py +++ b/tests/functional/geth/test_proxy.py @@ -57,12 +57,10 @@ def test_uups_proxy(get_contract_type, geth_contract, owner, ethereum): @geth_process_test -def test_gnosis_safe(get_contract_type, geth_contract, owner, ethereum, chain): +def test_gnosis_safe(safe_proxy_container, geth_contract, owner, ethereum, chain): # Setup a proxy contract. - _type = get_contract_type("SafeProxy") - contract = ContractContainer(_type) target = geth_contract.address - proxy_instance = owner.deploy(contract, target) + proxy_instance = owner.deploy(safe_proxy_container, target) # (test) actual = ethereum.get_proxy_info(proxy_instance.address) diff --git a/tests/functional/test_proxy.py b/tests/functional/test_proxy.py index 6d4302bd04..4274797946 100644 --- a/tests/functional/test_proxy.py +++ b/tests/functional/test_proxy.py @@ -5,9 +5,12 @@ """ -def test_minimal_proxy(ethereum, minimal_proxy): +def test_minimal_proxy(ethereum, minimal_proxy, chain): actual = ethereum.get_proxy_info(minimal_proxy.address) assert actual is not None assert actual.type == ProxyType.Minimal # It is the placeholder value still. assert actual.target == "0xBEbeBeBEbeBebeBeBEBEbebEBeBeBebeBeBebebe" + # Show getting the contract using the proxy address. + contract = chain.contracts.instance_at(minimal_proxy.address) + assert contract.abi == [] # No target ABIs; no proxy ABIs either.