Ejemplo n.º 1
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(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))));
        }
Ejemplo n.º 2
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))));
        }
Ejemplo n.º 3
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);
        }
Ejemplo 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));
        }
Ejemplo n.º 5
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);
        }
Ejemplo n.º 6
0
        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));
        }
Ejemplo n.º 7
0
        public void PerformModSetAnalysis()
        {
            BoogieProgram prog = context.Program;

            List <BoogieImplementation> impls = new List <BoogieImplementation>();
            Dictionary <string, BoogieGlobalVariable> globals    = new Dictionary <string, BoogieGlobalVariable>();
            Dictionary <string, BoogieProcedure>      procedures = new Dictionary <string, BoogieProcedure>();

            foreach (var decl in prog.Declarations)
            {
                if (decl is BoogieImplementation)
                {
                    impls.Add((BoogieImplementation)decl);
                }
                else if (decl is BoogieProcedure)
                {
                    BoogieProcedure proc = (BoogieProcedure)decl;
                    procedures.Add(proc.Name, proc);
                }
                else if (decl is BoogieGlobalVariable)
                {
                    var globalVar = (BoogieGlobalVariable)decl;
                    globals.Add(globalVar.Name, globalVar);
                }
            }

            calculateFlattenCmdLists(impls);

            foreach (var impl in impls)
            {
                HashSet <BoogieGlobalVariable> modSet = new HashSet <BoogieGlobalVariable>();
                modSets.Add(impl.Name, modSet);

                foreach (var stmt in flattenedCmdLists[impl.Name])
                {
                    switch (stmt)
                    {
                    case BoogieHavocCmd havoc:
                        foreach (var identifier in havoc.Vars)
                        {
                            var idName = identifier.Name;
                            if (globals.ContainsKey(idName))
                            {
                                modSet.Add(globals[idName]);
                            }
                        }
                        break;

                    case BoogieAssignCmd assign:
                        switch (assign.Lhs)
                        {
                        case BoogieIdentifierExpr idExpr:
                        {
                            var idName = idExpr.Name;
                            if (globals.ContainsKey(idName))
                            {
                                modSet.Add(globals[idName]);
                            }
                            break;
                        }

                        case BoogieMapSelect mapSelect:
                        {
                            var idName = findOutermostIdentifierExpr(mapSelect).Name;
                            if (globals.ContainsKey(idName))
                            {
                                modSet.Add(globals[idName]);
                            }
                            break;
                        }

                        default:
                            throw new RuntimeWrappedException("unexpected LHS");
                        }
                        break;
                    }
                }
            }

            bool modSetChange;

            do
            {
                modSetChange = false;

                foreach (var impl in impls)
                {
                    HashSet <BoogieGlobalVariable> currModSet = modSets[impl.Name];
                    int oldSize = currModSet.Count;
                    foreach (var stmt in flattenedCmdLists[impl.Name])
                    {
                        if (stmt is BoogieCallCmd)
                        {
                            BoogieCallCmd callCmd = (BoogieCallCmd)stmt;

                            if (modSets.ContainsKey(callCmd.Callee))
                            {
                                currModSet.UnionWith(modSets[callCmd.Callee]);
                            }
                        }
                    }

                    if (currModSet.Count > oldSize)
                    {
                        modSetChange = true;
                    }
                }
            } while (modSetChange);

            foreach (var impl in impls)
            {
                procedures[impl.Name].ModSet = modSets[impl.Name].ToList();
            }
        }
Ejemplo n.º 8
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));
        }