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

Importing interfaces not as docs describe #2900

Closed
PatrickAlphaC opened this issue Jun 7, 2022 · 7 comments · Fixed by #3725
Closed

Importing interfaces not as docs describe #2900

PatrickAlphaC opened this issue Jun 7, 2022 · 7 comments · Fixed by #3725
Labels
bug - documentation an issue with documentation

Comments

@PatrickAlphaC
Copy link

Version Information

  • vyper Version (output of vyper --version): 0.3.3
  • OS: osx
  • Python Version (output of python --version): 3.9.5

What's your issue about?

Please include information like:

  • full output of the error you received
  • what command you ran
  • the code that caused the failure (see this link for help with formatting code)
  • please try running your example with the --debug flag turned on

I have an interface that looks like such:

# @version ^0.3.3
interface IFace:
    def read_stuff() -> uint256: view

And a contract that looks as such:

# @version ^0.3.3
from interfaces.IFace import IFace

@external
@view
def read_contract(some_address: address) -> uint256:
    myContract: IFace = IFace(some_address)
    return myContract.read_stuff()

However, when I run vyper contracts/MyContract.vy I get:

Error compiling: contracts/MyContract.vy
vyper.exceptions.UnknownAttribute: IFace has no member 'read_stuff'. 
  contract "contracts/MyContract.vy", function "read_contract", line 11:11 
       10     myContract: IFace = IFace(some_address)
  ---> 11     return myContract.read_stuff()
  -------------------^
       12

According to the documentation, when importing interfaces, you need to use regular vyper syntax. However, adjusting my interface as such:

# @version ^0.3.3

interface IFace:
    @external
    def read_stuff() -> uint256: 
        pass

Results in this error:

vyper.exceptions.StructureException: Body must only contain state mutability label
  contract "contracts/interfaces/IFace.vy", function "read_stuff", line 6:8 
       5     def read_stuff() -> uint256:
  ---> 6         pass
  ---------------^
       7

How can it be fixed?

I'm not sure

@fubuloubu
Copy link
Member

fubuloubu commented Jun 7, 2022

So, you can't import types from other Vyper contracts. What the docs mean by "regular vyper syntax" is that your file structure and internals should look like this:

interfaces/IFace.vy:

@view
@external
def read_stuff() -> uint256: 
    pass

Contract.vy:

# @version ^0.3.3
import interfaces.IFace as IFace

@view
@external
def read_contract(some_address: address) -> uint256:
    myContract: IFace = IFace(some_address)
    return myContract.read_stuff()

@PatrickAlphaC
Copy link
Author

Got it. We should probably update the docs to be more clear - been slamming my head.

@fubuloubu fubuloubu added the bug - documentation an issue with documentation label Jun 7, 2022
@fubuloubu
Copy link
Member

There's also a longer term fix with libraries that is coming in #2431

@kaimast
Copy link

kaimast commented Feb 12, 2023

I'm still so confused by this. I have this one file named contract1.vy

@external
def interface_func():
    pass

And then this other file named contract2.vy

import contract1 as Contract1

@external
def main_func(_to_call: address):
    other_contract: Contract1 = Contract1(_to_call)
    to_call.interface_func()

However, compilation of contract2.vy fails with

vyper.exceptions.UndeclaredDefinition: Unknown interface: Contract1. Did you mean 'ERC20Detailed', or maybe 'ERC721'?
            line 1:0
             ---> 1 import contract1 as Contract1
             -------^

@fubuloubu
Copy link
Member

Try this

import .contract1 as Contract1

@kaimast
Copy link

kaimast commented Feb 12, 2023

I tried this before, but it yields in a syntax error:

vyper.exceptions.SyntaxException: invalid syntax (<unknown>, line 1)
line 1:8
---> 1 import .contract1 as Contract1
---------------^

I also tried putting a separate interface in a subfolder as people mentioned before, but that did not seem to work either.

@charles-cooper
Copy link
Member

this should be closed by the language redesign done in #3663 and #3725. there are still two ways of importing interfaces, via importing .vyi interface files and also by interface Foo: declarations. however, the issue at hand should be fixed, see the following example works:

# ifaces.vy
interface IFoo:
    def foo(): nonpayable
# contract.vy
from ifaces import foo

@external
def call_foo():
    foo.IFoo(msg.sender).foo()

honestly now that you can import types from other modules, we could remove the .vyi file machinery entirely in favor of the in-line interface declarations. i'm going to close this issue for now as soon as #3725 is merged though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug - documentation an issue with documentation
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants