vyperlang / vyper

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

Folding Not Supported in Certain Locations #4190

Open ritzdorf opened 4 months ago

ritzdorf commented 4 months ago

Version Information

Several Vyper constructs require or can be optimized if constant values are provided. To achieve this, AST nodes can be folded to constants by the compiler, however, the following locations do not support folding:

POC

The following example demonstrates the different issues.

@external
def foo():
    x: Bytes[32] = slice(msg.data, 0, 31 + 1) # StructureException
@external
def foo(tuple: (uint256,uint256)) -> uint256:
    return tuple[0+1] # InvalidType
k: constant(Bytes[3]) = b'aaa'
@external
def foo():

    a: Bytes[2] = convert (k, Bytes[2]) # compiles instead of failing
    b: Bytes[2] = convert (b'aaa', Bytes[2]) # TypeMismatch
a: constant(uint256) = 12
@external
def foo():
    # The following check is inserted by the compiler although it is not necessary
    # [assert, [iszero, [shr, 128, 12 <12>]]],
    b: uint128 = convert (a, uint128)
topic: constant(bytes32) = 0x1212121212121210212801291212121212121210121212121212121212121212
@external
def foo():
    raw_log([[topic]][0], b'') # InvalidType
ritzdorf commented 4 months ago

One more location to add: default values.

Example:

@external
def foo(x: int256 = 2**255-1):

does not compile with:

TypeMismatch('Expected int256 but literal can only be cast as uint256.', vyper.ast.nodes.Int:
charles-cooper commented 1 month ago

One more location to add: default values.

Example:

@external
def foo(x: int256 = 2**255-1):

does not compile with:

TypeMismatch('Expected int256 but literal can only be cast as uint256.', vyper.ast.nodes.Int:

this one is expected behavior i think, since 2**255 is out of bounds of the range of int256, and compile-time safemath should match runtime safemath.