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.