Пример #1
0
 def visitIdentifier(self, ctx: SolidityParser.IdentifierContext):
     name: str = ctx.name.text
     if name.startswith(cfg.reserved_name_prefix) or name.startswith(f'_{cfg.reserved_name_prefix}'):
         raise SyntaxException(f'Identifiers must not start with reserved prefix _?{cfg.reserved_name_prefix}', ctx, self.code)
     elif name.endswith(cfg.reserved_conflict_resolution_suffix):
         raise SyntaxException(f'Identifiers must not end with reserved suffix {cfg.reserved_name_prefix}', ctx, self.code)
     return ast.Identifier(name)
Пример #2
0
    def visitAnnotatedTypeName(self, ctx: SolidityParser.AnnotatedTypeNameContext):
        pa = None
        hom = Homomorphism.NON_HOMOMORPHIC
        if ctx.privacy_annotation is not None:
            pa = self.visit(ctx.privacy_annotation)
            if ctx.homomorphism is not None:
                hom = self.visit(ctx.homomorphism)

            if not (isinstance(pa, ast.AllExpr) or isinstance(pa, ast.MeExpr) or isinstance(pa, IdentifierExpr)):
                raise SyntaxException('Privacy annotation can only be me | all | Identifier', ctx.privacy_annotation, self.code)
            if isinstance(pa, ast.AllExpr) and hom != Homomorphism.NON_HOMOMORPHIC:
                raise SyntaxException('Public types cannot be homomorphic', ctx.homomorphism, self.code)

        return ast.AnnotatedTypeName(self.visit(ctx.type_name), pa, hom)
Пример #3
0
 def visitElementaryTypeName(self, ctx: SolidityParser.ElementaryTypeNameContext):
     t = ctx.getText()
     if t == 'address':
         return ast.AddressTypeName()
     elif t == 'address payable':
         return ast.AddressPayableTypeName()
     elif t == 'bool':
         return ast.BoolTypeName()
     elif t.startswith('int'):
         return ast.IntTypeName(t)
     elif t.startswith('uint'):
         return ast.UintTypeName(t)
     elif t == 'var':
         raise SyntaxException(f'Use of unsupported var keyword', ctx, self.code)
     else:
         raise SyntaxException(f"Use of unsupported type '{t}'.", ctx, self.code)
Пример #4
0
 def visitHomomorphismAnnotation(self, ctx:SolidityParser.HomomorphismAnnotationContext):
     t = ctx.getText()
     for h in Homomorphism:
         if h.type_annotation == t:
             return h
     else:
         raise SyntaxException(f'Unsupported homomorphism {t}', ctx, self.code)
Пример #5
0
    def visitVersionPragma(self, ctx: SolidityParser.VersionPragmaContext):
        version = ctx.ver.getText().strip()
        spec = NpmSpec(version)
        name = self.handle_field(ctx.name)
        if name == 'zkay' and Version(cfg.zkay_version) not in spec:
            raise SyntaxException(f'Contract requires a different zkay version.\n'
                                  f'Current version is {cfg.zkay_version} but pragma zkay mandates {version}.',
                                  ctx.ver, self.code)
        elif name != 'zkay' and spec != cfg.zkay_solc_version_compatibility:
            # For backwards compatibility with older zkay versions
            assert name == 'solidity'
            raise SyntaxException(f'Contract requires solidity version {spec}, which is not compatible '
                                  f'with the current zkay version (requires {cfg.zkay_solc_version_compatibility}).',
                                  ctx.ver, self.code)

        return f'{name} {version}'
Пример #6
0
    def visitFunctionCallExpr(self, ctx: SolidityParser.FunctionCallExprContext):
        func = self.visit(ctx.func)
        args = self.handle_field(ctx.args)

        if isinstance(func, IdentifierExpr):
            if func.idf.name == 'reveal':
                if len(args) != 2:
                    raise SyntaxException(f'Invalid number of arguments for reveal: {args}', ctx.args, self.code)
                return ReclassifyExpr(args[0], args[1], None)
            elif func.idf.name in self.rehom_expressions:
                name = func.idf.name
                homomorphism = self.rehom_expressions[name]
                if len(args) != 1:
                    raise SyntaxException(f'Invalid number of arguments for {name}: {args}', ctx.args, self.code)
                return RehomExpr(args[0], homomorphism)

        return FunctionCallExpr(func, args)
Пример #7
0
    def visitAnnotatedTypeName(self, ctx: SolidityParser.AnnotatedTypeNameContext):
        pa = None
        if ctx.privacy_annotation is not None:
            pa = self.visit(ctx.privacy_annotation)

            if not (isinstance(pa, ast.AllExpr) or isinstance(pa, ast.MeExpr) or isinstance(pa, IdentifierExpr)):
                raise SyntaxException('Privacy annotation can only be me | all | Identifier', ctx.privacy_annotation, self.code)

        return ast.AnnotatedTypeName(self.visit(ctx.type_name), pa)
Пример #8
0
 def handle_fdef(self, ctx):
     if isinstance(ctx, SolidityParser.ConstructorDefinitionContext):
         idf, ret_params = None, None
     else:
         idf, ret_params = self.visit(ctx.idf), self.handle_field(ctx.return_parameters)
         if '$' in idf.name:
             raise SyntaxException('$ is not allowed in zkay function identifiers', ctx.idf, self.code)
     params, mods, body = self.handle_field(ctx.parameters), self.handle_field(ctx.modifiers), self.visit(ctx.body)
     return ast.ConstructorOrFunctionDefinition(idf, params, mods, ret_params, body)
Пример #9
0
    def visitStringLiteralExpr(self, ctx: SolidityParser.StringLiteralExprContext):
        s = ctx.getText()

        # Remove quotes
        if s.startswith('"'):
            s = s[1:-1].replace('\\"', '"')
        else:
            s = s[2:-2]

        raise SyntaxException('Use of unsupported string literal expression', ctx, self.code)
Пример #10
0
 def visitContractDefinition(self, ctx: SolidityParser.ContractDefinitionContext):
     identifier = self.visit(ctx.idf)
     if '$' in identifier.name:
         raise SyntaxException('$ is not allowed in zkay contract identifiers', ctx.idf, self.code)
     parts = [self.visit(c) for c in ctx.parts]
     state_vars = [p for p in parts if isinstance(p, StateVariableDeclaration)]
     cfdefs = [p for p in parts if isinstance(p, ast.ConstructorOrFunctionDefinition)]
     constructors = [p for p in cfdefs if p.is_constructor]
     functions = [p for p in cfdefs if p.is_function]
     enums = [p for p in parts if isinstance(p, ast.EnumDefinition)]
     return ContractDefinition(identifier, state_vars, constructors, functions, enums)
Пример #11
0
    def visitFunctionCallExpr(self, ctx: SolidityParser.FunctionCallExprContext):
        func = self.visit(ctx.func)
        args = self.handle_field(ctx.args)

        if isinstance(func, IdentifierExpr):
            if func.idf.name == 'reveal':
                if len(args) != 2:
                    raise SyntaxException(f'Invalid number of arguments for reveal: {args}', ctx.args, self.code)
                return ReclassifyExpr(args[0], args[1])

        return FunctionCallExpr(func, args)
Пример #12
0
 def visitAssignmentExpr(self, ctx: SolidityParser.AssignmentExprContext):
     if not self.is_expr_stmt(ctx):
         raise SyntaxException('Assignments are only allowed as statements', ctx, self.code)
     lhs = self.visit(ctx.lhs)
     rhs = self.visit(ctx.rhs)
     assert ctx.op.text[-1] == '='
     op = ctx.op.text[:-1] if ctx.op.text != '=' else ''
     if op:
         # If the assignment contains an additional operator -> replace lhs = rhs with lhs = lhs 'op' rhs
         rhs = FunctionCallExpr(BuiltinFunction(op).override(line=ctx.op.line, column=ctx.op.column), [self.visit(ctx.lhs), rhs])
         rhs.line = ctx.rhs.start.line
         rhs.column = ctx.rhs.start.column + 1
     return ast.AssignmentStatement(lhs, rhs, op)
Пример #13
0
    def _handle_crement_expr(self, ctx, kind: str):
        if not self.is_expr_stmt(ctx):
            raise SyntaxException(f'{kind}-crement expressions are only allowed as statements', ctx, self.code)
        op = '+' if ctx.op.text == '++' else '-'

        one = NumberLiteralExpr(1)
        one.line = ctx.op.line
        one.column = ctx.op.column + 1

        fct = FunctionCallExpr(BuiltinFunction(op).override(line=ctx.op.line, column=ctx.op.column), [self.visit(ctx.expr), one])
        fct.line = ctx.op.line
        fct.column = ctx.op.column + 1

        return ast.AssignmentStatement(self.visit(ctx.expr), fct, f'{kind}{ctx.op.text}')
Пример #14
0
    def visitExpressionStatement(self, ctx: SolidityParser.ExpressionStatementContext):
        e = self.visit(ctx.expr)
        if isinstance(e, ast.Statement):
            return e
        else:
            # handle require
            if isinstance(e, FunctionCallExpr):
                f = e.func
                if isinstance(f, IdentifierExpr):
                    if f.idf.name == 'require':
                        if len(e.args) != 1:
                            raise SyntaxException(f'Invalid number of arguments for require: {e.args}', ctx.expr, self.code)
                        return ast.RequireStatement(e.args[0])

            assert isinstance(e, ast.Expression)
            return ExpressionStatement(e)
Пример #15
0
 def visitEnumDefinition(self, ctx:SolidityParser.EnumDefinitionContext):
     idf = self.visit(ctx.idf)
     if '$' in idf.name:
         raise SyntaxException('$ is not allowed in zkay enum identifiers', ctx.idf, self.code)
     values = [self.visit(v) for v in ctx.values]
     return ast.EnumDefinition(idf, values)
Пример #16
0
 def visitEnumValue(self, ctx:SolidityParser.EnumValueContext):
     idf = self.visit(ctx.idf)
     if '$' in idf.name:
         raise SyntaxException('$ is not allowed in zkay enum value identifiers', ctx.idf, self.code)
     return ast.EnumValue(idf)
Пример #17
0
 def visitIndexExpr(self, ctx: SolidityParser.IndexExprContext):
     arr = self.visit(ctx.arr)
     if not isinstance(arr, ast.LocationExpr):
         raise SyntaxException(f'Expression cannot be indexed', ctx.arr, self.code)
     index = self.visit(ctx.index)
     return IndexExpr(arr, index)