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

Ape-compiled Contracts not being recognized in test suite #2262

Open
davoice-321 opened this issue Sep 2, 2024 · 12 comments · May be fixed by #2277
Open

Ape-compiled Contracts not being recognized in test suite #2262

davoice-321 opened this issue Sep 2, 2024 · 12 comments · May be fixed by #2277
Labels
category: bug Something isn't working

Comments

@davoice-321
Copy link

Environment information

  • OS: macOS / linux / win
  • Python Version: 3.11.8
  • ape and plugin versions:
$ ape --version
# 0.8.13

$ ape plugins list
# alchemy      0.8.0
  ens          0.8.0
  etherscan    0.8.2
  foundry      0.8.4
  hardhat      0.8.1
  infura       0.8.0
  solidity     0.8.3
  template     0.8.0
  tokens       0.8.0
  vyper        0.8.4
  • Contents of your ape-config.yaml (NOTE: do not post anything private like RPC urls or secrets!):
$ cat ape-config.yaml
# name: Project

plugins:
  - name: solidity
    version: ">=0.6.0 <0.9.0"
  - name: hardhat
    version: "0.8.1"
  - name: etherscan
    version: "0.8.2"
  - name: foundry
    version: "0.8.4"

dependencies:
  # - name: openzeppelin
  #   github: OpenZeppelin/openzeppelin-contracts
  #   version: 4.8.3
  - name: openzeppelin-3.4.2
    github: OpenZeppelin/openzeppelin-contracts
    version: 3.4.2
  - name: openzeppelin-4.5.0
    github: OpenZeppelin/openzeppelin-contracts
    version: 4.5.0
  - name: openzeppelin-4.3.0
    github: OpenZeppelin/openzeppelin-contracts
    version: 4.3.0
  - name: setprotocol
    github: SetProtocol/set-protocol-v2
    version: 0.11.0

What went wrong?

ABI and type of contract-deployed contracts are not being read during testing
Situation

-I'm using conftest.py to set up a deployment for a series of contracts.

2 of the contracts are deployed using owner.deploy()
2 of the contracts are deployed through a contract that was compiled using Ape

Using the contract-deployed contracts works in the following instances:

When the contracts are deployed and used in a script (ape run)
When the contracts are deployed and used in a conftest.py function (i'm assuming because running this function is like running a script)

The contracts are being outputted from the conftest.py function. Expected behavior is that the ABI and type of contract-deployed contracts are read properly during testing.

Here is the output from the conftest.py function re: the contracts (printing the contracts in the test function).

<Identified Contract1 0x68b9...>, <Unnamed contract 0xe94b0...>, <Unnamed contract 0xCcd7A...>, <Identified Contract2 0x539a46F...>)

Both unnamed contracts were compiled with Ape and should be identifiable.

Unnamed contracts are being identified within conftest.py by directly referencing the ABI. In addition, one of the unnamed contracts is calling an initialization function within the conftest.py function. That function runs without error indicating that the ABI is successfully being referenced properly in the context of the conftest.py function.

How contracts are being identified.
token_abi_path = os.environ["token_abi_path"]
contract_1= Contract(address, abi=token_abi_path)

contract_abi = project.Contract.contract_type.abi
contract_2 = Contract(address_2, abi=contract_abi)

Note that the contract addresses for the contract-deployed contracts are being emitted via events. which is how they are being captured to link the address to the ABI:

deployment_events = contract1.decode_logs()

contract_1_address = deployment_events[-1]._Token

contract_2_address = deployment_events[2].contractAddress

I tried this using a tenderly fork and a mainnet-fork

Error trace from Tenderly Fork

self = <Node (Tenderly/v1.0.0) chain_id=1337>, rpc = 'debug_setHead', parameters = ['0x13a5715']

def make_request(self, rpc: str, parameters: Optional[Iterable] = None) -> Any:
    parameters = parameters or []

    try:
        result = self.web3.provider.make_request(RPCEndpoint(rpc), parameters)
    except HTTPError as err:
        if "method not allowed" in str(err).lower():
            raise APINotImplementedError(
                f"RPC method '{rpc}' is not implemented by this node instance."
            )

        raise ProviderError(str(err)) from err

    if "error" in result:
        error = result["error"]
        message = (
            error["message"] if isinstance(error, dict) and "message" in error else str(error)
        )

        if (
            "does not exist/is not available" in str(message)
            or re.match(r"Method .*?not found", message)
            or message.startswith("Unknown RPC Endpoint")
            or "RPC Endpoint has not been implemented" in message
        ):
            raise APINotImplementedError(
                f"RPC method '{rpc}' is not implemented by this node instance."
            )

      raise ProviderError(message)

E ape.exceptions.ProviderError: method not found

../venv/lib/python3.11/site-packages/ape_ethereum/provider.py:1130: ProviderError

Error trace from mainnet fork

FAILED tests/test.py::test_1 - ape.exceptions.ContractNotFoundError: Failed to get contract type for address '0xe2f7b5...'. Contract may need verification.

How can it be fixed?

Ensure ABIs and types for contract-deployed contracts used in scripts and conftest.py functions are exported properly in testing.

@davoice-321 davoice-321 added the category: bug Something isn't working label Sep 2, 2024
Copy link

linear bot commented Sep 2, 2024

@davoice-321
Copy link
Author

Additional note:

It looks like ape has trouble even identifying previously-identified contracts in test functions.

Trace from an error where the contract was identified, but still throws 'contract may need verification' error in tests:

E ape.exceptions.ContractNotFoundError: Failed to get contract type for address '0x5C3A8b...'. Contract may need verification.

contract is properly identified when exported from conftest.py function:

<Identified Contract 0x5C3A8b...>

Contract was also deployed via ape.

ape shouldn't require verification for contracts that were compiled within Ape -- whether they are deployed by ape (as in this case) or via a contract.

contract types and ABIs should be properly exported from when fixtures are set up to deploy and export contract types and ABIs.

@antazoey
Copy link
Member

antazoey commented Sep 3, 2024

I wonder if isolation has to do with it?
You can try running with ape test --disable-isolation to see if that helps.

(edit: because Ape's contract caching system doesn't care if you are using ape test or ape run commands, so the only different I can think of is the isolation / scoping issues, but also I am working on a test repo branch with some setup to help debug problems, will share in a bit)

@antazoey
Copy link
Member

antazoey commented Sep 3, 2024

I am attempting to reproduce here: antazoey/ape-playground#5
So far, I haven't hit any problems

@davoice-321
Copy link
Author

davoice-321 commented Sep 3, 2024

I was able to successfully run the tests with --disable-isolation.

However, there are some tests that need to run in isolation, as they change state.

I'm using chain.snapshot() and chain.restore() to run tests in isolation given the flag.

@fubuloubu
Copy link
Member

fubuloubu commented Sep 3, 2024

are you sending transactions within your scope="session" fixtures? I have noticed that will never seem to work properly if you are doing that, and should use normal function scope

@antazoey
Copy link
Member

antazoey commented Sep 3, 2024

are you sending transactions within your scope="session" fixtures? I have noticed that will never seem to work properly if you are doing that, and should use normal function scope

Hmm, this doesn't ring true to me. Scoping does work, except when using parametrized fixtures.
See my linked example, which sends the tx in the session-scoped fixture.

@davoice-321
Copy link
Author

I am attempting to reproduce here: antazoey/ape-playground#5 So far, I haven't hit any problems

I see the test you've set up here. Thanks for this. I see that you're doing a contract deployment (via a factory contract), and the export is working.

Is there a way for you to test this with a different pattern, similar to what i'm using?

here it is:

-set up a dummy contract (deployer)
-within the contract, deploy two new contracts contractB contractC with an event providing the addresses
-fetch the addresses using the event logs and initialize the contracts using ape:

contractB = project.ContractB.at(contractBAddress)
contractC = project.ContractC.at(contractCAddress)

return contracts through the conftest.py function and then run a test using those contracts.

@davoice-321
Copy link
Author

are you sending transactions within your scope="session" fixtures? I have noticed that will never seem to work properly if you are doing that, and should use normal function scope

i tried this with scope="session" and scope="module". both fail when --disable-isolation flag is not provided.

@antazoey
Copy link
Member

antazoey commented Sep 3, 2024

@davoice-321 I made the updates! But I haven't hit the problem yet.

@antazoey
Copy link
Member

antazoey commented Sep 9, 2024

Do you happen to have to minimal repro for us?

@davoice-321
Copy link
Author

hi. i don't have a minimal repo unfortunately. I've been able to overcome the issue by running tests with --disable-isolation

@antazoey antazoey linked a pull request Sep 11, 2024 that will close this issue
3 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
category: bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants