def __init__(self, vyper_module: vy_ast.Module, fn_node: vy_ast.FunctionDef, namespace: dict) -> None: self.vyper_module = vyper_module self.fn_node = fn_node self.namespace = namespace self.func = fn_node._metadata["type"] self.annotation_visitor = StatementAnnotationVisitor( fn_node, namespace) namespace.update(self.func.arguments) if self.func.visibility is FunctionVisibility.INTERNAL: node_list = fn_node.get_descendants(vy_ast.Attribute, { "value.id": "msg", "attr": {"data", "sender"} }) if node_list: raise StateAccessViolation( f"msg.{node_list[0].attr} is not allowed in internal functions", node_list[0]) if self.func.mutability == StateMutability.PURE: node_list = fn_node.get_descendants( vy_ast.Attribute, { "value.id": set(CONSTANT_ENVIRONMENT_VARS.keys()).union( set(MUTABLE_ENVIRONMENT_VARS.keys())) }, ) if node_list: raise StateAccessViolation( "not allowed to query contract or environment variables in pure functions", node_list[0], ) if self.func.mutability is not StateMutability.PAYABLE: node_list = fn_node.get_descendants(vy_ast.Attribute, { "value.id": "msg", "attr": "value" }) if node_list: raise NonPayableViolation( "msg.value is not allowed in non-payable functions", node_list[0]) for node in fn_node.body: self.visit(node) if self.func.return_type: if not check_for_terminus(fn_node.body): raise FunctionDeclarationException( f"Missing or unmatched return statements in function '{fn_node.name}'", fn_node, )
def __init__(self, fn_node: vy_ast.FunctionDef, namespace: dict) -> None: self.func = namespace["self"].get_member(fn_node.name, fn_node) self.namespace = namespace self.expr_visitor = ExpressionAnnotationVisitor() fn_node._metadata["type"] = self.func