Exemplo n.º 1
0
 def received(self,
              self_var: Expr,
              ctx: Context,
              pos=None,
              info=None) -> Expr:
     received_type = ctx.field_types[mangled.RECEIVED_FIELD]
     return helpers.struct_get(self.viper_ast, self_var,
                               mangled.RECEIVED_FIELD, received_type,
                               ctx.self_type, pos, info)
Exemplo n.º 2
0
 def get_balance(self,
                 self_var: Expr,
                 ctx: Context,
                 pos=None,
                 info=None) -> Expr:
     balance_type = ctx.field_types[names.ADDRESS_BALANCE]
     return helpers.struct_get(self.viper_ast, self_var,
                               names.ADDRESS_BALANCE, balance_type,
                               ctx.self_type, pos, info)
Exemplo n.º 3
0
 def increase_sent(self,
                   to: Expr,
                   amount: Expr,
                   res: List[Stmt],
                   ctx: Context,
                   pos=None,
                   info=None):
     self_var = ctx.self_var.local_var(ctx)
     sent_type = ctx.field_types[mangled.SENT_FIELD]
     sent = helpers.struct_get(self.viper_ast, self_var, mangled.SENT_FIELD,
                               sent_type, ctx.self_type, pos)
     sent_to = helpers.map_get(self.viper_ast, sent, to, self.viper_ast.Int,
                               self.viper_ast.Int, pos)
     sent_inc = self.viper_ast.Add(sent_to, amount, pos)
     sent_set = helpers.map_set(self.viper_ast, sent, to, sent_inc,
                                self.viper_ast.Int, self.viper_ast.Int, pos)
     self_set = helpers.struct_set(self.viper_ast, self_var, sent_set,
                                   mangled.SENT_FIELD, sent_type,
                                   ctx.self_type, pos)
     res.append(self.viper_ast.LocalVarAssign(self_var, self_set, pos,
                                              info))
Exemplo n.º 4
0
        def add_struct_members(struct, struct_type, components, wrapped=None):
            for member, member_type in struct_type.member_types.items():
                new_components = components + [member]
                mtype = self.type_translator.translate(member_type, ctx)
                get = helpers.struct_get(self.viper_ast, struct, member, mtype,
                                         struct_type, pos)
                if isinstance(member_type, StructType):
                    add_struct_members(get, member_type, new_components,
                                       wrapped)
                else:
                    if member == mangled.SELFDESTRUCT_FIELD:
                        name = f'{names.SELFDESTRUCT}()'
                    elif member == mangled.SENT_FIELD:
                        name = f'{names.SENT}()'
                    elif member == mangled.RECEIVED_FIELD:
                        name = f'{names.RECEIVED}()'
                    else:
                        name = '.'.join(new_components)

                    if wrapped:
                        name = wrapped(name)

                    add_model_var(name, member_type, get, new_components)
Exemplo n.º 5
0
 def increase_received(self,
                       amount: Expr,
                       res: List[Stmt],
                       ctx: Context,
                       pos=None,
                       info=None):
     self_var = ctx.self_var.local_var(ctx)
     # TODO: pass this as an argument
     msg_sender = helpers.msg_sender(self.viper_ast, ctx, pos)
     rec_type = ctx.field_types[mangled.RECEIVED_FIELD]
     rec = helpers.struct_get(self.viper_ast, self_var,
                              mangled.RECEIVED_FIELD, rec_type,
                              ctx.self_type, pos)
     rec_sender = helpers.map_get(self.viper_ast, rec, msg_sender,
                                  self.viper_ast.Int, self.viper_ast.Int,
                                  pos)
     rec_inc_sum = self.viper_ast.Add(rec_sender, amount, pos)
     rec_set = helpers.map_set(self.viper_ast, rec, msg_sender, rec_inc_sum,
                               self.viper_ast.Int, self.viper_ast.Int, pos)
     self_set = helpers.struct_set(self.viper_ast, self_var, rec_set,
                                   mangled.RECEIVED_FIELD, rec_type,
                                   ctx.self_type, pos)
     res.append(self.viper_ast.LocalVarAssign(self_var, self_set, pos,
                                              info))
Exemplo n.º 6
0
 def sent(self, self_var: Expr, ctx: Context, pos=None, info=None) -> Expr:
     sent_type = ctx.field_types[mangled.SENT_FIELD]
     return helpers.struct_get(self.viper_ast, self_var, mangled.SENT_FIELD,
                               sent_type, ctx.self_type, pos, info)
Exemplo n.º 7
0
        def construct(type, node):
            ret = []

            # If we encounter a bounded primitive type we add the following assumption:
            #   x >= lower
            #   x <= upper
            # where x is said integer
            if types.is_bounded(type):
                lower = self.viper_ast.IntLit(type.lower)
                upper = self.viper_ast.IntLit(type.upper)
                lcmp = self.viper_ast.LeCmp(lower, node)
                ucmp = self.viper_ast.LeCmp(node, upper)
                # If the no_overflows config option is enabled, we only assume non-negativity for uints
                if ctx.program.config.has_option(names.CONFIG_NO_OVERFLOWS):
                    if types.is_unsigned(type):
                        bounds = lcmp
                    else:
                        bounds = self.viper_ast.TrueLit()
                else:
                    bounds = self.viper_ast.And(lcmp, ucmp)
                ret.append(bounds)
            elif type == types.NON_NEGATIVE_INT:
                lower = self.viper_ast.IntLit(0)
                lcmp = self.viper_ast.LeCmp(lower, node)
                ret.append(lcmp)
            # If we encounter a map, we add the following assumptions:
            #   forall k: Key :: construct(map_get(k))
            #   forall k: Key :: map_get(k) <= map_sum()
            # where constuct constructs the assumption for the values contained
            # in the map (may be empty)
            elif isinstance(type, MapType):
                key_type = self.translate(type.key_type, ctx)
                value_type = self.translate(type.value_type, ctx)
                quant_var_name = ctx.new_quantified_var_name()
                quant_decl = self.viper_ast.LocalVarDecl(
                    quant_var_name, key_type)
                quant = quant_decl.localVar()
                new_node = helpers.map_get(self.viper_ast, node, quant,
                                           key_type, value_type)
                trigger = self.viper_ast.Trigger([new_node])
                sub_ret = construct(type.value_type, new_node)
                for r in sub_ret:
                    quantifier = self.viper_ast.Forall([quant_decl], [trigger],
                                                       r)
                    ret.append(quantifier)

                if types.is_unsigned(type.value_type):
                    mp_sum = helpers.map_sum(self.viper_ast, node, key_type)
                    r = self.viper_ast.LeCmp(new_node, mp_sum)
                    quantifier = self.viper_ast.Forall([quant_decl], [trigger],
                                                       r)
                    ret.append(quantifier)
            # If we encounter an array, we add the follwing assumptions:
            #   |array| == array_size
            #   forall i: Int :: 0 <= i && i < |array| ==> construct(array[i])
            # where construct recursively constructs the assumptions for nested arrays and maps
            elif isinstance(type, ArrayType):
                array_len = self.viper_ast.SeqLength(node)
                size = self.viper_ast.IntLit(type.size)
                if type.is_strict:
                    comp = self.viper_ast.EqCmp(array_len, size)
                else:
                    comp = self.viper_ast.LeCmp(array_len, size)
                ret.append(comp)

                quant_var_name = ctx.new_quantified_var_name()
                quant_decl = self.viper_ast.LocalVarDecl(
                    quant_var_name, self.viper_ast.Int)
                quant = quant_decl.localVar()
                new_node = helpers.array_get(self.viper_ast, node, quant,
                                             type.element_type)
                trigger = self.viper_ast.Trigger([new_node])

                leq = self.viper_ast.LeCmp(self.viper_ast.IntLit(0), quant)
                le = self.viper_ast.LtCmp(quant,
                                          self.viper_ast.SeqLength(node))
                bounds = self.viper_ast.And(leq, le)

                sub_ret = construct(type.element_type, new_node)
                for r in sub_ret:
                    implies = self.viper_ast.Implies(bounds, r)
                    quantifier = self.viper_ast.Forall([quant_decl], [trigger],
                                                       implies)
                    ret.append(quantifier)
            elif isinstance(type, (ContractType, InterfaceType)):
                return construct(types.VYPER_ADDRESS, node)
            # If we encounter a struct type we simply add the necessary assumptions for
            # all struct members
            # Additionally, we add an assumption about the type tag
            elif isinstance(type, StructType):
                for member_name, member_type in type.member_types.items():
                    viper_type = self.translate(member_type, ctx)
                    get = helpers.struct_get(self.viper_ast, node, member_name,
                                             viper_type, type)
                    ret.extend(construct(member_type, get))

                type_tag = self.viper_ast.IntLit(
                    mangled.struct_type_tag(type.name, type.kind))
                get_tag = helpers.struct_type_tag(self.viper_ast, node)
                ret.append(self.viper_ast.EqCmp(get_tag, type_tag))

            return ret