When types are validated for literal lists passed to builtin functions, we perform the following check:
However, in this scenario, expected
is the type class, not an instance, so it always fails. As a result, the compilation fails.
We will use the builtin len()
function to demonstrate this issue.
The len()
function accepts a single argument, which can be either a string, byte array or dynamic array:
All builtin functions implement the BuiltinFunction
class, which calls the _validate_arg_types()
function, which calls self._validate_single()
for all arguments.
In the case of the len()
function being called with a literal list, the argument passed to _validate_single()
is the list node, and the expected type is a tuple of the allowed type classes:
This calls the validate_expected_type()
, where the given_types
returns all the possible types for the literal list.
In the event that the node is a literal list, we go down this code path:
As we can see, this checks that isinstance(expected, (DArrayT, SArrayT))
. Only when this is the case does it proceed to the _validate_literal_array()
function, which allows us to return safely without an error.
Unfortunately, isinstance()
tells us if an instance fits a given type. But expected
is not an instance — it is the type class itself. As a result, this check will always fail, and the compilation will fail.
The following Vyper contracts will fail to compile due to this error:
Contracts that include literal lists as arguments to builtin functions will fail to compile.
Manual Review
In validate_expected_type()
, adjust the check to ensure that the expected type matches with DArrayT
or SArrayT
, rather than requiring it to be an instance of it.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.