vyper icon indicating copy to clipboard operation
vyper copied to clipboard

`Implements` directive behave inconsistently with `default` parameters

Open trocher opened this issue 2 years ago • 4 comments

Version Information

  • vyper Version (output of vyper --version): 0.3.8+commit.6020b8bb
  • OS: OSX
  • Python Version (output of python --version): 3.8.0

What's your issue about?

While Vyper allows defaults to be mentioned in interfaces, the concrete default values are ignored and the only thing done by the presence of such values in the interface is to adds an overload of the given function.

Mixing such interfaces with the implements directive lead to some inconsistent behaviours.

  • When using the implements directive with an interface declaring a function with default arguments, it is enough for the contract implementing it to define the "long overload", for example, the following contract compiles although the function goo() is not implemented (note that a call to test() would then revert)
interface A:
    def goo(a:uint16=32)-> uint16:nonpayable

implements: A

@external
def goo(a:uint16)->uint16:
    return a

@external
def test() -> uint16:
    d:A = A(self)
    return d.goo()
  • On the other side, if the interface is declaring a function with no arguments for example, an implementation having a function with default arguments would not pass the implements directive as the short overload is somehow not taken into account. To illustrate, this contract would not compile because of the implements.
interface A:
    def goo()-> uint16:nonpayable

implements: A

@external
def goo(a:uint16=6)->uint16:
    return a

trocher avatar Dec 05 '22 17:12 trocher

Some good finds today

fubuloubu avatar Dec 05 '22 17:12 fubuloubu

Can confirm the inconsistent behavior. Let me document another example, the ERC721 interface: If you do something like the following (without data: Bytes[1024]=b""), the compiler will not throw even though the overloaded function of safeTransferFrom (without data payload) is not implemented and therefore the contract doesn't implement the ERC721 interface completely:

from vyper.interfaces import ERC721
implements: ERC721

@external
@payable
def safeTransferFrom(owner: address, to: address, token_id: uint256, data: Bytes[1024]):
    ...

So the implements keyword is not ensuring feature completeness in a sense.

pcaversaccio avatar Feb 20 '23 22:02 pcaversaccio

btw, it should be allowed to use = ... for defaults, so you don't have to specify a specific value (should the value be enforced if present?)

fubuloubu avatar Sep 14 '24 19:09 fubuloubu

btw, it should be allowed to use = ... for defaults, so you don't have to specify a specific value (should the value be enforced if present?)

That's a good point. Maybe we should always enforce defaults to be ... in interfaces

charles-cooper avatar Sep 15 '24 16:09 charles-cooper