Esempio n. 1
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));
            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(GenerateWhileLoop(contract, houdiniVarMap, localVars));
            BoogieImplementation harnessImpl = new BoogieImplementation(harnessName, inParams, outParams, localVars, harnessBody);

            context.Program.AddDeclaration(harnessImpl);
        }
Esempio n. 2
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));
            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);
        }
Esempio n. 3
0
        private BoogieExpr dupAndReplaceExpr(BoogieExpr expr, bool isFail, bool inHarness)
        {
            List <BoogieExpr> dupAndReplaceExprList(List <BoogieExpr> exprs)
            {
                return(exprs.Select(e => dupAndReplaceExpr(e, isFail, inHarness)).ToList());
            }

            if (expr is BoogieIdentifierExpr)
            {
                string idName = ((BoogieIdentifierExpr)expr).Name;
                if (isFail && shadowGlobals.ContainsKey(idName))
                {
                    return(new BoogieIdentifierExpr(shadowGlobals[idName].Name));
                }

                return(expr);
            }
            if (expr is BoogieMapSelect)
            {
                BoogieMapSelect selectExpr = (BoogieMapSelect)expr;
                return(new BoogieMapSelect(dupAndReplaceExpr(selectExpr.BaseExpr, isFail, inHarness),
                                           dupAndReplaceExprList(selectExpr.Arguments)));
            }
            if (expr is BoogieMapUpdate)
            {
                BoogieMapUpdate updateExpr = (BoogieMapUpdate)expr;
                return(new BoogieMapUpdate(dupAndReplaceExpr(updateExpr.BaseExpr, isFail, inHarness),
                                           dupAndReplaceExprList(updateExpr.Arguments),
                                           dupAndReplaceExpr(updateExpr.Value, isFail, inHarness)));
            }
            if (expr is BoogieUnaryOperation)
            {
                BoogieUnaryOperation unaryOperation = (BoogieUnaryOperation)expr;
                return(new BoogieUnaryOperation(unaryOperation.Op, dupAndReplaceExpr(unaryOperation.Expr, isFail, inHarness)));
            }
            if (expr is BoogieBinaryOperation)
            {
                BoogieBinaryOperation binOperation = (BoogieBinaryOperation)expr;
                return(new BoogieBinaryOperation(binOperation.Op, dupAndReplaceExpr(binOperation.Lhs, isFail, inHarness),
                                                 dupAndReplaceExpr(binOperation.Rhs, isFail, inHarness)));
            }
            if (expr is BoogieITE)
            {
                BoogieITE iteExpr = (BoogieITE)expr;
                return(new BoogieITE(dupAndReplaceExpr(iteExpr.Guard, isFail, inHarness),
                                     dupAndReplaceExpr(iteExpr.ThenExpr, isFail, inHarness),
                                     dupAndReplaceExpr(iteExpr.ElseExpr, isFail, inHarness)));
            }
            if (expr is BoogieQuantifiedExpr)
            {
                BoogieQuantifiedExpr quantifiedExpr = (BoogieQuantifiedExpr)expr;
                return(new BoogieQuantifiedExpr(quantifiedExpr.IsForall, quantifiedExpr.QVars, quantifiedExpr.QVarTypes,
                                                dupAndReplaceExpr(quantifiedExpr.BodyExpr, isFail, inHarness),
                                                quantifiedExpr.Trigger));
            }
            if (expr is BoogieFuncCallExpr)
            {
                BoogieFuncCallExpr callExpr = (BoogieFuncCallExpr)expr;

                string calledFun = callExpr.Function;

                // TODO: handle this properly.
//                if (!isHarnessProcudure(calledFun) && procsWiltImplNames.Contains(calledFun))
//                {
//                    if (!inHarness || (!isConstructor(calledFun) && !isPublic(proceduresInProgram[calledFun])))
//                        calledFun = calledFun + (isFail ? "__fail" : "__success");
//                }

                return(new BoogieFuncCallExpr(calledFun, dupAndReplaceExprList(callExpr.Arguments)));
            }
            if (expr is BoogieTupleExpr)
            {
                BoogieTupleExpr tupleExpr = (BoogieTupleExpr)expr;
                return(new BoogieTupleExpr(dupAndReplaceExprList(tupleExpr.Arguments)));
            }

            return(expr);
        }
Esempio n. 4
0
        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));
        }
Esempio n. 5
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];
                if (!originalProcName.Equals("send"))
                {
                    context.Program.AddDeclaration(createFailImplementation(proc.Name, originalImpl));
                    context.Program.AddDeclaration(createSuccessImplementation(originalProcName + "__success", originalImpl));
                }
                else
                {
                    context.Program.AddDeclaration(CreateSendFail());
                    context.Program.AddDeclaration(CreateSendSucess());
                }

                // 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()));
                    BoogieExpr successAssumePred = new BoogieUnaryOperation(BoogieUnaryOperation.Opcode.NOT, new BoogieIdentifierExpr(revertGlobalName));

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

                    // 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()));
                    BoogieExpr failAssumePred = new BoogieIdentifierExpr(revertGlobalName);

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

                    stmtList.AddStatement(new BoogieIfCmd(new BoogieIdentifierExpr(exceptionVarName), failCallStmtList, successCallStmtList));
                }
            }
        }
        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));
        }