Exemple #1
0
        //Function to produce memory allocation as boogie reference types using "alloc"
        private void GenerateGlobalProcedureAllocMany()
        {
            // generate the internal one without base constructors
            string procName = "HavocAllocMany";
            List <BoogieVariable>  inParams   = new List <BoogieVariable>();
            List <BoogieVariable>  outParams  = new List <BoogieVariable>();
            List <BoogieAttribute> attributes = new List <BoogieAttribute>();

            if (Flags_HelperClass.GenerateInlineAttributes)
            {
                attributes.Add(new BoogieAttribute("inline", 1));
            }
            ;
            BoogieProcedure procedure = new BoogieProcedure(procName, inParams, outParams, attributes);

            context.getProgram.AddBoogieDeclaration(procedure);

            var oldAlloc = new BoogieLocalVariable(new BoogieTypedIdent("oldAlloc", new BoogieMapType(BoogieType.Ref, BoogieType.Bool)));
            List <BoogieVariable> localVars = new List <BoogieVariable>()
            {
                oldAlloc
            };

            BoogieStmtList       procBody          = new BoogieStmtList();
            BoogieIdentifierExpr oldAllocIdentExpr = new BoogieIdentifierExpr("oldAlloc");
            BoogieIdentifierExpr allocIdentExpr    = new BoogieIdentifierExpr("Alloc");

            // oldAlloc = Alloc
            procBody.AddStatement(new BoogieAssignCmd(oldAllocIdentExpr, allocIdentExpr));
            // havoc Alloc
            procBody.AddStatement(new BoogieHavocCmd(allocIdentExpr));


            var             qVar              = QVarGenerator.NewQVar(0, 0);
            BoogieMapSelect allocMapSelect    = new BoogieMapSelect(allocIdentExpr, qVar);
            BoogieMapSelect oldAllocMapSelect = new BoogieMapSelect(oldAllocIdentExpr, qVar);
            BoogieExpr      allocAssumeExpr   = new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.IMP, oldAllocMapSelect, allocMapSelect);

            procBody.AddStatement(new BoogieAssumeCmd(new BoogieQuantifiedExpr(true, new List <BoogieIdentifierExpr>()
            {
                qVar
            }, new List <BoogieType>()
            {
                BoogieType.Ref
            }, allocAssumeExpr)));

            BoogieImplementation implementation = new BoogieImplementation(procName, inParams, outParams, localVars, procBody);

            context.getProgram.AddBoogieDeclaration(implementation);
        }
Exemple #2
0
        private BoogieStmtList GenerateHavocBlock(ContractDefinition contract, List <BoogieVariable> localVars)
        {
            BoogieStmtList stmtList = new BoogieStmtList();

            foreach (BoogieVariable localVar in localVars)
            {
                string varName = localVar.TypedIdent.Name;
                if (!varName.Equals("this"))
                {
                    stmtList.AddStatement(new BoogieHavocCmd(new BoogieIdentifierExpr(varName)));
                }
            }
            return(stmtList);
        }
Exemple #3
0
        private BoogieStmtList HavocLocals(List <BoogieVariable> locals)
        {
            BoogieStmtList stmtList = new BoogieStmtList();

            foreach (BoogieVariable localVar in locals)
            {
                string varName = localVar.TypedIdent.Name;
                if (!varName.Equals("this"))
                {
                    stmtList.AddStatement(new BoogieHavocCmd(new BoogieIdentifierExpr(varName)));
                }
            }

            return(stmtList);
        }
Exemple #4
0
        private BoogieWhileCmd GenerateCorralWhileLoop(ContractDefinition contract)
        {
            BoogieStmtList body = new BoogieStmtList();

            body.AddStatement(GenerateCorralCall(contract));

            List <BoogiePredicateCmd> candidateInvs = new List <BoogiePredicateCmd>();

            // add the contract invariant if present
            if (contractInvariants.ContainsKey(contract.Name))
            {
                contractInvariants[contract.Name].ForEach(x => candidateInvs.Add(new BoogieLoopInvCmd(x)));
            }

            return(new BoogieWhileCmd(new BoogieLiteralExpr(true), body, candidateInvs));
        }
Exemple #5
0
        //Generate Fresh Procedure Boogie Type and add as new reference to BoogieProgram
        private void BuildGlobalProcedureFresh()
        {
            // generate the internal one without base constructors
            string procName = "FreshRefGenerator";
            List <BoogieVariable> inParams = new List <BoogieVariable>();

            var outVar = new BoogieFormalParam(new BoogieTypedIdent("newRef", BoogieType.Ref));
            List <BoogieVariable> outParams = new List <BoogieVariable>()
            {
                outVar
            };
            List <BoogieAttribute> attributes = new List <BoogieAttribute>();

            if (Flags_HelperClass.GenerateInlineAttributes)
            {
                attributes.Add(new BoogieAttribute("inline", 1));
            }
            ;
            BoogieProcedure procedure = new BoogieProcedure(procName, inParams, outParams, attributes);

            context.getProgram.AddBoogieDeclaration(procedure);

            List <BoogieVariable> localVars = new List <BoogieVariable>();
            BoogieStmtList        procBody  = new BoogieStmtList();

            var outVarIdentifier = new BoogieIdentifierExpr("newRef");
            BoogieIdentifierExpr allocIdentExpr = new BoogieIdentifierExpr("Alloc");

            // havoc tmp;
            procBody.AddStatement(new BoogieHavocCmd(outVarIdentifier));
            // assume Alloc[tmp] == false;
            BoogieMapSelect allocMapSelect  = new BoogieMapSelect(allocIdentExpr, outVarIdentifier);
            BoogieExpr      allocAssumeExpr = new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.EQ, allocMapSelect, new BoogieLiteralExpr(false));

            procBody.AddStatement(new BoogieAssumeCmd(allocAssumeExpr));
            // Alloc[tmp] := true;
            procBody.AddStatement(new BoogieAssignCmd(allocMapSelect, new BoogieLiteralExpr(true)));
            // assume tmp != null
            procBody.AddStatement(new BoogieAssumeCmd(
                                      new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.NEQ, outVarIdentifier, new BoogieIdentifierExpr("null"))));

            BoogieImplementation implementation = new BoogieImplementation(procName, inParams, outParams, localVars, procBody);

            context.getProgram.AddBoogieDeclaration(implementation);
        }
Exemple #6
0
        private void GenerateStructConstructors(ContractDefinition contract, StructDefinition structDefn)
        {
            // generate the internal one without base constructors
            string procName = structDefn.CanonicalName + "_ctor";
            List <BoogieVariable> inParams = new List <BoogieVariable>();

            inParams.AddRange(TransUtils.GetDefaultInParams());
            foreach (var member in structDefn.Members)
            {
                Debug.Assert(!member.TypeDescriptions.IsStruct(), "Do no handle nested structs yet!");
                var formalType = TransUtils.GetBoogieTypeFromSolidityTypeName(member.TypeName);
                var formalName = member.Name;
                inParams.Add(new BoogieFormalParam(new BoogieTypedIdent(formalName, formalType)));
            }

            List <BoogieVariable>  outParams  = new List <BoogieVariable>();
            List <BoogieAttribute> attributes = new List <BoogieAttribute>();

            if (context.TranslateFlags.GenerateInlineAttributes)
            {
                attributes.Add(new BoogieAttribute("inline", 1));
            }
            ;
            BoogieProcedure procedure = new BoogieProcedure(procName, inParams, outParams, attributes);

            context.Program.AddDeclaration(procedure);

            List <BoogieVariable> localVars = new List <BoogieVariable>();
            BoogieStmtList        procBody  = new BoogieStmtList();

            foreach (var member in structDefn.Members)
            {
                //f[this] = f_arg
                Debug.Assert(!member.TypeDescriptions.IsStruct(), "Do no handle nested structs yet!");
                var mapName       = member.Name + "_" + structDefn.CanonicalName;
                var formalName    = member.Name;
                var mapSelectExpr = new BoogieMapSelect(new BoogieIdentifierExpr(mapName), new BoogieIdentifierExpr("this"));
                procBody.AddStatement(new BoogieAssignCmd(mapSelectExpr, new BoogieIdentifierExpr(member.Name)));
            }

            BoogieImplementation implementation = new BoogieImplementation(procName, inParams, outParams, localVars, procBody);

            context.Program.AddDeclaration(implementation);
        }
Exemple #7
0
        private BoogieStmtList GenerateHavocBlock(ContractDefinition contract, List <BoogieVariable> localVars)
        {
            BoogieStmtList stmtList = new BoogieStmtList();

            foreach (BoogieVariable localVar in localVars)
            {
                string varName = localVar.TypedIdent.Name;
                if (!varName.Equals("this"))
                {
                    stmtList.AddStatement(new BoogieHavocCmd(new BoogieIdentifierExpr(varName)));
                }
            }

            if (context.TranslateFlags.InstrumentGas)
            {
                TransUtils.havocGas(stmtList);
            }

            var nowVar    = new BoogieIdentifierExpr("now");
            var tmpNowVar = new BoogieIdentifierExpr("tmpNow");

            stmtList.AddStatement(new BoogieAssignCmd(tmpNowVar, nowVar));
            stmtList.AddStatement(new BoogieHavocCmd(nowVar));
            stmtList.AddStatement(new BoogieAssumeCmd(new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.GT, nowVar, tmpNowVar)));
            stmtList.AddStatement(new BoogieAssumeCmd(new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.NEQ, new BoogieIdentifierExpr("msgsender_MSG"), new BoogieIdentifierExpr("null"))));

            if (context.TranslateFlags.NoTxnsFromContract)
            {
                foreach (var contractDef in context.ContractDefinitions)
                {
                    BoogieIdentifierExpr contractIdent = new BoogieIdentifierExpr(contractDef.Name);
                    stmtList.AddStatement(new BoogieAssumeCmd(new BoogieBinaryOperation(
                                                                  BoogieBinaryOperation.Opcode.NEQ,
                                                                  new BoogieMapSelect(new BoogieIdentifierExpr("DType"),
                                                                                      new BoogieIdentifierExpr("msgsender_MSG")),
                                                                  contractIdent)));
                }

                stmtList.AddStatement((new BoogieAssignCmd(new BoogieMapSelect(new BoogieIdentifierExpr("Alloc"), new BoogieIdentifierExpr("msgsender_MSG")), new BoogieLiteralExpr(true))));
            }

            return(stmtList);
        }
Exemple #8
0
        private void GenerateBoogieHarnessForContract(ContractDefinition contract, Dictionary <int, BoogieExpr> houdiniVarMap)
        {
            string harnessName              = "BoogieEntry_" + contract.Name;
            List <BoogieVariable> inParams  = new List <BoogieVariable>();
            List <BoogieVariable> outParams = new List <BoogieVariable>();
            BoogieProcedure       harness   = new BoogieProcedure(harnessName, inParams, outParams);

            context.Program.AddDeclaration(harness);

            List <BoogieVariable> localVars   = CollectLocalVars(contract);
            BoogieStmtList        harnessBody = new BoogieStmtList();

            harnessBody.AddStatement(GenerateDynamicTypeAssumes(contract));
            GenerateConstructorCall(contract).ForEach(x => harnessBody.AddStatement(x));
            harnessBody.AddStatement(GenerateWhileLoop(contract, houdiniVarMap, localVars));
            BoogieImplementation harnessImpl = new BoogieImplementation(harnessName, inParams, outParams, localVars, harnessBody);

            context.Program.AddDeclaration(harnessImpl);
        }
Exemple #9
0
        private void GenerateCorralChoiceProcForContract(ContractDefinition contract)
        {
            string procName = "CorralChoice_" + contract.Name;
            List <BoogieVariable> inParams = new List <BoogieVariable>()
            {
                new BoogieFormalParam(new BoogieTypedIdent("this", BoogieType.Ref)),
            };
            List <BoogieVariable> outParams = new List <BoogieVariable>();
            BoogieProcedure       harness   = new BoogieProcedure(procName, inParams, outParams);

            context.Program.AddDeclaration(harness);

            List <BoogieVariable> localVars = RemoveThisFromVariables(CollectLocalVars(contract));
            BoogieStmtList        procBody  = GenerateHavocBlock(contract, localVars);

            procBody.AddStatement(GenerateChoiceBlock(contract));
            BoogieImplementation procImpl = new BoogieImplementation(procName, inParams, outParams, localVars, procBody);

            context.Program.AddDeclaration(procImpl);
        }
Exemple #10
0
        private BoogieStmtList CreateBodyOfSend(List <BoogieVariable> inParams, List <BoogieVariable> outParams, string fbProcName)
        {
            var fromIdExp = new BoogieIdentifierExpr(inParams[0].Name);
            var amtIdExp  = new BoogieIdentifierExpr(inParams[2].Name);
            var guard     = new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.GE,
                                                      new BoogieMapSelect(new BoogieIdentifierExpr("Balance"), fromIdExp),
                                                      amtIdExp);

            // call FallbackDispatch(from, to, amount)
            var toIdExpr = new BoogieIdentifierExpr(inParams[1].Name);
            var callStmt = new BoogieCallCmd(
                fbProcName,
                new List <BoogieExpr>()
            {
                fromIdExp, toIdExpr, amtIdExp
            },
                new List <BoogieIdentifierExpr>()
                );

            var thenBody     = new BoogieStmtList();
            var successIdExp = new BoogieIdentifierExpr(outParams[0].Name);

            thenBody.AddStatement(new BoogieCommentCmd("---- Logic for payable function START "));
            var balFrom = new BoogieMapSelect(new BoogieIdentifierExpr("Balance"), new BoogieIdentifierExpr(inParams[0].Name));
            var balTo   = new BoogieMapSelect(new BoogieIdentifierExpr("Balance"), new BoogieIdentifierExpr(inParams[1].Name));
            var msgVal  = new BoogieIdentifierExpr(inParams[2].Name);

            //balance[msg.sender] = balance[msg.sender] - msg.value
            thenBody.AddStatement(new BoogieAssignCmd(balFrom, new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.SUB, balFrom, msgVal)));
            //balance[this] = balance[this] + msg.value
            thenBody.AddStatement(new BoogieAssignCmd(balTo, new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.ADD, balTo, msgVal)));
            thenBody.AddStatement(new BoogieCommentCmd("---- Logic for payable function END "));

            thenBody.AddStatement(callStmt);
            thenBody.AddStatement(new BoogieAssignCmd(successIdExp, new BoogieLiteralExpr(true)));

            var elseBody = new BoogieAssignCmd(successIdExp, new BoogieLiteralExpr(false));

            return(BoogieStmtList.MakeSingletonStmtList(new BoogieIfCmd(guard, thenBody,
                                                                        BoogieStmtList.MakeSingletonStmtList(elseBody))));
        }
Exemple #11
0
        private BoogieWhileCmd GenerateCorralWhileLoop(ContractDefinition contract)
        {
            BoogieStmtList    body   = new BoogieStmtList();
            string            callee = "CorralChoice_" + contract.Name;
            List <BoogieExpr> inputs = new List <BoogieExpr>()
            {
                new BoogieIdentifierExpr("this"),
            };

            body.AddStatement(new BoogieCallCmd(callee, inputs, null));

            List <BoogiePredicateCmd> candidateInvs = new List <BoogiePredicateCmd>();

            // add the contract invariant if present
            if (contractInvariants.ContainsKey(contract.Name))
            {
                contractInvariants[contract.Name].ForEach(x => candidateInvs.Add(new BoogieLoopInvCmd(x)));
            }

            return(new BoogieWhileCmd(new BoogieLiteralExpr(true), body, candidateInvs));
        }
Exemple #12
0
        private void GenerateCorralHarnessForContract(ContractDefinition contract)
        {
            string harnessName              = "CorralEntry_" + contract.Name;
            List <BoogieVariable> inParams  = new List <BoogieVariable>();
            List <BoogieVariable> outParams = new List <BoogieVariable>();
            BoogieProcedure       harness   = new BoogieProcedure(harnessName, inParams, outParams);

            context.Program.AddDeclaration(harness);

            List <BoogieVariable> localVars = new List <BoogieVariable>
            {
                new BoogieLocalVariable(new BoogieTypedIdent("this", BoogieType.Ref)),
                new BoogieLocalVariable(new BoogieTypedIdent("msgsender_MSG", BoogieType.Ref)),
                new BoogieLocalVariable(new BoogieTypedIdent("msgvalue_MSG", BoogieType.Int)),
            };

            if (context.IsConstructorDefined(contract))
            {
                FunctionDefinition ctor = context.GetConstructorByContract(contract);
                localVars.AddRange(GetParamsOfFunction(ctor));
            }
            BoogieStmtList harnessBody = new BoogieStmtList();

            harnessBody.AddStatement(GenerateDynamicTypeAssumes(contract));
            GenerateConstructorCall(contract).ForEach(x => harnessBody.AddStatement(x));
            if (context.TranslateFlags.ModelReverts)
            {
                BoogieExpr assumePred = new BoogieUnaryOperation(BoogieUnaryOperation.Opcode.NOT, new BoogieIdentifierExpr("revert"));
                if (context.TranslateFlags.InstrumentGas)
                {
                    assumePred = new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.AND, assumePred, new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.GE, new BoogieIdentifierExpr("gas"), new BoogieLiteralExpr(0)));
                }

                harnessBody.AddStatement(new BoogieAssumeCmd(assumePred));
            }
            harnessBody.AddStatement(GenerateCorralWhileLoop(contract));
            BoogieImplementation harnessImpl = new BoogieImplementation(harnessName, inParams, outParams, localVars, harnessBody);

            context.Program.AddDeclaration(harnessImpl);
        }
Exemple #13
0
        private BoogieWhileCmd GenerateWhileLoop(ContractDefinition contract, Dictionary <int, BoogieExpr> houdiniVarMap, List <BoogieVariable> localVars)
        {
            // havoc all local variables except `this'
            BoogieStmtList body = GenerateHavocBlock(contract, localVars);

            // generate the choice block
            body.AddStatement(GenerateChoiceBlock(contract));

            // generate candidate invariants for Houdini
            List <BoogiePredicateCmd> candidateInvs = new List <BoogiePredicateCmd>();

            foreach (int id in houdiniVarMap.Keys)
            {
                BoogieIdentifierExpr houdiniVar   = new BoogieIdentifierExpr(GetHoudiniVarName(id, contract));
                BoogieExpr           candidateInv = houdiniVarMap[id];
                BoogieExpr           invExpr      = new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.IMP, houdiniVar, candidateInv);
                BoogieLoopInvCmd     invCmd       = new BoogieLoopInvCmd(invExpr);
                candidateInvs.Add(invCmd);
            }

            return(new BoogieWhileCmd(new BoogieLiteralExpr(true), body, candidateInvs));
        }
Exemple #14
0
        public static BoogieStmtList constrainVarValues(TranslatorContext context, VariableDeclaration var, BoogieIdentifierExpr boogieVar)
        {
            BoogieStmtList stmts = new BoogieStmtList();

            if (context.TranslateFlags.UseModularArithmetic)
            {
                if (var.TypeDescriptions.IsUintWSize(null, out uint uintSize))
                {
                    BigInteger            maxUIntValue = (BigInteger)Math.Pow(2, uintSize);
                    BoogieBinaryOperation lower        = new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.GE, boogieVar, new BoogieLiteralExpr(BigInteger.Zero));
                    BoogieBinaryOperation upper        = new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.LT, boogieVar, new BoogieLiteralExpr(maxUIntValue));
                    stmts.AddStatement(new BoogieAssumeCmd(new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.AND, lower, upper)));
                }
                else if (var.TypeDescriptions.IsIntWSize(out uint intSize))
                {
                    BigInteger            maxIntValue = (BigInteger)Math.Pow(2, intSize);
                    BoogieBinaryOperation lower       = new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.GE, boogieVar, new BoogieLiteralExpr(-maxIntValue));
                    BoogieBinaryOperation upper       = new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.LT, boogieVar, new BoogieLiteralExpr(maxIntValue));
                    stmts.AddStatement(new BoogieAssumeCmd(new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.AND, lower, upper)));
                }
            }

            return(stmts);
        }
Exemple #15
0
        public void Generate()
        {
            // Collect Global Variables.
            HashSet <BoogieGlobalVariable> globals = new HashSet <BoogieGlobalVariable>();

            foreach (var decl in context.Program.Declarations)
            {
                if (decl is BoogieGlobalVariable)
                {
                    var g = (BoogieGlobalVariable)decl;

                    if (mustHaveShadow(g.Name))
                    {
                        globals.Add(g);
                    }
                }
            }

            // Generate shadow state.
            foreach (var g in globals)
            {
                var varName = g.TypedIdent.Name;
                BoogieTypedIdent     shadowGlobal     = new BoogieTypedIdent("__tmp__" + varName, g.TypedIdent.Type);
                BoogieGlobalVariable shadowGlobalDecl = new BoogieGlobalVariable(shadowGlobal);

                context.Program.AddDeclaration(shadowGlobalDecl);
                shadowGlobals.Add(varName, shadowGlobalDecl);
            }

            // Duplicate and rename methods.
            Dictionary <string, BoogieImplementation> proceduresWithImpl = new Dictionary <string, BoogieImplementation>();

            procsWiltImplNames = proceduresWithImpl.Keys;
            foreach (var decl in context.Program.Declarations)
            {
                if (decl is BoogieImplementation)
                {
                    var boogieImpl = ((BoogieImplementation)decl);
                    if (proceduresInProgram.ContainsKey(boogieImpl.Name))
                    {
                        proceduresWithImpl.Add(boogieImpl.Name, boogieImpl);
                    }
                }
            }

            Dictionary <string, BoogieProcedure> failProcedures = new Dictionary <string, BoogieProcedure>();

            foreach (var implPair in proceduresWithImpl)
            {
                BoogieProcedure proc = proceduresInProgram[implPair.Key];

                if (isPublic(proc) || isConstructor(proc.Name))
                {
                    // If public maintain original definition as the wrapper.
                    BoogieProcedure successVersion = duplicateProcedure(proc, "success", true);
                    //BoogieImplementation successImpl = duplicateImplementation(implPair.Value, "success");

                    context.Program.AddDeclaration(successVersion);
                    //context.Program.AddDeclaration(successImpl);

                    BoogieProcedure failVersion = duplicateProcedure(proc, "fail", true);

                    context.Program.AddDeclaration(failVersion);

                    // Use original name of the procedure.
                    failProcedures.Add(implPair.Key, failVersion);
                }
                else if (!isHarnessProcudure(proc.Name))
                {
                    // Otherwise reuse original definition/impl as the "successful" method.
                    BoogieProcedure failVersion = duplicateProcedure(proc, "fail");

                    context.Program.AddDeclaration(failVersion);

                    // Use original name of the procedure.
                    failProcedures.Add(implPair.Key, failVersion);

                    // Reuse original node
                    proc.Name           = proc.Name + "__success";
                    implPair.Value.Name = implPair.Value.Name + "__success";
                }
            }

            // Create implementations for failing methods.
            foreach (var failProcedurePair in failProcedures)
            {
                string          originalProcName = failProcedurePair.Key;
                BoogieProcedure proc             = failProcedurePair.Value;

                var originalImpl = proceduresWithImpl[originalProcName];
                context.Program.AddDeclaration(createFailImplementation(proc.Name, originalImpl));
                context.Program.AddDeclaration(createSuccessImplementation(originalProcName + "__success", originalImpl));

                // Remove original implementation for non-public methods
                if (!isPublic(proceduresInProgram[originalProcName]) && !isConstructor(originalProcName))
                {
                    context.Program.Declarations.Remove(originalImpl);
                }
            }

            foreach (var implPair in proceduresWithImpl)
            {
                // Update non-public methods in harness methods
                if (isHarnessProcudure(implPair.Key))
                {
                    context.Program.AddDeclaration(createSuccessImplementation(implPair.Key, implPair.Value));

                    context.Program.Declarations.Remove(implPair.Value);
                }
            }

            // Create wrappers for public methods.

            foreach (var proc in proceduresInProgram.Values)
            {
                if (proceduresWithImpl.ContainsKey(proc.Name) && (isPublic(proc) || isConstructor(proc.Name)))
                {
                    BoogieImplementation impl = proceduresWithImpl[proc.Name];
                    impl.StructuredStmts = new BoogieStmtList();
                    impl.LocalVars       = new List <BoogieVariable>();

                    var exceptionVarName = "__exception";
                    var revertGlobalName = "revert";
                    impl.LocalVars.Add(new BoogieLocalVariable(new BoogieTypedIdent(exceptionVarName, BoogieType.Bool)));

                    var stmtList = impl.StructuredStmts;
                    stmtList.AddStatement(new BoogieHavocCmd(new BoogieIdentifierExpr(exceptionVarName)));
                    stmtList.AddStatement(new BoogieAssignCmd(new BoogieIdentifierExpr(revertGlobalName), new BoogieLiteralExpr(false)));

                    // Call Successful version.
                    BoogieStmtList successCallStmtList = new BoogieStmtList();
                    successCallStmtList.AddStatement(new BoogieCallCmd(impl.Name + "__success",
                                                                       impl.InParams.Select(inParam => (BoogieExpr) new BoogieIdentifierExpr(inParam.Name)).ToList(),
                                                                       impl.OutParams.Select(outParam => new BoogieIdentifierExpr(outParam.Name)).ToList()));
                    successCallStmtList.AddStatement(new BoogieAssumeCmd(new BoogieUnaryOperation(BoogieUnaryOperation.Opcode.NOT, new BoogieIdentifierExpr(revertGlobalName))));

                    // Call fail version.
                    BoogieStmtList failCallStmtList = new BoogieStmtList();
                    // Write global variables to temps
                    foreach (var shadowGlobalPair in shadowGlobals)
                    {
                        string origVarName = shadowGlobalPair.Key;
                        string shadowName  = shadowGlobalPair.Value.Name;
                        failCallStmtList.AddStatement(new BoogieAssignCmd(new BoogieIdentifierExpr(shadowName), new BoogieIdentifierExpr(origVarName)));
                    }
                    failCallStmtList.AddStatement(new BoogieCallCmd(impl.Name + "__fail",
                                                                    impl.InParams.Select(inParam => (BoogieExpr) new BoogieIdentifierExpr(inParam.Name)).ToList(),
                                                                    impl.OutParams.Select(outParam => new BoogieIdentifierExpr(outParam.Name)).ToList()));
                    failCallStmtList.AddStatement(new BoogieAssumeCmd(new BoogieIdentifierExpr(revertGlobalName)));

                    stmtList.AddStatement(new BoogieIfCmd(new BoogieIdentifierExpr(exceptionVarName), failCallStmtList, successCallStmtList));
                }
            }
        }
        private BoogieStmtList GenerateBody(List <BoogieVariable> inParams)
        {
            //
            // foreach contract C that is not Lib/VeriSol
            //    if (DT[this] == C)
            //       if C has a fallback f
            //            call ret := fallBack_C(this=to, sender=from, msg.value)
            //       else
            //            assume msg.value == 0;
            // else
            //     call fallBack_unknownType(from, to, msg.value)
            BoogieIfCmd ifCmd = null;

            Debug.Assert(context.ContractDefinitions.Count >= 1, "There should be at least one contract");

            List <BoogieExpr> arguments = new List <BoogieExpr>()
            {
                new BoogieIdentifierExpr(inParams[1].Name),
                new BoogieIdentifierExpr(inParams[0].Name),
                new BoogieIdentifierExpr(inParams[2].Name)
            };
            List <BoogieIdentifierExpr> outParams = new List <BoogieIdentifierExpr>();

            BoogieStmtList noMatchCase = BoogieStmtList.MakeSingletonStmtList(
                new BoogieCallCmd("Fallback_UnknownType", arguments, outParams));

            foreach (var contract in context.ContractDefinitions)
            {
                if (contract.ContractKind == EnumContractKind.LIBRARY)
                {
                    continue;
                }


                FunctionDefinition function = context.ContractToFallbackMap.ContainsKey(contract) ?
                                              context.ContractToFallbackMap[contract] : null;
                BoogieExpr lhs   = new BoogieMapSelect(new BoogieIdentifierExpr("DType"), new BoogieIdentifierExpr(inParams[1].Name));
                BoogieExpr rhs   = new BoogieIdentifierExpr(contract.Name);
                BoogieExpr guard = new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.EQ, lhs, rhs);


                BoogieStmtList thenBody = null;

                if (function != null)
                {
                    string callee = TransUtils.GetCanonicalFunctionName(function, context);
                    thenBody = BoogieStmtList.MakeSingletonStmtList(new BoogieCallCmd(callee, arguments, outParams));
                }
                else
                {
                    // No fallback means not payable (amount == 0)
                    thenBody = BoogieStmtList.MakeSingletonStmtList(
                        new BoogieAssumeCmd(
                            new BoogieBinaryOperation(
                                BoogieBinaryOperation.Opcode.EQ,
                                new BoogieIdentifierExpr(inParams[2].Name),
                                new BoogieLiteralExpr(BigInteger.Zero)))
                        );
                }

                BoogieStmtList elseBody = ifCmd == null ? noMatchCase : BoogieStmtList.MakeSingletonStmtList(ifCmd);

                ifCmd = new BoogieIfCmd(guard, thenBody, elseBody);
            }


            return(BoogieStmtList.MakeSingletonStmtList(ifCmd));
        }
Exemple #17
0
        private void generateRevertLogicForCmd(BoogieCmd cmd, BoogieStmtList parent, bool isFail, bool inHarness)
        {
            List <BoogieExpr> dupAndReplaceExprList(List <BoogieExpr> exprs)
            {
                return(exprs.Select(e => dupAndReplaceExpr(e, isFail, inHarness)).ToList());
            }

            BoogieStmtList dupAndReplaceStmList(BoogieStmtList stmtList)
            {
                if (stmtList == null)
                {
                    return(null);
                }

                BoogieStmtList newList = new BoogieStmtList();

                stmtList.BigBlocks[0].SimpleCmds.ForEach(c => generateRevertLogicForCmd(c, newList, isFail, inHarness));
                return(newList);
            }

            if (cmd is BoogieAssignCmd assignCmd)
            {
                parent.AddStatement(new BoogieAssignCmd(dupAndReplaceExpr(assignCmd.Lhs, isFail, inHarness),
                                                        dupAndReplaceExpr(assignCmd.Rhs, isFail, inHarness)));
            }
            else if (cmd is BoogieCallCmd callCmd)
            {
                string calleeName           = callCmd.Callee;
                bool   emitCheckRevertLogic = false;
                if (!isHarnessProcudure(calleeName) && procsWiltImplNames.Contains(calleeName))
                {
                    if (!inHarness || !isPublic(proceduresInProgram[calleeName]))
                    {
                        calleeName           = calleeName + (isFail ? "__fail" : "__success");
                        emitCheckRevertLogic = !inHarness;
                    }
                }

                var newIns = callCmd.Ins != null?dupAndReplaceExprList(callCmd.Ins) : null;

                var newOuts = callCmd.Outs != null?callCmd.Outs.Select(e => (BoogieIdentifierExpr)dupAndReplaceExpr(e, isFail, inHarness)).ToList() : null;

                parent.AddStatement(new BoogieCallCmd(calleeName, newIns, newOuts));

                if (emitCheckRevertLogic)
                {
                    BoogieStmtList thenBody = new BoogieStmtList();
                    thenBody.AddStatement(new BoogieReturnCmd());

                    parent.AddStatement(new BoogieIfCmd(new BoogieIdentifierExpr("revert"), thenBody, null));
                }
            }
            else if (cmd is BoogieAssertCmd assertCmd)
            {
                if (!isFail)
                {
                    parent.AddStatement(new BoogieAssertCmd(dupAndReplaceExpr(assertCmd.Expr, false, inHarness), assertCmd.Attributes));
                }
            }
            else if (cmd is BoogieAssumeCmd assumeCmd)
            {
                parent.AddStatement(new BoogieAssumeCmd(dupAndReplaceExpr(assumeCmd.Expr, isFail, inHarness)));
            }
            else if (cmd is BoogieLoopInvCmd loopInvCmd)
            {
                parent.AddStatement(new BoogieLoopInvCmd(dupAndReplaceExpr(loopInvCmd.Expr, isFail, inHarness)));
            }
            else if (cmd is BoogieReturnExprCmd returnExprCmd)
            {
                // This one does not seem to be used.
                parent.AddStatement(new BoogieReturnExprCmd(dupAndReplaceExpr(returnExprCmd.Expr, isFail, inHarness)));
            }
            else if (cmd is BoogieHavocCmd havocCmd)
            {
                parent.AddStatement(new BoogieHavocCmd(havocCmd.Vars.Select(id => (BoogieIdentifierExpr)dupAndReplaceExpr(id, isFail, inHarness)).ToList()));
            }
            else if (cmd is BoogieIfCmd ifCmd)
            {
                parent.AddStatement(new BoogieIfCmd(dupAndReplaceExpr(ifCmd.Guard, isFail, inHarness),
                                                    dupAndReplaceStmList(ifCmd.ThenBody),
                                                    dupAndReplaceStmList(ifCmd.ElseBody)));
            }
            else if (cmd is BoogieWhileCmd whileCmd)
            {
                var            body           = dupAndReplaceStmList(whileCmd.Body);
                BoogieStmtList invsAsStmtList = new BoogieStmtList();
                whileCmd.Invariants.ForEach(i => generateRevertLogicForCmd(i, invsAsStmtList, isFail, inHarness));
                List <BoogiePredicateCmd> invs = invsAsStmtList.BigBlocks[0].SimpleCmds.Select(c => (BoogiePredicateCmd)c).ToList();
                parent.AddStatement(new BoogieWhileCmd(dupAndReplaceExpr(whileCmd.Guard, isFail, inHarness), body, invs));
            }
            else
            {
                parent.AddStatement(cmd);
            }
        }
Exemple #18
0
        // generate a non-deterministic choice block to call every public visible functions except constructors
        private BoogieIfCmd GenerateChoiceBlock(ContractDefinition contract)
        {
            HashSet <FunctionDefinition> funcDefs       = context.GetVisibleFunctionsByContract(contract);
            List <FunctionDefinition>    publicFuncDefs = new List <FunctionDefinition>();

            foreach (FunctionDefinition funcDef in funcDefs)
            {
                if (funcDef.IsConstructorForContract(contract.Name))
                {
                    continue;
                }
                if (funcDef.Visibility == EnumVisibility.PUBLIC || funcDef.Visibility == EnumVisibility.EXTERNAL)
                {
                    publicFuncDefs.Add(funcDef);
                }
            }
            BoogieIfCmd ifCmd = null;

            for (int i = publicFuncDefs.Count - 1; i >= 0; --i)
            {
                BoogieExpr guard = new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.EQ,
                                                             new BoogieIdentifierExpr("choice"),
                                                             new BoogieLiteralExpr(i + 1));

                BoogieStmtList thenBody = new BoogieStmtList();

                FunctionDefinition funcDef = publicFuncDefs[i];
                string             callee  = TransUtils.GetCanonicalFunctionName(funcDef, context);
                List <BoogieExpr>  inputs  = new List <BoogieExpr>()
                {
                    new BoogieIdentifierExpr("this"),
                    new BoogieIdentifierExpr("msgsender_MSG"),
                    new BoogieIdentifierExpr("msgvalue_MSG"),
                };
                foreach (VariableDeclaration param in funcDef.Parameters.Parameters)
                {
                    string name = TransUtils.GetCanonicalLocalVariableName(param);
                    inputs.Add(new BoogieIdentifierExpr(name));
                    if (param.TypeName is ArrayTypeName array)
                    {
                        thenBody.AddStatement(new BoogieCallCmd(
                                                  "FreshRefGenerator",
                                                  new List <BoogieExpr>(), new List <BoogieIdentifierExpr>()
                        {
                            new BoogieIdentifierExpr(name)
                        }));
                    }
                }

                List <BoogieIdentifierExpr> outputs = new List <BoogieIdentifierExpr>();
                var retParamCount = 0;

                foreach (VariableDeclaration param in funcDef.ReturnParameters.Parameters)
                {
                    //string name = "__ret" + funcDef.Name;
                    string name = $"__ret_{retParamCount++}_" + funcDef.Name;

                    if (!string.IsNullOrEmpty(param.Name))
                    {
                        name = TransUtils.GetCanonicalLocalVariableName(param);
                    }
                    outputs.Add(new BoogieIdentifierExpr(name));
                }

                BoogieCallCmd callCmd = new BoogieCallCmd(callee, inputs, outputs);
                thenBody.AddStatement(callCmd);

                BoogieStmtList elseBody = ifCmd == null ? null : BoogieStmtList.MakeSingletonStmtList(ifCmd);
                ifCmd = new BoogieIfCmd(guard, thenBody, elseBody);
            }
            return(ifCmd);
        }
Exemple #19
0
        private void GenerateCorralHarnessForContract(ContractDefinition contract)
        {
            string harnessName = "CorralEntry_" + contract.Name;

            if (context.TranslateFlags.CreateMainHarness && contract.Name.Equals(context.EntryPointContract))
            {
                harnessName = "main";
            }

            List <BoogieVariable> inParams  = new List <BoogieVariable>();
            List <BoogieVariable> outParams = new List <BoogieVariable>();
            BoogieProcedure       harness   = new BoogieProcedure(harnessName, inParams, outParams);

            context.Program.AddDeclaration(harness);

            List <BoogieVariable> localVars = new List <BoogieVariable>
            {
                new BoogieLocalVariable(new BoogieTypedIdent("this", BoogieType.Ref)),
                new BoogieLocalVariable(new BoogieTypedIdent("msgsender_MSG", BoogieType.Ref)),
                new BoogieLocalVariable(new BoogieTypedIdent("msgvalue_MSG", BoogieType.Int)),
            };

            if (context.IsConstructorDefined(contract))
            {
                FunctionDefinition ctor = context.GetConstructorByContract(contract);
                localVars.AddRange(GetParamsOfFunction(ctor));
            }
            BoogieStmtList harnessBody = new BoogieStmtList();

            //harnessBody.AddStatement(new BoogieAssignCmd(new BoogieIdentifierExpr("this"), ));
            if (context.TranslateFlags.NoCustomTypes)
            {
                harnessBody.AddStatement((new BoogieAssumeCmd(new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.EQ, new BoogieIdentifierExpr("null"), new BoogieLiteralExpr(0)))));
            }
            harnessBody.AddStatement(new BoogieCallCmd("FreshRefGenerator", new List <BoogieExpr>(), new List <BoogieIdentifierExpr>()
            {
                new BoogieIdentifierExpr("this")
            }));
            harnessBody.AddStatement(new BoogieAssumeCmd(new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.GE, new BoogieIdentifierExpr("now"), new BoogieLiteralExpr(0))));
            harnessBody.AddStatement(GenerateDynamicTypeAssumes(contract));
            if (!context.TranslateFlags.PrePostHarness)
            {
                GenerateConstructorCall(contract).ForEach(x => harnessBody.AddStatement(x));
            }

            if (context.TranslateFlags.ModelReverts)
            {
                BoogieExpr assumePred = new BoogieUnaryOperation(BoogieUnaryOperation.Opcode.NOT, new BoogieIdentifierExpr("revert"));
                if (context.TranslateFlags.InstrumentGas)
                {
                    assumePred = new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.AND, assumePred, new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.GE, new BoogieIdentifierExpr("gas"), new BoogieLiteralExpr(0)));
                }

                harnessBody.AddStatement(new BoogieAssumeCmd(assumePred));
            }

            if (context.TranslateFlags.PrePostHarness)
            {
                harnessBody.AddStatement(GenerateCorralCall(contract));
                BoogieStmtList body = new BoogieStmtList();
                harnessBody.AddStatement(new BoogieWhileCmd(new BoogieLiteralExpr(true), body));
            }
            else
            {
                harnessBody.AddStatement(GenerateCorralWhileLoop(contract));
            }

            BoogieImplementation harnessImpl = new BoogieImplementation(harnessName, inParams, outParams, localVars, harnessBody);

            context.Program.AddDeclaration(harnessImpl);
        }
        private BoogieImplementation CreateSendFail()
        {
            // send__fail(from: Ref, to: Ref, amt: uint) returns (success: boolean)
            // {
            //    var __exception: bool;
            //    havoc __exception;
            //
            //    if(__exception)
            //    {
            //       //save current temps
            //      if ((__tmp__Balance[from]) >= (amt)) {
            //           call FallbackDispatch__fail(from, to, amt);
            //      }
            //
            //       success := false;
            //       assume(__revert);
            //
            //       // restore old temps
            //       revert := false;
            //    }
            //    else {
            //       if ((__tmp__Balance[from]) >= (amt)) {
            //           call FallbackDispatch__fail(from, to, amt);
            //           success := true;
            //       } else {
            //           success := false;
            //       }
            //
            //       assume(!(__revert));
            //    }
            // }

            List <BoogieVariable> inParams = new List <BoogieVariable>()
            {
                new BoogieFormalParam(new BoogieTypedIdent("from", BoogieType.Ref)),
                new BoogieFormalParam(new BoogieTypedIdent("to", BoogieType.Ref)),
                new BoogieFormalParam(new BoogieTypedIdent("amount", BoogieType.Int))
            };

            List <BoogieVariable> outParms = new List <BoogieVariable>()
            {
                new BoogieFormalParam(new BoogieTypedIdent("success", BoogieType.Bool))
            };

            List <BoogieVariable> locals = new List <BoogieVariable>()
            {
                new BoogieLocalVariable(new BoogieTypedIdent("__exception", BoogieType.Bool))
            };

            var fromId = new BoogieIdentifierExpr("from");
            var toId   = new BoogieIdentifierExpr("to");
            var amtId  = new BoogieIdentifierExpr("amount");

            var successId = new BoogieIdentifierExpr("success");

            var revertId = new BoogieIdentifierExpr("revert");

            var exceptionId = new BoogieIdentifierExpr("__exception");

            var body = new BoogieStmtList();

            body.AddStatement(new BoogieHavocCmd(exceptionId));

            var checkTmpBalGuard = new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.GE,
                                                             new BoogieMapSelect(new BoogieIdentifierExpr(shadowGlobals["Balance"].Name), fromId),
                                                             amtId);
            var callFailDispatch = new BoogieCallCmd("FallbackDispatch__fail", new List <BoogieExpr>()
            {
                fromId, toId, amtId
            }, null);

            var exceptionCase = new BoogieStmtList();

            foreach (var shadowGlobalPair in shadowGlobals)
            {
                var shadowName   = shadowGlobalPair.Value.Name;
                var tmpLocalName = "__snap_" + shadowName;
                locals.Add(new BoogieLocalVariable(new BoogieTypedIdent(tmpLocalName, shadowGlobalPair.Value.TypedIdent.Type)));

                exceptionCase.AddStatement(new BoogieAssignCmd(new BoogieIdentifierExpr(tmpLocalName), new BoogieIdentifierExpr(shadowName)));
            }

            BoogieStmtList exStmtList = new BoogieStmtList();

            exStmtList.AddStatement(new BoogieCommentCmd("---- Logic for payable function START "));
            var exBalFrom = new BoogieMapSelect(new BoogieIdentifierExpr(shadowGlobals["Balance"].Name), new BoogieIdentifierExpr(inParams[0].Name));
            var exBalTo   = new BoogieMapSelect(new BoogieIdentifierExpr(shadowGlobals["Balance"].Name), new BoogieIdentifierExpr(inParams[1].Name));
            var exMsgVal  = new BoogieIdentifierExpr(inParams[2].Name);

            //balance[msg.sender] = balance[msg.sender] - msg.value
            exStmtList.AddStatement(new BoogieAssignCmd(exBalFrom, new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.SUB, exBalFrom, exMsgVal)));
            //balance[this] = balance[this] + msg.value
            exStmtList.AddStatement(new BoogieAssignCmd(exBalTo, new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.ADD, exBalTo, exMsgVal)));
            exStmtList.AddStatement(new BoogieCommentCmd("---- Logic for payable function END "));
            exStmtList.AddStatement(callFailDispatch);

            exceptionCase.AddStatement(new BoogieIfCmd(checkTmpBalGuard, exStmtList, null));
            exceptionCase.AddStatement(new BoogieAssignCmd(successId, new BoogieLiteralExpr(false)));
            BoogieExpr failAssumePred = revertId;

            if (context.TranslateFlags.InstrumentGas)
            {
                failAssumePred = new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.OR, failAssumePred, new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.LT, new BoogieIdentifierExpr("gas"), new BoogieLiteralExpr(0)));
            }

            exceptionCase.AddStatement(new BoogieAssumeCmd(failAssumePred));

            foreach (var shadowGlobalPair in shadowGlobals)
            {
                var shadowName   = shadowGlobalPair.Value.Name;
                var tmpLocalName = "__snap_" + shadowName;

                exceptionCase.AddStatement(new BoogieAssignCmd(new BoogieIdentifierExpr(shadowName), new BoogieIdentifierExpr(tmpLocalName)));
            }

            exceptionCase.AddStatement(new BoogieAssignCmd(revertId, new BoogieLiteralExpr(false)));

            var successCase         = new BoogieStmtList();
            var successDispatchCall = new BoogieStmtList();

            successDispatchCall.AddStatement(new BoogieCommentCmd("---- Logic for payable function START "));
            //balance[msg.sender] = balance[msg.sender] - msg.value
            successDispatchCall.AddStatement(new BoogieAssignCmd(exBalFrom, new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.SUB, exBalFrom, exMsgVal)));
            //balance[this] = balance[this] + msg.value
            successDispatchCall.AddStatement(new BoogieAssignCmd(exBalTo, new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.ADD, exBalTo, exMsgVal)));
            successDispatchCall.AddStatement(new BoogieCommentCmd("---- Logic for payable function END "));
            successDispatchCall.AddStatement(callFailDispatch);
            successDispatchCall.AddStatement(new BoogieAssignCmd(successId, new BoogieLiteralExpr(true)));

            successCase.AddStatement(new BoogieIfCmd(checkTmpBalGuard, successDispatchCall, BoogieStmtList.MakeSingletonStmtList(new BoogieAssignCmd(successId, new BoogieLiteralExpr(false)))));
            BoogieExpr successAssumePred = new BoogieUnaryOperation(BoogieUnaryOperation.Opcode.NOT, revertId);

            if (context.TranslateFlags.InstrumentGas)
            {
                successAssumePred = new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.AND, successAssumePred, new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.GE, new BoogieIdentifierExpr("gas"), new BoogieLiteralExpr(0)));
            }

            successCase.AddStatement(new BoogieAssumeCmd(successAssumePred));

            body.AddStatement(new BoogieIfCmd(exceptionId, exceptionCase, successCase));
            return(new BoogieImplementation("send__fail", inParams, outParms, locals, body));
        }
Exemple #21
0
        private BoogieStmtList GenerateBodyOfFallbackDispatch(List <BoogieVariable> inParams, string fbUnknownProcName)
        {
            // Perform the payable logic to transfer balance
            //
            // Fallback(from, to, amount)
            //
            // foreach contract C that is not Lib/VeriSol
            //    if (DT[this] == C)
            //       if C has a fallback f
            //            call ret := fallBack_C(this=to, sender=from, msg.value)
            //       else
            //            assume msg.value == 0;
            // else
            //    if stubModel == callback
            //     call fallBack_unknownType(from, to, amout) //we switch the order of first two parameters to ease callbacks
            //    else if stubmodel == havoc
            //      havoc all global state, except local state of this contract
            //    else
            //      skip //default
            BoogieIfCmd ifCmd = null;

            Debug.Assert(context.ContractDefinitions.Count >= 1, "There should be at least one contract");

            List <BoogieIdentifierExpr> outParams = new List <BoogieIdentifierExpr>();

            List <BoogieExpr> unkwnFnArgs = new List <BoogieExpr>()
            {
                new BoogieIdentifierExpr(inParams[0].Name),
                new BoogieIdentifierExpr(inParams[1].Name),
                new BoogieIdentifierExpr(inParams[2].Name)
            };

            // fbUnknown(from, to, amount)
            BoogieStmtList noMatchCase = BoogieStmtList.MakeSingletonStmtList(
                new BoogieCallCmd(fbUnknownProcName, unkwnFnArgs, outParams));

            foreach (var contract in context.ContractDefinitions)
            {
                if (contract.ContractKind == EnumContractKind.LIBRARY)
                {
                    continue;
                }

                FunctionDefinition function = context.ContractToFallbackMap.ContainsKey(contract) ?
                                              context.ContractToFallbackMap[contract] : null;
                BoogieExpr lhs   = new BoogieMapSelect(new BoogieIdentifierExpr("DType"), new BoogieIdentifierExpr(inParams[1].Name));
                BoogieExpr rhs   = new BoogieIdentifierExpr(contract.Name);
                BoogieExpr guard = new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.EQ, lhs, rhs);


                BoogieStmtList thenBody = null;

                if (function != null)
                {
                    List <BoogieExpr> arguments = new List <BoogieExpr>()
                    {
                        new BoogieIdentifierExpr(inParams[1].Name),
                        new BoogieIdentifierExpr(inParams[0].Name),
                        new BoogieIdentifierExpr(inParams[2].Name)
                    };

                    string callee = TransUtils.GetCanonicalFunctionName(function, context);
                    // to.fallback(from, amount), thus need to switch param0 and param1
                    thenBody = BoogieStmtList.MakeSingletonStmtList(new BoogieCallCmd(callee, arguments, outParams));
                }
                else
                {
                    // No fallback means not payable (amount == 0)
                    thenBody = BoogieStmtList.MakeSingletonStmtList(
                        new BoogieAssumeCmd(
                            new BoogieBinaryOperation(
                                BoogieBinaryOperation.Opcode.EQ,
                                new BoogieIdentifierExpr(inParams[2].Name),
                                new BoogieLiteralExpr(BigInteger.Zero)))
                        );
                }

                BoogieStmtList elseBody = ifCmd == null ? noMatchCase : BoogieStmtList.MakeSingletonStmtList(ifCmd);

                ifCmd = new BoogieIfCmd(guard, thenBody, elseBody);
            }

            return(BoogieStmtList.MakeSingletonStmtList(ifCmd));
        }
Exemple #22
0
        /// <summary>
        /// generate a non-deterministic choice block to call every public visible functions except constructors
        ///
        /// </summary>
        /// <param name="contracts"></param>
        /// <param name="context"></param>
        /// <param name="callBackTarget">If non-null, this will be the msg.sender for calling back into the contracts</param>
        /// <returns></returns>
        public static BoogieIfCmd GenerateChoiceBlock(List <ContractDefinition> contracts, TranslatorContext context, Tuple <string, string> callBackTarget = null)
        {
            BoogieIfCmd ifCmd = null;
            int         j     = 0;

            foreach (var contract in contracts)
            {
                if (contract.ContractKind != EnumContractKind.CONTRACT)
                {
                    continue;
                }

                HashSet <FunctionDefinition> funcDefs       = context.GetVisibleFunctionsByContract(contract);
                List <FunctionDefinition>    publicFuncDefs = new List <FunctionDefinition>();
                foreach (FunctionDefinition funcDef in funcDefs)
                {
                    if (funcDef.IsConstructor)
                    {
                        continue;
                    }
                    if (funcDef.IsFallback)
                    {
                        continue;                     //let us not call fallback directly in harness
                    }
                    if (funcDef.Visibility == EnumVisibility.PUBLIC || funcDef.Visibility == EnumVisibility.EXTERNAL)
                    {
                        publicFuncDefs.Add(funcDef);
                    }
                }
                for (int i = publicFuncDefs.Count - 1; i >= 0; --i)
                {
                    j++;
                    BoogieExpr guard = new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.EQ,
                                                                 new BoogieIdentifierExpr("choice"),
                                                                 new BoogieLiteralExpr(j));

                    BoogieStmtList thenBody = new BoogieStmtList();

                    FunctionDefinition funcDef = publicFuncDefs[i];
                    string             callee  = TransUtils.GetCanonicalFunctionName(funcDef, context);
                    List <BoogieExpr>  inputs  = new List <BoogieExpr>()
                    {
                        // let us just call back into the calling contract
                        callBackTarget != null ? new BoogieIdentifierExpr(callBackTarget.Item1) : new BoogieIdentifierExpr("this"),
                        callBackTarget != null ? new BoogieIdentifierExpr(callBackTarget.Item2) : new BoogieIdentifierExpr("msgsender_MSG"),
                        new BoogieIdentifierExpr("msgvalue_MSG"),
                    };
                    foreach (VariableDeclaration param in funcDef.Parameters.Parameters)
                    {
                        string name = TransUtils.GetCanonicalLocalVariableName(param);
                        inputs.Add(new BoogieIdentifierExpr(name));
                        if (param.TypeName is ArrayTypeName array)
                        {
                            thenBody.AddStatement(new BoogieCallCmd(
                                                      "FreshRefGenerator",
                                                      new List <BoogieExpr>(), new List <BoogieIdentifierExpr>()
                            {
                                new BoogieIdentifierExpr(name)
                            }));
                        }
                    }

                    List <BoogieIdentifierExpr> outputs = new List <BoogieIdentifierExpr>();
                    var retParamCount = 0;

                    foreach (VariableDeclaration param in funcDef.ReturnParameters.Parameters)
                    {
                        string name = $"__ret_{retParamCount++}_" + funcDef.Name;
                        if (!string.IsNullOrEmpty(param.Name))
                        {
                            name = TransUtils.GetCanonicalLocalVariableName(param);
                        }
                        outputs.Add(new BoogieIdentifierExpr(name));
                    }

                    if (context.TranslateFlags.InstrumentGas)
                    {
                        havocGas(thenBody);
                    }
                    BoogieCallCmd callCmd = new BoogieCallCmd(callee, inputs, outputs);
                    thenBody.AddStatement(callCmd);

                    BoogieStmtList elseBody = ifCmd == null ? null : BoogieStmtList.MakeSingletonStmtList(ifCmd);
                    ifCmd = new BoogieIfCmd(guard, thenBody, elseBody);
                }
            }
            return(ifCmd);
        }
        private BoogieImplementation CreateSendSucess()
        {
            // send__success(from: Ref, to: Ref, amt: uint) returns (success: boolean)
            // {
            //    var __exception: bool;
            //    havoc __exception;
            //
            //    if(__exception)
            //    {
            //        //set tmps
            //        if ((__tmp__Balance[from]) >= (amt)) {
            //            call FallbackDispatch__fail(from, to, amt);
            //        }
            //
            //        success := false;
            //        assume(__revert);
            //
            //        revert := false;
            //    }
            //    else {
            //        if ((Balance[from]) >= (amt)) {
            //            call FallbackDispatch__success(from, to, amt);
            //            success := true;
            //        } else {
            //            success := false;
            //        }
            //
            //        assume(!(__revert));
            //    }
            // }

            List <BoogieVariable> inParams = new List <BoogieVariable>()
            {
                new BoogieFormalParam(new BoogieTypedIdent("from", BoogieType.Ref)),
                new BoogieFormalParam(new BoogieTypedIdent("to", BoogieType.Ref)),
                new BoogieFormalParam(new BoogieTypedIdent("amount", BoogieType.Int))
            };

            List <BoogieVariable> outParms = new List <BoogieVariable>()
            {
                new BoogieFormalParam(new BoogieTypedIdent("success", BoogieType.Bool))
            };

            List <BoogieVariable> locals = new List <BoogieVariable>()
            {
                new BoogieLocalVariable(new BoogieTypedIdent("__exception", BoogieType.Bool))
            };


            var fromId = new BoogieIdentifierExpr("from");
            var toId   = new BoogieIdentifierExpr("to");
            var amtId  = new BoogieIdentifierExpr("amount");

            var successId = new BoogieIdentifierExpr("success");

            var revertId = new BoogieIdentifierExpr("revert");

            var exceptionId = new BoogieIdentifierExpr("__exception");

            BoogieStmtList body = new BoogieStmtList();

            body.AddStatement(new BoogieHavocCmd(exceptionId));

            BoogieStmtList exceptionCase = new BoogieStmtList();

            foreach (var shadowGlobalPair in shadowGlobals)
            {
                string origVarName = shadowGlobalPair.Key;
                string shadowName  = shadowGlobalPair.Value.Name;
                exceptionCase.AddStatement(new BoogieAssignCmd(new BoogieIdentifierExpr(shadowName), new BoogieIdentifierExpr(origVarName)));
            }

            var checkTmpBalGuard = new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.GE,
                                                             new BoogieMapSelect(new BoogieIdentifierExpr(shadowGlobals["Balance"].Name), fromId),
                                                             amtId);
            var callFailDispatch = new BoogieCallCmd("FallbackDispatch__fail", new List <BoogieExpr>()
            {
                fromId, toId, amtId
            }, null);

            exceptionCase.AddStatement(new BoogieIfCmd(checkTmpBalGuard, BoogieStmtList.MakeSingletonStmtList(callFailDispatch), null));

            exceptionCase.AddStatement(new BoogieAssignCmd(successId, new BoogieLiteralExpr(false)));

            BoogieExpr failAssumePred = revertId;

            if (context.TranslateFlags.InstrumentGas)
            {
                failAssumePred = new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.OR, failAssumePred, new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.LT, new BoogieIdentifierExpr("gas"), new BoogieLiteralExpr(0)));
            }

            exceptionCase.AddStatement(new BoogieAssumeCmd(failAssumePred));
            exceptionCase.AddStatement(new BoogieAssignCmd(revertId, new BoogieLiteralExpr(false)));

            var successCase = new BoogieStmtList();

            var checkBalGuard = new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.GE,
                                                          new BoogieMapSelect(new BoogieIdentifierExpr("Balance"), fromId),
                                                          amtId);

            var successCaseStmts    = new BoogieStmtList();
            var callSuccessDispatch = new BoogieCallCmd("FallbackDispatch__success", new List <BoogieExpr>()
            {
                fromId, toId, amtId
            }, null);

            successCaseStmts.AddStatement(callSuccessDispatch);
            successCaseStmts.AddStatement(new BoogieAssignCmd(successId, new BoogieLiteralExpr(true)));

            successCase.AddStatement(new BoogieIfCmd(checkBalGuard, successCaseStmts, BoogieStmtList.MakeSingletonStmtList(new BoogieAssignCmd(successId, new BoogieLiteralExpr(false)))));

            BoogieExpr successAssumePred = new BoogieUnaryOperation(BoogieUnaryOperation.Opcode.NOT, revertId);

            if (context.TranslateFlags.InstrumentGas)
            {
                successAssumePred = new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.AND, successAssumePred, new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.GE, new BoogieIdentifierExpr("gas"), new BoogieLiteralExpr(0)));
            }

            successCase.AddStatement(new BoogieAssumeCmd(successAssumePred));

            body.AddStatement(new BoogieIfCmd(exceptionId, exceptionCase, successCase));
            return(new BoogieImplementation("send__success", inParams, outParms, locals, body));
        }
Exemple #24
0
        private BoogieStmtList CreateBodyOfUnknownFallback(List <BoogieVariable> fbLocalVars, List <BoogieVariable> inParams)
        {
            Debug.Assert(context.TranslateFlags.ModelStubsAsSkips() || context.TranslateFlags.ModelStubsAsCallbacks() || context.TranslateFlags.ModelStubsAsMultipleCallbacks(),
                         "CreateBodyOfUnknownFallback called in unexpected context");
            var procBody = new BoogieStmtList();

            /*procBody.AddStatement(new BoogieCommentCmd("---- Logic for payable function START "));
             * var balnSender = new BoogieMapSelect(new BoogieIdentifierExpr("Balance"), new BoogieIdentifierExpr(inParams[0].Name));
             * var balnThis = new BoogieMapSelect(new BoogieIdentifierExpr("Balance"), new BoogieIdentifierExpr(inParams[1].Name));
             * var msgVal = new BoogieIdentifierExpr("amount");
             * //assume Balance[msg.sender] >= msg.value
             * procBody.AddStatement(new BoogieAssumeCmd(new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.GE, balnSender, msgVal)));
             * //balance[from] = balance[from] - msg.value
             * procBody.AddStatement(new BoogieAssignCmd(balnSender, new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.SUB, balnSender, msgVal)));
             * //balance[to] = balance[to] + msg.value
             * procBody.AddStatement(new BoogieAssignCmd(balnThis, new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.ADD, balnThis, msgVal)));
             * procBody.AddStatement(new BoogieCommentCmd("---- Logic for payable function END "));*/

            BoogieStmtList body = procBody;

            if (context.TranslateFlags.ModelStubsAsCallbacks() ||
                context.TranslateFlags.ModelStubsAsMultipleCallbacks())
            {
                if (context.TranslateFlags.ModelReverts)
                {
                    BoogieBinaryOperation revertGuard = new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.EQ, new BoogieIdentifierExpr("choice"), new BoogieLiteralExpr(BigInteger.Zero));
                    BoogieStmtList        thenBody    = new BoogieStmtList();
                    thenBody.AddStatement(new BoogieAssignCmd(new BoogieIdentifierExpr("revert"), new BoogieLiteralExpr(true)));
                    thenBody.AddStatement(new BoogieReturnCmd());
                    BoogieIfCmd earlyExitCmd = new BoogieIfCmd(revertGuard, thenBody, null);
                    body.AddStatement(earlyExitCmd);
                }
                if (context.TranslateFlags.InstrumentGas)
                {
                    BoogieBinaryOperation gasGuard     = new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.LT, new BoogieIdentifierExpr("gas"), new BoogieLiteralExpr(TranslatorContext.TX_GAS_COST));
                    BoogieIfCmd           earlyExitCmd = new BoogieIfCmd(gasGuard, BoogieStmtList.MakeSingletonStmtList(new BoogieReturnCmd()), null);
                    body.AddStatement(earlyExitCmd);
                }
            }

            if (context.TranslateFlags.ModelStubsAsMultipleCallbacks())
            {
                fbLocalVars.Add(new BoogieLocalVariable(new BoogieTypedIdent("iterate", BoogieType.Bool)));
                BoogieBinaryOperation gasGuard = new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.GE, new BoogieIdentifierExpr("gas"), new BoogieLiteralExpr(TranslatorContext.TX_GAS_COST));
                BoogieBinaryOperation guard    = new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.AND, new BoogieIdentifierExpr("iterate"), gasGuard);
                BoogieStmtList        loopBody = new BoogieStmtList();
                procBody.AddStatement(new BoogieWhileCmd(guard, loopBody, new List <BoogieExpr>()));
                body = loopBody;
            }

            if (context.TranslateFlags.ModelStubsAsCallbacks() || context.TranslateFlags.ModelStubsAsMultipleCallbacks())
            {
                List <BoogieVariable> localVars = TransUtils.CollectLocalVars(context.ContractDefinitions.ToList(), context);
                fbLocalVars.AddRange(localVars);
                // if (*) fn1(from, *, ...)
                // we only redirect the calling contract, but the msg.sender need not be to, as it can call into anohter contract that calls
                // into from

                if (context.TranslateFlags.ModelStubsAsMultipleCallbacks())
                {
                    body.AppendStmtList(HavocLocals(localVars));
                    body.AddStatement(new BoogieHavocCmd(new BoogieIdentifierExpr("iterate")));
                }


                BoogieIfCmd typeIf = null;
                foreach (ContractDefinition curDef in context.ContractDefinitions.ToList())
                {
                    BoogieIfCmd reentrantCalls = TransUtils.GenerateChoiceBlock(new List <ContractDefinition>()
                    {
                        curDef
                    },
                                                                                context, false, Tuple.Create(inParams[0].Name, inParams[1].Name));

                    if (reentrantCalls == null)
                    {
                        continue;
                    }

                    BoogieExpr            dtype = new BoogieMapSelect(new BoogieIdentifierExpr("DType"), new BoogieIdentifierExpr(inParams[0].Name));
                    BoogieBinaryOperation guard = new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.EQ, dtype, new BoogieIdentifierExpr(curDef.Name));
                    typeIf = new BoogieIfCmd(guard, BoogieStmtList.MakeSingletonStmtList(reentrantCalls), typeIf == null ? null : BoogieStmtList.MakeSingletonStmtList(typeIf));
                }

                /*BoogieIfCmd ifCmd = null;
                 *
                 * if (context.TranslateFlags.ModelReverts)
                 * {
                 *  BoogieExpr guard = new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.EQ,
                 *                      new BoogieIdentifierExpr("choice"),
                 *                      new BoogieLiteralExpr(choices.Item2 + 1));
                 *
                 *  BoogieAssignCmd assign = new BoogieAssignCmd(new BoogieIdentifierExpr("revert"), new BoogieLiteralExpr(true));
                 *  ifCmd = new BoogieIfCmd(guard, BoogieStmtList.MakeSingletonStmtList(assign), BoogieStmtList.MakeSingletonStmtList(choices.Item1));
                 * }
                 * else
                 * {
                 *  ifCmd = choices.Item1;
                 * }*/

                body.AddStatement(typeIf);
            }



            return(procBody);
        }
Exemple #25
0
        public void Generate()
        {
            List <BoogieVariable> inParams = new List <BoogieVariable>()
            {
                new BoogieFormalParam(new BoogieTypedIdent("from", BoogieType.Ref)),
                new BoogieFormalParam(new BoogieTypedIdent("to", BoogieType.Ref)),
                new BoogieFormalParam(new BoogieTypedIdent("amount", BoogieType.Int))
            };
            List <BoogieVariable> outParams = new List <BoogieVariable>();

            List <BoogieAttribute> attributes = new List <BoogieAttribute>();

            if (context.TranslateFlags.GenerateInlineAttributes)
            {
                attributes.Add(new BoogieAttribute("inline", 1));
            }
            ;
            var             procName  = "FallbackDispatch";
            BoogieProcedure procedure = new BoogieProcedure(procName, inParams, outParams, attributes);

            context.Program.AddDeclaration(procedure);

            List <BoogieVariable> localVars  = new List <BoogieVariable>();
            var            fbUnknownProcName = "Fallback_UnknownType";
            BoogieStmtList procBody          = GenerateBodyOfFallbackDispatch(inParams, fbUnknownProcName);

            BoogieImplementation implementation = new BoogieImplementation(procName, inParams, outParams, localVars, procBody);

            context.Program.AddDeclaration(implementation);

            // let us havoc all the global variables when fallback_unknowntype is called
            var             modSet        = context.Program.Declarations.Where(x => x is BoogieGlobalVariable).Select(x => (BoogieGlobalVariable)x).ToList();
            BoogieProcedure unknownFbProc = new BoogieProcedure(fbUnknownProcName, inParams, outParams, attributes);

            context.Program.AddDeclaration(unknownFbProc);

            // we need to create an implementation as Corral seem to ignore modifies on declarations
            // https://github.com/boogie-org/corral/issues/98
            BoogieStmtList fbBody      = new BoogieStmtList();
            var            fbLocalVars = new List <BoogieVariable>();

            if (context.TranslateFlags.ModelStubsAsSkips() || context.TranslateFlags.ModelStubsAsCallbacks())
            {
                fbBody.AppendStmtList(CreateBodyOfUnknownFallback(fbLocalVars, inParams));
            }
            else
            {
                Debug.Assert(context.TranslateFlags.ModelStubsAsHavocs(), "Unknown option for modeling stubs");
                foreach (var global in modSet)
                {
                    fbBody.AddStatement(new BoogieHavocCmd(new BoogieIdentifierExpr(global.Name)));
                }
            }

            BoogieImplementation unknownFbImpl = new BoogieImplementation(fbUnknownProcName, inParams, outParams, fbLocalVars, fbBody);

            context.Program.AddDeclaration(unknownFbImpl);

            var sendProcName = "send";

            var sendOutParams = new List <BoogieVariable>()
            {
                new BoogieFormalParam(new BoogieTypedIdent("success", BoogieType.Bool))
            };
            BoogieProcedure sendProc = new BoogieProcedure(sendProcName, inParams, sendOutParams, attributes);

            context.Program.AddDeclaration(sendProc);

            BoogieStmtList sendBody = CreateBodyOfSend(inParams, sendOutParams, procName);

            context.Program.AddDeclaration(new BoogieImplementation(sendProcName, inParams, sendOutParams, localVars, sendBody));
        }
Exemple #26
0
        public static Tuple <BoogieIfCmd, int> GeneratePartialChoiceBlock(List <ContractDefinition> contracts, TranslatorContext context, BoogieExpr thisExpr, int startingPoint, bool canRevert, BoogieIfCmd alternatives = null, Tuple <string, string> callBackTarget = null)
        {
            BoogieIfCmd ifCmd = alternatives;
            int         j     = startingPoint;

            foreach (var contract in contracts)
            {
                if (contract.ContractKind != EnumContractKind.CONTRACT)
                {
                    continue;
                }

                HashSet <FunctionDefinition> funcDefs       = context.GetVisibleFunctionsByContract(contract);
                List <FunctionDefinition>    publicFuncDefs = new List <FunctionDefinition>();
                foreach (FunctionDefinition funcDef in funcDefs)
                {
                    if (funcDef.IsConstructor)
                    {
                        continue;
                    }
                    if (funcDef.IsFallback)
                    {
                        continue;                     //let us not call fallback directly in harness
                    }
                    if (context.TranslateFlags.PerformFunctionSlice &&
                        !context.TranslateFlags.SliceFunctions.Contains(funcDef))
                    {
                        continue;
                    }

                    if (funcDef.Visibility == EnumVisibility.PUBLIC || funcDef.Visibility == EnumVisibility.EXTERNAL)
                    {
                        publicFuncDefs.Add(funcDef);
                    }
                }
                for (int i = publicFuncDefs.Count - 1; i >= 0; --i)
                {
                    j++;
                    BoogieExpr guard = new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.EQ,
                                                                 new BoogieIdentifierExpr("choice"),
                                                                 new BoogieLiteralExpr(j));

                    BoogieStmtList thenBody = new BoogieStmtList();

                    FunctionDefinition funcDef = publicFuncDefs[i];
                    string             callee  = TransUtils.GetCanonicalFunctionName(funcDef, context);
                    List <BoogieExpr>  inputs  = new List <BoogieExpr>()
                    {
                        // let us just call back into the calling contract
                        callBackTarget != null ? new BoogieIdentifierExpr(callBackTarget.Item1) : thisExpr,
                        callBackTarget != null ? new BoogieIdentifierExpr(callBackTarget.Item2) : new BoogieIdentifierExpr("msgsender_MSG"),
                        new BoogieIdentifierExpr("msgvalue_MSG"),
                    };
                    var inpParamCount = 0;
                    foreach (VariableDeclaration param in funcDef.Parameters.Parameters)
                    {
                        string name = $"__arg_{inpParamCount++}_" + funcDef.Name;
                        if (!string.IsNullOrEmpty(param.Name))
                        {
                            name = TransUtils.GetCanonicalLocalVariableName(param, context);
                        }

                        BoogieIdentifierExpr boogieVar = new BoogieIdentifierExpr(name);
                        inputs.Add(boogieVar);
                        if (param.TypeName is ArrayTypeName array)
                        {
                            thenBody.AddStatement(new BoogieCallCmd(
                                                      "FreshRefGenerator",
                                                      new List <BoogieExpr>(), new List <BoogieIdentifierExpr>()
                            {
                                new BoogieIdentifierExpr(name)
                            }));
                        }

                        thenBody.AppendStmtList(constrainVarValues(context, param, boogieVar));
                    }

                    List <BoogieIdentifierExpr> outputs = new List <BoogieIdentifierExpr>();
                    var retParamCount = 0;

                    foreach (VariableDeclaration param in funcDef.ReturnParameters.Parameters)
                    {
                        string name = $"__ret_{retParamCount++}_" + funcDef.Name;
                        if (!string.IsNullOrEmpty(param.Name))
                        {
                            name = TransUtils.GetCanonicalLocalVariableName(param, context);
                        }

                        outputs.Add(new BoogieIdentifierExpr(name));
                    }

                    if (funcDef.StateMutability.Equals(EnumStateMutability.PAYABLE))
                    {
                        BoogieExpr assumeExpr = new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.GE,
                                                                          new BoogieIdentifierExpr("msgvalue_MSG"), new BoogieLiteralExpr(BigInteger.Zero));
                        thenBody.AddStatement(new BoogieAssumeCmd(assumeExpr));

                        if (!canRevert)
                        {
                            thenBody.AddStatement(new BoogieCommentCmd("---- Logic for payable function START "));
                            var balnSender = new BoogieMapSelect(new BoogieIdentifierExpr("Balance"), new BoogieIdentifierExpr("msgsender_MSG"));
                            var balnThis   = new BoogieMapSelect(new BoogieIdentifierExpr("Balance"), new BoogieIdentifierExpr("this"));
                            var msgVal     = new BoogieIdentifierExpr("msgvalue_MSG");
                            //assume Balance[msg.sender] >= msg.value
                            thenBody.AddStatement(new BoogieAssumeCmd(new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.GE, balnSender, msgVal)));
                            //balance[msg.sender] = balance[msg.sender] - msg.value
                            thenBody.AddStatement(new BoogieAssignCmd(balnSender, new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.SUB, balnSender, msgVal)));
                            //balance[this] = balance[this] + msg.value
                            thenBody.AddStatement(new BoogieAssignCmd(balnThis, new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.ADD, balnThis, msgVal)));
                            thenBody.AddStatement(new BoogieCommentCmd("---- Logic for payable function END "));
                        }
                    }
                    else
                    {
                        BoogieExpr assumeExpr = new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.EQ,
                                                                          new BoogieIdentifierExpr("msgvalue_MSG"), new BoogieLiteralExpr(BigInteger.Zero));
                        thenBody.AddStatement(new BoogieAssumeCmd(assumeExpr));
                    }

                    BoogieCallCmd callCmd = new BoogieCallCmd(callee, inputs, outputs);
                    thenBody.AddStatement(callCmd);

                    if (context.TranslateFlags.InstrumentGas)
                    {
                        var gasVar = new BoogieIdentifierExpr("gas");

                        BoogieBinaryOperation gasGuard = new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.GE, gasVar, new BoogieLiteralExpr(BigInteger.Zero));

                        BoogieIfCmd ifExpr = new BoogieIfCmd(gasGuard, thenBody, null);

                        thenBody = new BoogieStmtList();
                        //thenBody.AddStatement(new BoogieAssumeCmd(new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.GE, gasVar, new BoogieLiteralExpr(TranslatorContext.TX_GAS_COST))));
                        thenBody.AddStatement(new BoogieAssignCmd(gasVar, new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.SUB, gasVar, new BoogieLiteralExpr(TranslatorContext.TX_GAS_COST))));
                        thenBody.AddStatement(ifExpr);
                    }

                    BoogieStmtList elseBody = ifCmd == null ? null : BoogieStmtList.MakeSingletonStmtList(ifCmd);
                    ifCmd = new BoogieIfCmd(guard, thenBody, elseBody);
                }
            }
            return(new Tuple <BoogieIfCmd, int>(ifCmd, j));
        }