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

Compiler panic when importing interfaces with max_value() as a default argument value #3077

Closed
hadfieldn opened this issue Aug 30, 2022 · 5 comments · Fixed by #3079
Closed

Comments

@hadfieldn
Copy link

Version Information

  • vyper Version (output of vyper --version): 0.3.6
  • OS: osx
  • Python Version (output of python --version): 3.9.8

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 --verbose flag turned on

When a contract has a function that uses max_value(uint256) as a default argument value, it causes a compiler panic when it is imported as an interface:

# ContractB.vy (compiles successfully)

@view
@external
def foo(_max: uint256 = max_value(uint256)) -> uint256:
    return _max
# ContractA.vy (fails to compile)

import ContractB as ContractB

Compiling ContractA results in a compile error:

$ vyper ContractA.vy
Error compiling: ContractA.vy
vyper.exceptions.CompilerPanic: max_value should always be folded

This is an unhandled internal compiler error. Please create an issue on Github to notify the developers.

How can it be fixed?

Fill this in if you know how to fix it.

@hadfieldn
Copy link
Author

The same failure occurs when the default value is min_value(uint256), but it succeeds with empty(uint256).

@hadfieldn
Copy link
Author

hadfieldn commented Aug 30, 2022

As a workaround, if I declare a constant for the default value, it works, but I have to declare the same constant in the contract doing the import:

# ContractB.vy (compiles successfully)

# `MAX_UINT256` is deprecated, so we use `_MAX_UINT256`
_MAX_UINT256: constant(uint256) = max_value(uint256)


@view
@external
def foo(_max: uint256 = _MAX_UINT256) -> uint256:
    return _max

Fails unless _MAX_UINT256 is declared in ContractA:

# ContractA.vy (fails to compile)

import ContractB as ContractB
$ vyper ContractA.vy
Error compiling: ContractA.vy
vyper.exceptions.UndeclaredDefinition: '_MAX_UINT256' has not been declared.
  contract "ContractB", function "foo", line 9:24
       8 @external
  ---> 9 def foo(_max: uint256 = _MAX_UINT256) -> uint256:
  -------------------------------^
      10     return _max

Succeeds:

# ContractA.vy (compiles successfully)

import ContractB as ContractB

_MAX_UINT256: constant(uint256) = max_value(uint256)
$ vyper ContractA.vy
0x61000d61000f60003961000d6000f3a165767970657283000306000b

@charles-cooper
Copy link
Member

whoa, that also seems like a bug. you should not be able to override constants in the imported contract from the importing contract.

@hadfieldn
Copy link
Author

Also works if I declare the interface inline:

# ContractA.vy (compiles successfully)

interface ContractB:
    def foo(_max: uint256 = max_value(uint256)) -> uint256: view

@hadfieldn
Copy link
Author

Related to the need to redeclare constants locally, but probably a separate issue -- if the imported contract references a struct in its function signatures, I also have to declare that Struct in the importing contract.

(I know this was reported in #2670)

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

Successfully merging a pull request may close this issue.

2 participants