Exemple #1
0
        //Construct Memory Maps for Arrays for Mapping and ArrayTypeName types.
        private void ConstructMappingMemoryArray(Mapping mapping, HashSet <KeyValuePair <BoogieType, BoogieType> > generatedTypes)
        {
            BoogieType boogieKeyType   = Conversion_Utility_Tool.GetBoogieTypeFromSolidityTypeName(mapping.KeyType);
            BoogieType boogieValueType = null;

            if (mapping.ValueType is Mapping submapping)
            {
                boogieValueType = BoogieType.Ref;
                ConstructMappingMemoryArray(submapping, generatedTypes);
            }
            else if (mapping.ValueType is ArrayTypeName array)
            {
                boogieValueType = BoogieType.Ref;
                ConstructArrayMemoryMap(array, generatedTypes);
            }
            else
            {
                boogieValueType = Conversion_Utility_Tool.GetBoogieTypeFromSolidityTypeName(mapping.ValueType);
            }

            KeyValuePair <BoogieType, BoogieType> pair = new KeyValuePair <BoogieType, BoogieType>(boogieKeyType, boogieValueType);

            if (!generatedTypes.Contains(pair))
            {
                generatedTypes.Add(pair);
                BuildSingleMapMemoryName(boogieKeyType, boogieValueType);
            }
        }
Exemple #2
0
        //Build Memory Map for Array types,
        private void ConstructArrayMemoryMap(ArrayTypeName array, HashSet <KeyValuePair <BoogieType, BoogieType> > generatedTypes)
        {
            BoogieType boogieKeyType   = BoogieType.Int;
            BoogieType boogieValueType = null;

            if (array.BaseType is ArrayTypeName subarray)
            {
                boogieValueType = BoogieType.Ref;
                ConstructArrayMemoryMap(subarray, generatedTypes); //construct array memory map with sub array
            }
            else if (array.BaseType is Mapping mapping)
            {
                boogieValueType = BoogieType.Ref;
                ConstructMappingMemoryArray(mapping, generatedTypes); // construct array memory map using mapping type
            }
            else
            {
                boogieValueType = Conversion_Utility_Tool.GetBoogieTypeFromSolidityTypeName(array.BaseType); //type cannot be resolve, request type declaration
            }

            KeyValuePair <BoogieType, BoogieType> pair = new KeyValuePair <BoogieType, BoogieType>(boogieKeyType, boogieValueType);

            if (generatedTypes.Contains(pair) == false)
            {
                generatedTypes.Add(pair);
                BuildSingleMapMemoryName(boogieKeyType, boogieValueType);
            }
        }
        //Create a contract boogie harness for each respective contract parsed through here.
        private void createContractBoogieHarness(ContractDefinition contract)
        {
            //create the contract harness name
            string contractHarnessName = "BoogieEntry_" + contract.Name;

            //input boogie variables
            List <BoogieVariable> inputParameters = new List <BoogieVariable>();
            //output boogie variables
            List <BoogieVariable> outputParameters = new List <BoogieVariable>();

            //Generate the harness procedure declaration.
            BoogieProcedure harnessProcedureDeclaration = new BoogieProcedure(contractHarnessName, inputParameters, outputParameters);

            classTranslatorContext.getProgram.AddBoogieDeclaration(harnessProcedureDeclaration);

            List <BoogieVariable> localVariables = Conversion_Utility_Tool.CollectLocalVars(new List <ContractDefinition>()
            {
                contract
            }, classTranslatorContext);
            BoogieStmtList harnessBody = new BoogieStmtList();

            //add dynamic type assumptions to harness body and generate constructor call fallback.
            harnessBody.AddStatement(BuildDynamicTypeAssumptions(contract));
            GenerateConstructorCall(contract).ForEach(x => harnessBody.AddStatement(x));

            //create a boogie implementation type that represents a harness with the above parameters
            BoogieImplementation harnessImpl = new BoogieImplementation(contractHarnessName, inputParameters, outputParameters, localVariables, harnessBody);

            //add the implementation as a declaration to the Boogie Program
            classTranslatorContext.getProgram.AddBoogieDeclaration(harnessImpl);
        }
Exemple #4
0
        /**
         * Iterates through contract set, filters functions and events from base contracts and adds them to AST_Handler instance
         */
        public void filterFunctionsAndEvents()
        {
            List <ContractDefinition> contractSet = new List <ContractDefinition>(classTranslatorContext.ContractDefinitionsMap);

            foreach (ContractDefinition indexContract in contractSet)
            {
                // create a localised list of integer values containi
                List <int> baseContractSet = new List <int>(indexContract.LinearBaseContracts);

                //for each base contract, return its respective function and event definitiosn and add them to the Handler context.
                foreach (int i in baseContractSet)
                {
                    //return the base contract at index i
                    ContractDefinition baseContract = classTranslatorContext.retrieveASTNodethroughID(i) as ContractDefinition;
                    if (baseContract != null)
                    {
                        //loop through function defs hashset and for each functionDefinition, compute
                        //the function signature and add the function to the AST_Handler instance.
                        foreach (FunctionDefinition function in classTranslatorContext.returnFunctionDefs(baseContract))
                        {
                            string functionSignature = Conversion_Utility_Tool.ComputeFunctionSignature(function);

                            if (classTranslatorContext != null)
                            {
                                classTranslatorContext.AddFunctionToDynamicType(
                                    Conversion_Utility_Tool.ComputeFunctionSignature(function), //Computed signature of function
                                    indexContract,                                              //contract for which function will be added
                                    function);                                                  //Function be added
                            }
                        }
                        foreach (EventDefinition singleEvent in classTranslatorContext.retrieveEventDefinitionsUsingContract(baseContract))
                        {
                            //if the translator context is not null then add the single event to the contract via addEventToContract
                            if (classTranslatorContext != null)
                            {
                                classTranslatorContext.InsertEventInContract(indexContract, singleEvent);
                            }
                        }

                        //Compute Visible functions in existing function declaration
                        foreach (string funcSig in classTranslatorContext.SignatureFunctionMap.Keys)
                        {
                            foreach (ContractDefinition tempContract in classTranslatorContext.SignatureFunctionMap[funcSig].Keys)
                            {
                                FunctionDefinition funcDef = classTranslatorContext.SignatureFunctionMap[funcSig][tempContract];
                                classTranslatorContext.AddVisibleFunctionToContract(funcDef, tempContract);
                            }
                        }
                    }
                }
            }
        }
Exemple #5
0
        private void GenerateStructConstructors(ContractDefinition contract, StructDefinition structDefn)
        {
            // generate the internal one without base constructors
            string procName = structDefn.CanonicalName + "_ctor";
            List <BoogieVariable> inParams = new List <BoogieVariable>();

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

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

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

            context.getProgram.AddBoogieDeclaration(procedure);

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

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

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

            context.getProgram.AddBoogieDeclaration(implementation);
        }
Exemple #6
0
        //Function to insert a function into the specified contract.
        public void InsertFunctionInContract(ContractDefinition contract, FunctionDefinition funcDef)
        {
            if (FunctionMapping.ContainsKey(contract) == false)
            {
                Debug.Assert(!FunctionSignatureMapping.ContainsKey(contract));
                FunctionMapping[contract]          = new HashSet <FunctionDefinition>();
                FunctionSignatureMapping[contract] = new HashSet <string>();
            }

            Debug.Assert(!FunctionMapping[contract].Contains(funcDef), $"Repeated function warning: {funcDef.Name}");
            FunctionMapping[contract].Add(funcDef);

            string signature = Conversion_Utility_Tool.ComputeFunctionSignature(funcDef);

            FunctionSignatureMapping[contract].Add(signature);

            Debug.Assert(!FunctionToContractMap.ContainsKey(funcDef), $" Repeated function warning: {funcDef.Name}");
            FunctionToContractMap[funcDef] = contract;
        }
        //Function to generate constructor call and add IdentifierExpressions from contract users.
        private List <BoogieCmd> GenerateConstructorCall(ContractDefinition contract)
        {
            List <BoogieCmd> localStmtList = new List <BoogieCmd>();
            string           callee        = Conversion_Utility_Tool.GetCanonicalConstructorName(contract);

            //Identify third part users of the conttract.
            //sender refers external party call.
            List <BoogieExpr> constructorCallInputs = new List <BoogieExpr>();

            constructorCallInputs.Add(new BoogieIdentifierExpr("this"));
            constructorCallInputs.Add(new BoogieIdentifierExpr("msgsender_MSG"));
            constructorCallInputs.Add(new BoogieIdentifierExpr("msgvalue_MSG"));


            if (classTranslatorContext.checkConstructorExists(contract) == true)
            {
                FunctionDefinition constructor = classTranslatorContext.retrieveConstructor(contract);
                foreach (VariableDeclaration param in constructor.Parameters.Parameters)
                {
                    string name = Conversion_Utility_Tool.GetCanonicalLocalVariableName(param, classTranslatorContext);
                    constructorCallInputs.Add(new BoogieIdentifierExpr(name));

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

            if (Flags_HelperClass.InstrumentGas)
            {
                Conversion_Utility_Tool.havocGas(localStmtList);
            }

            localStmtList.Add(new BoogieCallCmd(callee, constructorCallInputs, null));
            return(localStmtList);
        }
        /// <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, AST_Handler 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.RetrieveVisibleFunctions(contract);
                List <FunctionDefinition>    publicFuncDefs = new List <FunctionDefinition>();
                foreach (FunctionDefinition funcDef in funcDefs)
                {
                    if (funcDef.ofConstructorType)
                    {
                        continue;
                    }
                    if (funcDef.ofFallBackType)
                    {
                        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  = Conversion_Utility_Tool.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"),
                    };
                    var inpParamCount = 0;
                    foreach (VariableDeclaration param in funcDef.Parameters.Parameters)
                    {
                        string name = $"__arg_{inpParamCount++}_" + funcDef.Name;
                        if (!string.IsNullOrEmpty(param.Name))
                        {
                            name = Conversion_Utility_Tool.GetCanonicalLocalVariableName(param, context);
                        }
                        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 = Conversion_Utility_Tool.GetCanonicalLocalVariableName(param, context);
                        }

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

                    if (Flags_HelperClass.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);
        }
        public static List <BoogieVariable> CollectLocalVars(List <ContractDefinition> contracts, AST_Handler 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.RetrieveVisibleFunctions(contract);
                foreach (FunctionDefinition funcDef in funcDefs)
                {
                    if (funcDef.Visibility == EnumVisibility.PUBLIC || funcDef.Visibility == EnumVisibility.EXTERNAL)
                    {
                        var inpParamCount = 0;
                        foreach (VariableDeclaration param in funcDef.Parameters.Parameters)
                        {
                            string name = $"__arg_{inpParamCount++}_" + funcDef.Name;
                            if (!string.IsNullOrEmpty(param.Name))
                            {
                                name = Conversion_Utility_Tool.GetCanonicalLocalVariableName(param, context);
                            }
                            if (!uniqueVarNames.Contains(name))
                            {
                                BoogieType     type     = Conversion_Utility_Tool.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_{retParamCount++}_" + funcDef.Name;
                            if (!string.IsNullOrEmpty(param.Name))
                            {
                                name = Conversion_Utility_Tool.GetCanonicalLocalVariableName(param, context);
                            }
                            if (!uniqueVarNames.Contains(name))
                            {
                                BoogieType     type     = Conversion_Utility_Tool.GetBoogieTypeFromSolidityTypeName(param.TypeName);
                                BoogieVariable localVar = new BoogieLocalVariable(new BoogieTypedIdent(name, type));
                                localVars.Add(localVar);
                                uniqueVarNames.Add(name);
                            }
                        }
                    }
                }
            }
            return(localVars);
        }