Exemple #1
0
    def _validate_arg_types(self, node):
        num_args = len(
            self._inputs)  # the number of args the signature indicates

        expect_num_args = num_args
        if self._has_varargs:
            # note special meaning for -1 in validate_call_args API
            expect_num_args = (num_args, -1)

        validate_call_args(node, expect_num_args, self._kwargs)

        for arg, (_, expected) in zip(node.args, self._inputs):
            self._validate_single(arg, expected)

        for kwarg in node.keywords:
            kwarg_settings = self._kwargs[kwarg.arg]
            if kwarg_settings.require_literal and not isinstance(
                    kwarg.value, vy_ast.Constant):
                raise TypeMismatch("Value for kwarg must be a literal",
                                   kwarg.value)
            self._validate_single(kwarg.value, kwarg_settings.typ)

        # typecheck varargs. we don't have type info from the signature,
        # so ensure that the types of the args can be inferred exactly.
        varargs = node.args[num_args:]
        if len(varargs) > 0:
            assert self._has_varargs  # double check validate_call_args
        for arg in varargs:
            # call get_exact_type_from_node for its side effects -
            # ensures the type can be inferred exactly.
            get_exact_type_from_node(arg)
Exemple #2
0
 def visit_Log(self, node):
     if not isinstance(node.value, vy_ast.Call):
         raise StructureException("Log must call an event", node)
     event = get_exact_type_from_node(node.value.func)
     if not isinstance(event, Event):
         raise StructureException("Value is not an event", node.value)
     event.fetch_call_return(node.value)
Exemple #3
0
    def visit_Expr(self, node):
        if not isinstance(node.value, vy_ast.Call):
            raise StructureException(
                "Expressions without assignment are disallowed", node)
        fn_type = get_exact_type_from_node(node.value.func)
        if isinstance(fn_type, Event):
            raise StructureException(
                "To call an event you must use the `log` statement", node)

        if isinstance(fn_type, ContractFunction):
            if (fn_type.mutability > StateMutability.VIEW
                    and self.func.mutability <= StateMutability.VIEW):
                raise StateAccessViolation(
                    f"Cannot call a mutating function from a {self.func.mutability.value} function",
                    node,
                )

            if self.func.mutability == StateMutability.PURE:
                raise StateAccessViolation(
                    f"Cannot call any function from a {self.func.mutability.value} function",
                    node)
        return_value = fn_type.fetch_call_return(node.value)
        if (return_value and not isinstance(fn_type, MemberFunctionDefinition)
                and not isinstance(fn_type, ContractFunction)):
            raise StructureException(
                f"Function '{fn_type._id}' cannot be called without assigning the result",
                node)
        self.expr_visitor.visit(node.value)
Exemple #4
0
 def visit_Subscript(self, node, type_):
     base_type = get_exact_type_from_node(node.value)
     if isinstance(base_type, BaseTypeDefinition):
         # in the vast majority of cases `base_type` is a type definition,
         # however there are some edge cases with args to builtin functions
         self.visit(node.slice, base_type.get_index_type(node.slice.value))
     self.visit(node.value, base_type)
Exemple #5
0
    def visit_Call(self, node, type_):
        call_type = get_exact_type_from_node(node.func)
        node_type = type_ or call_type.fetch_call_return(node)
        node._metadata["type"] = node_type
        self.visit(node.func)

        if isinstance(call_type, ContractFunction) and call_type.is_internal:
            self.func.called_functions.add(call_type)

        if isinstance(call_type, (Event, ContractFunction)):
            # events and function calls
            for arg, arg_type in zip(node.args,
                                     list(call_type.arguments.values())):
                self.visit(arg, arg_type)
            for kwarg in node.keywords:
                # We should only see special kwargs
                self.visit(kwarg.value,
                           call_type.call_site_kwargs[kwarg.arg].typ)
        elif isinstance(call_type, StructPrimitive):
            # literal structs
            for value, arg_type in zip(node.args[0].values,
                                       list(call_type.members.values())):
                self.visit(value, arg_type)
        elif isinstance(call_type, MemberFunctionDefinition):
            assert len(node.args) == len(call_type.arg_types)
            for arg, arg_type in zip(node.args, call_type.arg_types):
                self.visit(arg, arg_type)
        else:
            # builtin functions
            arg_types = call_type.infer_arg_types(node)
            for arg, arg_type in zip(node.args, arg_types):
                self.visit(arg, arg_type)
            kwarg_types = call_type.infer_kwarg_types(node)
            for kwarg in node.keywords:
                self.visit(kwarg.value, kwarg_types[kwarg.arg])
Exemple #6
0
def _is_terminus_node(node: vy_ast.VyperNode) -> bool:
    if getattr(node, "_is_terminus", None):
        return True
    if isinstance(node, vy_ast.Expr) and isinstance(node.value, vy_ast.Call):
        func = get_exact_type_from_node(node.value.func)
        if getattr(func, "_is_terminus", None):
            return True
    return False
Exemple #7
0
    def infer_arg_types(self, node):
        self._validate_arg_types(node)
        ret = [expected for (_, expected) in self._inputs]

        # handle varargs.
        n_known_args = len(self._inputs)
        varargs = node.args[n_known_args:]
        if len(varargs) > 0:
            assert self._has_varargs
        ret.extend(get_exact_type_from_node(arg) for arg in varargs)
        return ret
Exemple #8
0
def check_kwargable(node: vy_ast.VyperNode) -> bool:
    """
    Check if the given node can be used as a default arg
    """
    if _check_literal(node):
        return True
    if isinstance(node, (vy_ast.Tuple, vy_ast.List)):
        return all(check_kwargable(item) for item in node.elements)
    if isinstance(node, vy_ast.Call):
        args = node.args
        if len(args) == 1 and isinstance(args[0], vy_ast.Dict):
            return all(check_kwargable(v) for v in args[0].values)

        call_type = get_exact_type_from_node(node.func)
        if getattr(call_type, "_kwargable", False):
            return True

    value_type = get_exact_type_from_node(node)
    # is_constant here actually means not_assignable, and is to be renamed
    return getattr(value_type, "is_constant", False)
Exemple #9
0
    def visit_AugAssign(self, node):
        if isinstance(node.value, vy_ast.Tuple):
            raise StructureException(
                "Right-hand side of assignment cannot be a tuple", node.value)

        target = get_exact_type_from_node(node.target)

        validate_expected_type(node.value, target)
        target.validate_modification(node, self.func.mutability)

        self.expr_visitor.visit(node.value)
Exemple #10
0
 def visit_AugAssign(self, node):
     if isinstance(node.value, vy_ast.Tuple):
         raise StructureException(
             "Right-hand side of assignment cannot be a tuple", node.value)
     target = get_exact_type_from_node(node.target)
     validate_expected_type(node.value, target)
     if self.func.mutability <= StateMutability.VIEW and target.location == DataLocation.STORAGE:
         raise StateAccessViolation(
             f"Cannot modify storage in a {self.func.mutability.value} function",
             node)
     target.validate_modification(node)
Exemple #11
0
def check_constant(node: vy_ast.VyperNode) -> bool:
    """
    Check if the given node is a literal or constant value.
    """
    if check_literal(node):
        return True
    if isinstance(node, (vy_ast.Tuple, vy_ast.List)):
        for item in node.elements:
            if not check_constant(item):
                return False
        return True

    value_type = get_exact_type_from_node(node)
    return getattr(value_type, "is_constant", False)
Exemple #12
0
 def visit_Compare(self, node, type_):
     if isinstance(node.op, (vy_ast.In, vy_ast.NotIn)):
         if isinstance(node.right, vy_ast.List):
             type_ = get_common_types(node.left, *node.right.elements).pop()
             self.visit(node.left, type_)
             for element in node.right.elements:
                 self.visit(element, type_)
         else:
             type_ = get_exact_type_from_node(node.right)
             self.visit(node.right, type_)
             self.visit(node.left, type_.value_type)
     else:
         type_ = get_common_types(node.left, node.right).pop()
         self.visit(node.left, type_)
         self.visit(node.right, type_)
Exemple #13
0
 def visit_Compare(self, node, type_):
     if isinstance(node.op, (vy_ast.In, vy_ast.NotIn)):
         if isinstance(node.right, vy_ast.List):
             type_ = get_common_types(node.left, *node.right.elements).pop()
             self.visit(node.left, type_)
             rlen = len(node.right.elements)
             self.visit(node.right, ArrayDefinition(type_, rlen))
         else:
             type_ = get_exact_type_from_node(node.right)
             self.visit(node.right, type_)
             self.visit(node.left, type_.value_type)
     else:
         type_ = get_common_types(node.left, node.right).pop()
         self.visit(node.left, type_)
         self.visit(node.right, type_)
Exemple #14
0
def _validate_address_code_attribute(node: vy_ast.Attribute) -> None:
    value_type = get_exact_type_from_node(node.value)
    if isinstance(value_type, AddressDefinition) and node.attr == "code":
        # Validate `slice(<address>.code, start, length)` where `length` is constant
        parent = node.get_ancestor()
        if isinstance(parent, vy_ast.Call):
            ok_func = isinstance(parent.func,
                                 vy_ast.Name) and parent.func.id == "slice"
            ok_args = len(parent.args) == 3 and isinstance(
                parent.args[2], vy_ast.Int)
            if ok_func and ok_args:
                return
        raise StructureException(
            "(address).code is only allowed inside of a slice function with a constant length",
            node)
Exemple #15
0
def check_constant(node: vy_ast.VyperNode) -> bool:
    """
    Check if the given node is a literal or constant value.
    """
    if _check_literal(node):
        return True
    if isinstance(node, (vy_ast.Tuple, vy_ast.List)):
        return all(check_constant(item) for item in node.elements)
    if isinstance(node, vy_ast.Call):
        args = node.args
        if len(args) == 1 and isinstance(args[0], vy_ast.Dict):
            return all(check_constant(v) for v in args[0].values)

        call_type = get_exact_type_from_node(node.func)
        if getattr(call_type, "_kwargable", False):
            return True

    return False
Exemple #16
0
    def visit_Subscript(self, node, type_):
        if isinstance(node.value, vy_ast.List):
            possible_base_types = get_possible_types_from_node(node.value)

            if len(possible_base_types) == 1:
                base_type = possible_base_types.pop()

            elif type_ and len(possible_base_types) > 1:
                for possible_type in possible_base_types:
                    if isinstance(possible_type.value_type, type(type_)):
                        base_type = possible_type
                        break

        else:
            base_type = get_exact_type_from_node(node.value)
        if isinstance(base_type, BaseTypeDefinition):
            # in the vast majority of cases `base_type` is a type definition,
            # however there are some edge cases with args to builtin functions
            self.visit(node.slice, base_type.get_index_type(node.slice.value))
        self.visit(node.value, base_type)
Exemple #17
0
    def visit_Call(self, node, type_):
        call_type = get_exact_type_from_node(node.func)
        node._metadata["type"] = type_ or call_type.fetch_call_return(node)
        self.visit(node.func)

        if isinstance(call_type, (Event, ContractFunction)):
            # events and internal function calls
            for arg, arg_type in zip(node.args,
                                     list(call_type.arguments.values())):
                self.visit(arg, arg_type)
        elif isinstance(call_type, StructPrimitive):
            # literal structs
            for value, arg_type in zip(node.args[0].values,
                                       list(call_type.members.values())):
                self.visit(value, arg_type)
        elif node.func.id not in ("empty", "range"):
            # builtin functions
            for arg in node.args:
                self.visit(arg, None)
            for kwarg in node.keywords:
                self.visit(kwarg.value, None)
Exemple #18
0
    def visit_Subscript(self, node, type_):
        node._metadata["type"] = type_

        if isinstance(type_, TypeTypeDefinition):
            # don't recurse; can't annotate AST children of type definition
            return

        if isinstance(node.value, vy_ast.List):
            possible_base_types = get_possible_types_from_node(node.value)

            if len(possible_base_types) == 1:
                base_type = possible_base_types.pop()

            elif type_ is not None and len(possible_base_types) > 1:
                for possible_type in possible_base_types:
                    if isinstance(possible_type.value_type, type(type_)):
                        base_type = possible_type
                        break

        else:
            base_type = get_exact_type_from_node(node.value)

        self.visit(node.slice, base_type.get_index_type())
        self.visit(node.value, base_type)
Exemple #19
0
 def visit_AugAssign(self, node):
     type_ = get_exact_type_from_node(node.target)
     self.expr_visitor.visit(node.target, type_)
     self.expr_visitor.visit(node.value, type_)
Exemple #20
0
 def visit_Name(self, node, type_):
     node._metadata["type"] = get_exact_type_from_node(node)
Exemple #21
0
 def visit_Attribute(self, node, type_):
     base_type = get_exact_type_from_node(node.value)
     node._metadata["type"] = base_type.get_member(node.attr, None)
     self.visit(node.value, None)
Exemple #22
0
 def visit_Name(self, node, type_):
     if isinstance(type_, TypeTypeDefinition):
         node._metadata["type"] = type_
     else:
         node._metadata["type"] = get_exact_type_from_node(node)