//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); }