vyperlang / vyper

Pythonic Smart Contract Language for the EVM
https://vyperlang.org
Other
4.83k stars 789 forks source link

Comparison not commutative when using `raw_call` #4079

Open ritzdorf opened 3 months ago

ritzdorf commented 3 months ago

Version Information

Issue description

This is related to https://github.com/vyperlang/vyper/issues/3253 to the previous issue only mentioned literals. It appears this can also appear with raw_call.

raw_call(...) == Bytes

might work but

Bytes == raw_call(...)

might not compile.

POC

All comparisons work except for the commented one at the bottom:

#@version 0.4.0.rc3

@internal
def four_bytes() -> Bytes[5]:
    return slice(msg.data, 1, 4)

@internal
def five_bytes() -> Bytes[5]:
    return slice(msg.data, 1, 5)

@external
def foo(a: address):
    # These all work
    h: uint256 = 2 if (raw_call(a, empty(Bytes[31]), max_outsize=12, revert_on_failure = False)[1] == empty(Bytes[31])) else 1
    i: uint256 = 2 if (self.five_bytes() == empty(Bytes[31])) else 1
    j: uint256 = 2 if (empty(Bytes[31]) == raw_call(a, empty(Bytes[31]), max_outsize=12, revert_on_failure = False)[1] ) else 1
    k: uint256 = 2 if (empty(Bytes[31]) == self.five_bytes()) else 1
    l: uint256 = 2 if (self.four_bytes() == self.five_bytes()) else 1
    m: uint256 = 2 if (self.five_bytes() == self.four_bytes()) else 1
    n: uint256 = 2 if (raw_call(a, empty(Bytes[31]), max_outsize=12, revert_on_failure = False)[1] == self.five_bytes()) else 1
    # This one does not work
    #x: uint256 = 2 if (self.five_bytes() == raw_call(a, empty(Bytes[31]), max_outsize=12, revert_on_failure = False)[1]) else 1

The bottom one fails compilation with:

vyper.exceptions.TypeMismatch: Cannot perform equality between dislike types