Beispiel #1
0
        private List <BoogieCallCmd> GenerateConstructorCall(ContractDefinition contract)
        {
            List <BoogieCallCmd> localStmtList = new List <BoogieCallCmd>();
            string            callee           = TransUtils.GetCanonicalConstructorName(contract);
            List <BoogieExpr> inputs           = new List <BoogieExpr>()
            {
                new BoogieIdentifierExpr("this"),
                new BoogieIdentifierExpr("msgsender_MSG"),
                new BoogieIdentifierExpr("msgvalue_MSG"),
            };

            if (context.IsConstructorDefined(contract))
            {
                FunctionDefinition ctor = context.GetConstructorByContract(contract);
                foreach (VariableDeclaration param in ctor.Parameters.Parameters)
                {
                    string name = TransUtils.GetCanonicalLocalVariableName(param);
                    inputs.Add(new BoogieIdentifierExpr(name));

                    if (param.TypeName is ArrayTypeName array)
                    {
                        localStmtList.Add(new BoogieCallCmd(
                                              "FreshRefGenerator",
                                              new List <BoogieExpr>(), new List <BoogieIdentifierExpr>()
                        {
                            new BoogieIdentifierExpr(name)
                        }));
                    }
                }
            }
            localStmtList.Add(new BoogieCallCmd(callee, inputs, null));
            return(localStmtList);
        }
Beispiel #2
0
        private List <BoogieVariable> GetParamsOfFunction(FunctionDefinition funcDef)
        {
            List <BoogieVariable> parameters = new List <BoogieVariable>();

            foreach (VariableDeclaration param in funcDef.Parameters.Parameters)
            {
                string         name     = TransUtils.GetCanonicalLocalVariableName(param);
                BoogieType     type     = TransUtils.GetBoogieTypeFromSolidityTypeName(param.TypeName);
                BoogieVariable localVar = new BoogieLocalVariable(new BoogieTypedIdent(name, type));
                parameters.Add(localVar);
            }

            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);
                }
                BoogieType     type     = TransUtils.GetBoogieTypeFromSolidityTypeName(param.TypeName);
                BoogieVariable localVar = new BoogieLocalVariable(new BoogieTypedIdent(name, type));
                parameters.Add(localVar);
            }

            return(parameters);
        }
Beispiel #3
0
        private List <BoogieVariable> CollectLocalVars(ContractDefinition contract)
        {
            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)),
                new BoogieLocalVariable(new BoogieTypedIdent("choice", BoogieType.Int)),
            };

            // use to remove duplicated variables by name
            HashSet <string> uniqueVarNames = new HashSet <string>()
            {
                "this", "msgsender_MSG", "msgvalue_MSG", "choice"
            };

            // Consider all visible functions
            HashSet <FunctionDefinition> funcDefs = context.GetVisibleFunctionsByContract(contract);

            foreach (FunctionDefinition funcDef in funcDefs)
            {
                if (funcDef.Visibility == EnumVisibility.PUBLIC || funcDef.Visibility == EnumVisibility.EXTERNAL)
                {
                    foreach (VariableDeclaration param in funcDef.Parameters.Parameters)
                    {
                        string name = TransUtils.GetCanonicalLocalVariableName(param);
                        if (!uniqueVarNames.Contains(name))
                        {
                            BoogieType     type     = TransUtils.GetBoogieTypeFromSolidityTypeName(param.TypeName);
                            BoogieVariable localVar = new BoogieLocalVariable(new BoogieTypedIdent(name, type));
                            localVars.Add(localVar);
                            uniqueVarNames.Add(name);
                        }
                    }

                    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);
                        }
                        if (!uniqueVarNames.Contains(name))
                        {
                            BoogieType     type     = TransUtils.GetBoogieTypeFromSolidityTypeName(param.TypeName);
                            BoogieVariable localVar = new BoogieLocalVariable(new BoogieTypedIdent(name, type));
                            localVars.Add(localVar);
                            uniqueVarNames.Add(name);
                        }
                    }
                }
            }
            return(localVars);
        }
Beispiel #4
0
        private List <BoogieCmd> GenerateConstructorCall(ContractDefinition contract)
        {
            List <BoogieCmd>  localStmtList = new List <BoogieCmd>();
            string            callee        = TransUtils.GetCanonicalConstructorName(contract);
            List <BoogieExpr> inputs        = new List <BoogieExpr>()
            {
                new BoogieIdentifierExpr("this"),
                new BoogieIdentifierExpr("msgsender_MSG"),
                new BoogieIdentifierExpr("msgvalue_MSG"),
            };

            if (context.IsConstructorDefined(contract))
            {
                FunctionDefinition ctor = context.GetConstructorByContract(contract);
                foreach (VariableDeclaration param in ctor.Parameters.Parameters)
                {
                    string name = TransUtils.GetCanonicalLocalVariableName(param, context);
                    inputs.Add(new BoogieIdentifierExpr(name));

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

            if (context.TranslateFlags.InstrumentGas)
            {
                var gasVar = new BoogieIdentifierExpr("gas");
                localStmtList.Add(new BoogieAssignCmd(gasVar, new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.SUB, gasVar, new BoogieLiteralExpr(TranslatorContext.CREATE_GAS_COST))));
            }

            localStmtList.Add(new BoogieCallCmd(callee, inputs, null));
            return(localStmtList);
        }
        public override bool Visit(ModifierDefinition modifier)
        {
            //if (modifier.Parameters.Length() > 0)
            //{
            //    throw new System.Exception("modifiers with parameters not implemented");
            //}
            var modifierInParams = TransUtils.GetDefaultInParams();

            foreach (var parameter in modifier.Parameters.Parameters)
            {
                string name = null;
                name = TransUtils.GetCanonicalLocalVariableName(parameter, context);
                BoogieType type = TransUtils.GetBoogieTypeFromSolidityTypeName(parameter.TypeName);
                modifierInParams.Add(new BoogieFormalParam(new BoogieTypedIdent(name, type)));
            }

            Block            body     = modifier.Body;
            bool             hasPre   = false;
            bool             hasPost  = false;
            List <Statement> postlude = new List <Statement>();

            // this list does not include locals introduced during translation
            List <BoogieLocalVariable> localVarsDeclared = new List <BoogieLocalVariable>();

            bool translatingPre = true;

            foreach (Statement statement in body.Statements)
            {
                if (statement is VariableDeclarationStatement varDecls)
                {
                    foreach (VariableDeclaration varDecl in varDecls.Declarations)
                    {
                        string     name = TransUtils.GetCanonicalLocalVariableName(varDecl, context);
                        BoogieType type = TransUtils.GetBoogieTypeFromSolidityTypeName(varDecl.TypeName);
                        // Issue a warning for intXX variables in case /useModularArithemtic option is used:
                        if (context.TranslateFlags.UseModularArithmetic && varDecl.TypeDescriptions.IsInt())
                        {
                            Console.WriteLine($"Warning: signed integer arithmetic is not handled with /useModularArithmetic option");
                        }
                        var boogieVariable = new BoogieLocalVariable(new BoogieTypedIdent(name, type));
                        if (translatingPre)
                        {
                            localVarsDeclared.Add(boogieVariable); // don't add locals after placeholder
                        }
                    }

                    // throw new System.Exception("locals within modifiers not supported");
                }
                if (statement is PlaceholderStatement)
                {
                    translatingPre = false;
                    // only capture those locals declared in the prefix, these are visible to postlude
                    context.AddPreludeLocalsToModifier(modifier.Name, localVarsDeclared);

                    continue;
                }
                if (translatingPre)
                {
                    hasPre = true;
                }
                else
                {
                    hasPost = true;
                }
            }

            var attributes = new List <BoogieAttribute>();

            attributes.Add(new BoogieAttribute("inline", 1));

            if (hasPre)
            {
                List <BoogieVariable> inParams  = new List <BoogieVariable>(modifierInParams);
                List <BoogieVariable> outParams = new List <BoogieVariable>();
                outParams.AddRange(localVarsDeclared.Select(x => new BoogieFormalParam(new BoogieTypedIdent("__out_mod_" + x.Name, x.TypedIdent.Type))));
                BoogieProcedure preludeProc = new BoogieProcedure(modifier.Name + "_pre", inParams, outParams, attributes);
                context.AddModiferToPreProc(modifier.Name, preludeProc);

                BoogieImplementation preludeImpl = new BoogieImplementation(modifier.Name + "_pre",
                                                                            inParams, outParams, new List <BoogieVariable>(), new BoogieStmtList());
                context.AddModiferToPreImpl(modifier.Name, preludeImpl);
            }

            if (hasPost)
            {
                List <BoogieVariable> inParams = new List <BoogieVariable>(modifierInParams);
                inParams.AddRange(localVarsDeclared);
                List <BoogieVariable> outParams    = new List <BoogieVariable>();
                BoogieProcedure       postludeProc = new BoogieProcedure(modifier.Name + "_post", inParams, outParams, attributes);
                context.AddModiferToPostProc(modifier.Name, postludeProc);

                BoogieImplementation postludeImpl = new BoogieImplementation(modifier.Name + "_post",
                                                                             inParams, outParams, new List <BoogieVariable>(), new BoogieStmtList());
                context.AddModiferToPostImpl(modifier.Name, postludeImpl);
            }

            return(false);
        }
Beispiel #6
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);
        }
Beispiel #7
0
        public override bool Visit(ModifierDefinition modifier)
        {
            //if (modifier.Parameters.Length() > 0)
            //{
            //    throw new System.Exception("modifiers with parameters not implemented");
            //}
            var modifierInParams = TransUtils.GetDefaultInParams();

            foreach (var parameter in modifier.Parameters.Parameters)
            {
                string name = null;
                name = TransUtils.GetCanonicalLocalVariableName(parameter);
                BoogieType type = TransUtils.GetBoogieTypeFromSolidityTypeName(parameter.TypeName);
                modifierInParams.Add(new BoogieFormalParam(new BoogieTypedIdent(name, type)));
            }

            Block            body     = modifier.Body;
            bool             hasPre   = false;
            bool             hasPost  = false;
            List <Statement> postlude = new List <Statement>();

            bool translatingPre = true;

            foreach (Statement statement in body.Statements)
            {
                if (statement is VariableDeclarationStatement)
                {
                    throw new System.Exception("locals within modifiers not supported");
                }
                if (statement is PlaceholderStatement)
                {
                    translatingPre = false;
                    continue;
                }
                if (translatingPre)
                {
                    hasPre = true;
                }
                else
                {
                    hasPost = true;
                }
            }

            if (hasPre)
            {
                List <BoogieVariable> inParams    = modifierInParams;
                List <BoogieVariable> outParams   = new List <BoogieVariable>();
                BoogieProcedure       preludeProc = new BoogieProcedure(modifier.Name + "_pre", inParams, outParams);
                context.AddModiferToPreProc(modifier.Name, preludeProc);

                BoogieImplementation preludeImpl = new BoogieImplementation(modifier.Name + "_pre",
                                                                            inParams, outParams, new List <BoogieVariable>(), new BoogieStmtList());
                context.AddModiferToPreImpl(modifier.Name, preludeImpl);
            }

            if (hasPost)
            {
                List <BoogieVariable> inParams     = modifierInParams;
                List <BoogieVariable> outParams    = new List <BoogieVariable>();
                BoogieProcedure       postludeProc = new BoogieProcedure(modifier.Name + "_post", inParams, outParams);
                context.AddModiferToPostProc(modifier.Name, postludeProc);

                BoogieImplementation postludeImpl = new BoogieImplementation(modifier.Name + "_post",
                                                                             inParams, outParams, new List <BoogieVariable>(), new BoogieStmtList());
                context.AddModiferToPostImpl(modifier.Name, postludeImpl);
            }

            return(false);
        }
Beispiel #8
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);
        }
Beispiel #9
0
        public static List <BoogieVariable> CollectLocalVars(List <ContractDefinition> contracts, TranslatorContext context)
        {
            Debug.Assert(contracts.Count > 0, "Internal exception: expecting at least one contract here");
            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)),
                new BoogieLocalVariable(new BoogieTypedIdent("choice", BoogieType.Int)),
            };

            // use to remove duplicated variables by name
            HashSet <string> uniqueVarNames = new HashSet <string>()
            {
                "this", "msgsender_MSG", "msgvalue_MSG", "choice"
            };

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

                // Consider all visible functions
                HashSet <FunctionDefinition> funcDefs = context.GetVisibleFunctionsByContract(contract);
                foreach (FunctionDefinition funcDef in funcDefs)
                {
                    if (funcDef.Visibility == EnumVisibility.PUBLIC || funcDef.Visibility == EnumVisibility.EXTERNAL)
                    {
                        foreach (VariableDeclaration param in funcDef.Parameters.Parameters)
                        {
                            string name = TransUtils.GetCanonicalLocalVariableName(param);
                            if (!uniqueVarNames.Contains(name))
                            {
                                BoogieType     type     = TransUtils.GetBoogieTypeFromSolidityTypeName(param.TypeName);
                                BoogieVariable localVar = new BoogieLocalVariable(new BoogieTypedIdent(name, type));
                                localVars.Add(localVar);
                                uniqueVarNames.Add(name);
                            }
                        }

                        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);
                            }
                            if (!uniqueVarNames.Contains(name))
                            {
                                BoogieType     type     = TransUtils.GetBoogieTypeFromSolidityTypeName(param.TypeName);
                                BoogieVariable localVar = new BoogieLocalVariable(new BoogieTypedIdent(name, type));
                                localVars.Add(localVar);
                                uniqueVarNames.Add(name);
                            }
                        }
                    }
                }
            }
            return(localVars);
        }
Beispiel #10
0
        private List <BoogieCmd> GenerateConstructorCall(ContractDefinition contract)
        {
            List <BoogieCmd>  localStmtList = new List <BoogieCmd>();
            string            callee        = TransUtils.GetCanonicalConstructorName(contract);
            List <BoogieExpr> inputs        = new List <BoogieExpr>()
            {
                new BoogieIdentifierExpr("this"),
                new BoogieIdentifierExpr("msgsender_MSG"),
                new BoogieIdentifierExpr("msgvalue_MSG"),
            };

            if (context.IsConstructorDefined(contract))
            {
                FunctionDefinition ctor = context.GetConstructorByContract(contract);
                if (ctor.StateMutability.Equals(EnumStateMutability.PAYABLE))
                {
                    BoogieExpr assumeExpr = new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.GE,
                                                                      new BoogieIdentifierExpr("msgvalue_MSG"), new BoogieLiteralExpr(BigInteger.Zero));
                    localStmtList.Add(new BoogieAssumeCmd(assumeExpr));

                    localStmtList.Add(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
                    localStmtList.Add(new BoogieAssumeCmd(new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.GE, balnSender, msgVal)));
                    //balance[msg.sender] = balance[msg.sender] - msg.value
                    localStmtList.Add(new BoogieAssignCmd(balnSender, new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.SUB, balnSender, msgVal)));
                    //balance[this] = balance[this] + msg.value
                    localStmtList.Add(new BoogieAssignCmd(balnThis, new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.ADD, balnThis, msgVal)));
                    localStmtList.Add(new BoogieCommentCmd("---- Logic for payable function END "));
                }
                else
                {
                    BoogieExpr assumeExpr = new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.EQ,
                                                                      new BoogieIdentifierExpr("msgvalue_MSG"), new BoogieLiteralExpr(BigInteger.Zero));
                    localStmtList.Add(new BoogieAssumeCmd(assumeExpr));
                }

                foreach (VariableDeclaration param in ctor.Parameters.Parameters)
                {
                    string name = TransUtils.GetCanonicalLocalVariableName(param, context);
                    inputs.Add(new BoogieIdentifierExpr(name));

                    if (param.TypeName is ArrayTypeName array)
                    {
                        localStmtList.Add(new BoogieCallCmd(
                                              "FreshRefGenerator",
                                              new List <BoogieExpr>(), new List <BoogieIdentifierExpr>()
                        {
                            new BoogieIdentifierExpr(name)
                        }));
                    }
                }
            }
            else
            {
                BoogieExpr assumeExpr = new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.EQ,
                                                                  new BoogieIdentifierExpr("msgvalue_MSG"), new BoogieLiteralExpr(BigInteger.Zero));
                localStmtList.Add(new BoogieAssumeCmd(assumeExpr));
            }

            if (context.TranslateFlags.InstrumentGas)
            {
                var gasVar = new BoogieIdentifierExpr("gas");
                localStmtList.Add(new BoogieAssignCmd(gasVar, new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.SUB, gasVar, new BoogieLiteralExpr(TranslatorContext.CREATE_GAS_COST))));
            }

            localStmtList.Add(new BoogieCallCmd(callee, inputs, null));
            return(localStmtList);
        }
Beispiel #11
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));
        }