private static BoogieMapSelect GetBoogieExprOfStateVar(VariableDeclaration varDecl, TranslatorContext context) { string name = TransUtils.GetCanonicalStateVariableName(varDecl, context); BoogieMapSelect mapSelect = new BoogieMapSelect(new BoogieIdentifierExpr(name), new BoogieIdentifierExpr("this")); return(mapSelect); }
public BoogieExpr GetLength(VariableDeclaration varDecl, BoogieExpr receiver) { if (context.TranslateFlags.UseMultiDim && context.Analysis.Alias.getResults().Contains(varDecl)) { BoogieExpr curExpr = receiver; int lvl = -1; List <BoogieExpr> keys = new List <BoogieExpr>(); while (curExpr is BoogieMapSelect sel) { curExpr = sel.BaseExpr; keys.Insert(0, sel.Arguments[0]); lvl++; } string lenName = GetMultiDimLengthName(varDecl, lvl); BoogieExpr lenExpr = new BoogieIdentifierExpr(lenName); foreach (BoogieExpr key in keys) { lenExpr = new BoogieMapSelect(lenExpr, key); } return(lenExpr); } return(new BoogieMapSelect(new BoogieIdentifierExpr("Length"), receiver)); }
public BoogieExpr GetSumExpr(VariableDeclaration decl, BoogieExpr varExpr) { BoogieIdentifierExpr sumIdent = new BoogieIdentifierExpr(GetSumName(decl)); BoogieMapSelect sumSelect = new BoogieMapSelect(sumIdent, varExpr); return(sumSelect); }
private BoogieIfCmd GenerateChoices(ContractDefinition contract) { BoogieExpr thisVal = new BoogieIdentifierExpr("this"); Tuple <BoogieIfCmd, int> curChoices = TransUtils.GeneratePartialChoiceBlock(new List <ContractDefinition>() { contract }, context, thisVal, 0, context.TranslateFlags.ModelReverts); if (context.TranslateFlags.TxnsOnFields) { HashSet <VariableDeclaration> contractFields = context.GetStateVarsByContract(contract); foreach (VariableDeclaration contractField in contractFields) { if (contractField.TypeDescriptions.IsContract() && contractField.TypeName is UserDefinedTypeName) { BoogieExpr fieldInstance = new BoogieMapSelect(new BoogieIdentifierExpr(TransUtils.GetCanonicalVariableName(contractField, context)), thisVal); String fieldContractName = contractField.TypeName.ToString(); ContractDefinition fieldDef = context.GetContractByName(fieldContractName); curChoices = TransUtils.GeneratePartialChoiceBlock(new List <ContractDefinition>() { fieldDef }, context, fieldInstance, curChoices.Item2, context.TranslateFlags.ModelReverts, curChoices.Item1); } } } return(curChoices.Item1); }
private BoogieAssumeCmd GenerateDynamicTypeAssumes(ContractDefinition contract) { BoogieExpr assumeLhs = new BoogieMapSelect(new BoogieIdentifierExpr("DType"), new BoogieIdentifierExpr("this")); List <ContractDefinition> subtypes = new List <ContractDefinition>(context.GetSubTypesOfContract(contract)); Debug.Assert(subtypes.Count > 0); BoogieExpr assumeExpr0 = new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.EQ, assumeLhs, new BoogieIdentifierExpr(subtypes[0].Name)); var assumeExpr = assumeExpr0; for (int i = 1; i < subtypes.Count; ++i) { BoogieExpr rhs = new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.EQ, assumeLhs, new BoogieIdentifierExpr(subtypes[i].Name)); assumeExpr = new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.OR, assumeExpr, rhs); } if (context.TranslateFlags.OmitAssumeFalseForDynDispatch) { return(new BoogieAssumeCmd(new BoogieLiteralExpr(true))); //assumeExpr0); } return(new BoogieAssumeCmd(assumeExpr)); }
private BoogieStmtList CreateBodyOfUnknownFallback(List <BoogieVariable> fbLocalVars, List <BoogieVariable> inParams) { Debug.Assert(context.TranslateFlags.ModelStubsAsSkips() || context.TranslateFlags.ModelStubsAsCallbacks(), "CreateBodyOfUnknownFallback called in unexpected context"); var procBody = new BoogieStmtList(); procBody.AddStatement(new BoogieCommentCmd("---- Logic for payable function START ")); var balnSender = new BoogieMapSelect(new BoogieIdentifierExpr("Balance"), new BoogieIdentifierExpr(inParams[0].Name)); var balnThis = new BoogieMapSelect(new BoogieIdentifierExpr("Balance"), new BoogieIdentifierExpr(inParams[1].Name)); var msgVal = new BoogieIdentifierExpr("amount"); //assume Balance[msg.sender] >= msg.value procBody.AddStatement(new BoogieAssumeCmd(new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.GE, balnSender, msgVal))); //balance[from] = balance[from] - msg.value procBody.AddStatement(new BoogieAssignCmd(balnSender, new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.SUB, balnSender, msgVal))); //balance[to] = balance[to] + msg.value procBody.AddStatement(new BoogieAssignCmd(balnThis, new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.ADD, balnThis, msgVal))); procBody.AddStatement(new BoogieCommentCmd("---- Logic for payable function END ")); if (context.TranslateFlags.ModelStubsAsCallbacks()) { fbLocalVars.AddRange(TransUtils.CollectLocalVars(context.ContractDefinitions.ToList(), context)); // if (*) fn1(from, *, ...) // we only redirect the calling contract, but the msg.sender need not be to, as it can call into anohter contract that calls // into from procBody.AddStatement(TransUtils.GenerateChoiceBlock(context.ContractDefinitions.ToList(), context, Tuple.Create(inParams[0].Name, inParams[1].Name))); } return(procBody); }
public BoogieExpr GetMemoryMapSelectExpr(VariableDeclaration decl, BoogieType mapKeyType, BoogieType mapValType, BoogieExpr baseExpr, BoogieExpr indexExpr) { string mapName = GetMemoryMapName(decl, mapKeyType, mapValType); BoogieIdentifierExpr mapIdent = new BoogieIdentifierExpr(mapName); BoogieMapSelect mapSelectExpr = new BoogieMapSelect(mapIdent, baseExpr); mapSelectExpr = new BoogieMapSelect(mapSelectExpr, indexExpr); return(mapSelectExpr); }
private BoogieIdentifierExpr findOutermostIdentifierExpr(BoogieMapSelect select) { if (select.BaseExpr is BoogieIdentifierExpr) { return((BoogieIdentifierExpr)select.BaseExpr); } return(findOutermostIdentifierExpr((BoogieMapSelect)select.BaseExpr)); }
//return a BoogieExpression public static BoogieExpr GetMemoryMapSelectExpr(BoogieType mapKeyType, BoogieType mapValType, BoogieExpr baseExpr, BoogieExpr indexExpr) { string generateMapName = generateMemoryMapName(mapKeyType, mapValType); BoogieIdentifierExpr mapIdentifier = new BoogieIdentifierExpr(generateMapName); BoogieMapSelect mapSelectExpr = new BoogieMapSelect(mapIdentifier, baseExpr); mapSelectExpr = new BoogieMapSelect(mapSelectExpr, indexExpr); return(mapSelectExpr); }
private void GenerateGlobalProcedureAllocMany() { if (context.TranslateFlags.LazyNestedAlloc) { return; } // generate the internal one without base constructors string procName = "HavocAllocMany"; List <BoogieVariable> inParams = new List <BoogieVariable>(); List <BoogieVariable> outParams = new List <BoogieVariable>(); List <BoogieAttribute> attributes = new List <BoogieAttribute>(); if (context.TranslateFlags.GenerateInlineAttributes) { attributes.Add(new BoogieAttribute("inline", 1)); } ; BoogieProcedure procedure = new BoogieProcedure(procName, inParams, outParams, attributes); context.Program.AddDeclaration(procedure); var oldAlloc = new BoogieLocalVariable(new BoogieTypedIdent("oldAlloc", new BoogieMapType(BoogieType.Ref, BoogieType.Bool))); List <BoogieVariable> localVars = new List <BoogieVariable>() { oldAlloc }; BoogieStmtList procBody = new BoogieStmtList(); BoogieIdentifierExpr oldAllocIdentExpr = new BoogieIdentifierExpr("oldAlloc"); BoogieIdentifierExpr allocIdentExpr = new BoogieIdentifierExpr("Alloc"); // oldAlloc = Alloc procBody.AddStatement(new BoogieAssignCmd(oldAllocIdentExpr, allocIdentExpr)); // havoc Alloc procBody.AddStatement(new BoogieHavocCmd(allocIdentExpr)); // assume forall i:ref oldAlloc[i] ==> alloc[i] var qVar = QVarGenerator.NewQVar(0, 0); BoogieMapSelect allocMapSelect = new BoogieMapSelect(allocIdentExpr, qVar); BoogieMapSelect oldAllocMapSelect = new BoogieMapSelect(oldAllocIdentExpr, qVar); BoogieExpr allocAssumeExpr = new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.IMP, oldAllocMapSelect, allocMapSelect); procBody.AddStatement(new BoogieAssumeCmd(new BoogieQuantifiedExpr(true, new List <BoogieIdentifierExpr>() { qVar }, new List <BoogieType>() { BoogieType.Ref }, allocAssumeExpr))); BoogieImplementation implementation = new BoogieImplementation(procName, inParams, outParams, localVars, procBody); context.Program.AddDeclaration(implementation); }
//Generate Fresh Procedure Boogie Type and add as new reference to BoogieProgram private void BuildGlobalProcedureFresh() { // generate the internal one without base constructors string procName = "FreshRefGenerator"; List <BoogieVariable> inParams = new List <BoogieVariable>(); var outVar = new BoogieFormalParam(new BoogieTypedIdent("newRef", BoogieType.Ref)); List <BoogieVariable> outParams = new List <BoogieVariable>() { outVar }; 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(); var outVarIdentifier = new BoogieIdentifierExpr("newRef"); BoogieIdentifierExpr allocIdentExpr = new BoogieIdentifierExpr("Alloc"); // havoc tmp; procBody.AddStatement(new BoogieHavocCmd(outVarIdentifier)); // assume Alloc[tmp] == false; BoogieMapSelect allocMapSelect = new BoogieMapSelect(allocIdentExpr, outVarIdentifier); BoogieExpr allocAssumeExpr = new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.EQ, allocMapSelect, new BoogieLiteralExpr(false)); procBody.AddStatement(new BoogieAssumeCmd(allocAssumeExpr)); // Alloc[tmp] := true; procBody.AddStatement(new BoogieAssignCmd(allocMapSelect, new BoogieLiteralExpr(true))); // assume tmp != null procBody.AddStatement(new BoogieAssumeCmd( new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.NEQ, outVarIdentifier, new BoogieIdentifierExpr("null")))); BoogieImplementation implementation = new BoogieImplementation(procName, inParams, outParams, localVars, procBody); context.getProgram.AddBoogieDeclaration(implementation); }
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(TransUtils.GetDefaultInParams()); foreach (var member in structDefn.Members) { Debug.Assert(!member.TypeDescriptions.IsStruct(), "Do no handle nested structs yet!"); var formalType = TransUtils.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 (context.TranslateFlags.GenerateInlineAttributes) { attributes.Add(new BoogieAttribute("inline", 1)); } ; BoogieProcedure procedure = new BoogieProcedure(procName, inParams, outParams, attributes); context.Program.AddDeclaration(procedure); List <BoogieVariable> localVars = new List <BoogieVariable>(); BoogieStmtList procBody = new BoogieStmtList(); foreach (var member in structDefn.Members) { //f[this] = f_arg 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.Program.AddDeclaration(implementation); }
private BoogieAssumeCmd GenerateDynamicTypeAssumes(ContractDefinition contract) { BoogieExpr assumeLhs = new BoogieMapSelect(new BoogieIdentifierExpr("DType"), new BoogieIdentifierExpr("this")); List <ContractDefinition> subtypes = new List <ContractDefinition>(context.GetSubTypesOfContract(contract)); Debug.Assert(subtypes.Count > 0); BoogieExpr assumeExpr = new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.EQ, assumeLhs, new BoogieIdentifierExpr(subtypes[0].Name)); for (int i = 1; i < subtypes.Count; ++i) { BoogieExpr rhs = new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.EQ, assumeLhs, new BoogieIdentifierExpr(subtypes[i].Name)); assumeExpr = new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.OR, assumeExpr, rhs); } return(new BoogieAssumeCmd(assumeExpr)); }
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)))); }
private BoogieStmtList GenerateBodyOfFallbackDispatch(List <BoogieVariable> inParams, string fbUnknownProcName) { // Perform the payable logic to transfer balance // // Fallback(from, to, amount) // // foreach contract C that is not Lib/VeriSol // if (DT[this] == C) // if C has a fallback f // call ret := fallBack_C(this=to, sender=from, msg.value) // else // assume msg.value == 0; // else // if stubModel == callback // call fallBack_unknownType(from, to, amout) //we switch the order of first two parameters to ease callbacks // else if stubmodel == havoc // havoc all global state, except local state of this contract // else // skip //default BoogieIfCmd ifCmd = null; Debug.Assert(context.ContractDefinitions.Count >= 1, "There should be at least one contract"); List <BoogieIdentifierExpr> outParams = new List <BoogieIdentifierExpr>(); List <BoogieExpr> unkwnFnArgs = new List <BoogieExpr>() { new BoogieIdentifierExpr(inParams[0].Name), new BoogieIdentifierExpr(inParams[1].Name), new BoogieIdentifierExpr(inParams[2].Name) }; // fbUnknown(from, to, amount) BoogieStmtList noMatchCase = BoogieStmtList.MakeSingletonStmtList( new BoogieCallCmd(fbUnknownProcName, unkwnFnArgs, outParams)); foreach (var contract in context.ContractDefinitions) { if (contract.ContractKind == EnumContractKind.LIBRARY) { continue; } FunctionDefinition function = context.ContractToFallbackMap.ContainsKey(contract) ? context.ContractToFallbackMap[contract] : null; BoogieExpr lhs = new BoogieMapSelect(new BoogieIdentifierExpr("DType"), new BoogieIdentifierExpr(inParams[1].Name)); BoogieExpr rhs = new BoogieIdentifierExpr(contract.Name); BoogieExpr guard = new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.EQ, lhs, rhs); BoogieStmtList thenBody = null; if (function != null) { List <BoogieExpr> arguments = new List <BoogieExpr>() { new BoogieIdentifierExpr(inParams[1].Name), new BoogieIdentifierExpr(inParams[0].Name), new BoogieIdentifierExpr(inParams[2].Name) }; string callee = TransUtils.GetCanonicalFunctionName(function, context); // to.fallback(from, amount), thus need to switch param0 and param1 thenBody = BoogieStmtList.MakeSingletonStmtList(new BoogieCallCmd(callee, arguments, outParams)); } else { // No fallback means not payable (amount == 0) thenBody = BoogieStmtList.MakeSingletonStmtList( new BoogieAssumeCmd( new BoogieBinaryOperation( BoogieBinaryOperation.Opcode.EQ, new BoogieIdentifierExpr(inParams[2].Name), new BoogieLiteralExpr(BigInteger.Zero))) ); } BoogieStmtList elseBody = ifCmd == null ? noMatchCase : BoogieStmtList.MakeSingletonStmtList(ifCmd); ifCmd = new BoogieIfCmd(guard, thenBody, elseBody); } return(BoogieStmtList.MakeSingletonStmtList(ifCmd)); }
private BoogieStmtList GenerateBody(List <BoogieVariable> inParams) { // // foreach contract C that is not Lib/VeriSol // if (DT[this] == C) // if C has a fallback f // call ret := fallBack_C(this=to, sender=from, msg.value) // else // assume msg.value == 0; // else // call fallBack_unknownType(from, to, msg.value) BoogieIfCmd ifCmd = null; Debug.Assert(context.ContractDefinitions.Count >= 1, "There should be at least one contract"); List <BoogieExpr> arguments = new List <BoogieExpr>() { new BoogieIdentifierExpr(inParams[1].Name), new BoogieIdentifierExpr(inParams[0].Name), new BoogieIdentifierExpr(inParams[2].Name) }; List <BoogieIdentifierExpr> outParams = new List <BoogieIdentifierExpr>(); BoogieStmtList noMatchCase = BoogieStmtList.MakeSingletonStmtList( new BoogieCallCmd("Fallback_UnknownType", arguments, outParams)); foreach (var contract in context.ContractDefinitions) { if (contract.ContractKind == EnumContractKind.LIBRARY) { continue; } FunctionDefinition function = context.ContractToFallbackMap.ContainsKey(contract) ? context.ContractToFallbackMap[contract] : null; BoogieExpr lhs = new BoogieMapSelect(new BoogieIdentifierExpr("DType"), new BoogieIdentifierExpr(inParams[1].Name)); BoogieExpr rhs = new BoogieIdentifierExpr(contract.Name); BoogieExpr guard = new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.EQ, lhs, rhs); BoogieStmtList thenBody = null; if (function != null) { string callee = TransUtils.GetCanonicalFunctionName(function, context); thenBody = BoogieStmtList.MakeSingletonStmtList(new BoogieCallCmd(callee, arguments, outParams)); } else { // No fallback means not payable (amount == 0) thenBody = BoogieStmtList.MakeSingletonStmtList( new BoogieAssumeCmd( new BoogieBinaryOperation( BoogieBinaryOperation.Opcode.EQ, new BoogieIdentifierExpr(inParams[2].Name), new BoogieLiteralExpr(BigInteger.Zero))) ); } BoogieStmtList elseBody = ifCmd == null ? noMatchCase : BoogieStmtList.MakeSingletonStmtList(ifCmd); ifCmd = new BoogieIfCmd(guard, thenBody, elseBody); } return(BoogieStmtList.MakeSingletonStmtList(ifCmd)); }
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); }
public void Generate() { // Collect Global Variables. HashSet <BoogieGlobalVariable> globals = new HashSet <BoogieGlobalVariable>(); foreach (var decl in context.Program.Declarations) { if (decl is BoogieGlobalVariable) { var g = (BoogieGlobalVariable)decl; if (mustHaveShadow(g.Name)) { globals.Add(g); } } } // Generate shadow state. foreach (var g in globals) { var varName = g.TypedIdent.Name; BoogieTypedIdent shadowGlobal = new BoogieTypedIdent("__tmp__" + varName, g.TypedIdent.Type); BoogieGlobalVariable shadowGlobalDecl = new BoogieGlobalVariable(shadowGlobal); context.Program.AddDeclaration(shadowGlobalDecl); shadowGlobals.Add(varName, shadowGlobalDecl); } // Duplicate and rename methods. Dictionary <string, BoogieImplementation> proceduresWithImpl = new Dictionary <string, BoogieImplementation>(); procsWiltImplNames = proceduresWithImpl.Keys; foreach (var decl in context.Program.Declarations) { if (decl is BoogieImplementation) { var boogieImpl = ((BoogieImplementation)decl); if (proceduresInProgram.ContainsKey(boogieImpl.Name)) { proceduresWithImpl.Add(boogieImpl.Name, boogieImpl); } } } Dictionary <string, BoogieProcedure> failProcedures = new Dictionary <string, BoogieProcedure>(); foreach (var implPair in proceduresWithImpl) { BoogieProcedure proc = proceduresInProgram[implPair.Key]; if (isPublic(proc) || isConstructor(proc.Name)) { // If public maintain original definition as the wrapper. BoogieProcedure successVersion = duplicateProcedure(proc, "success", true); //BoogieImplementation successImpl = duplicateImplementation(implPair.Value, "success"); context.Program.AddDeclaration(successVersion); //context.Program.AddDeclaration(successImpl); BoogieProcedure failVersion = duplicateProcedure(proc, "fail", true); context.Program.AddDeclaration(failVersion); // Use original name of the procedure. failProcedures.Add(implPair.Key, failVersion); } else if (!isHarnessProcudure(proc.Name)) { // Otherwise reuse original definition/impl as the "successful" method. BoogieProcedure failVersion = duplicateProcedure(proc, "fail"); context.Program.AddDeclaration(failVersion); // Use original name of the procedure. failProcedures.Add(implPair.Key, failVersion); // Reuse original node proc.Name = proc.Name + "__success"; implPair.Value.Name = implPair.Value.Name + "__success"; } } // Create implementations for failing methods. foreach (var failProcedurePair in failProcedures) { string originalProcName = failProcedurePair.Key; BoogieProcedure proc = failProcedurePair.Value; var originalImpl = proceduresWithImpl[originalProcName]; if (!originalProcName.Equals("send")) { context.Program.AddDeclaration(createFailImplementation(proc.Name, originalImpl)); context.Program.AddDeclaration(createSuccessImplementation(originalProcName + "__success", originalImpl)); } else { context.Program.AddDeclaration(CreateSendFail()); context.Program.AddDeclaration(CreateSendSucess()); } // Remove original implementation for non-public methods if (!isPublic(proceduresInProgram[originalProcName]) && !isConstructor(originalProcName)) { context.Program.Declarations.Remove(originalImpl); } } foreach (var implPair in proceduresWithImpl) { // Update non-public methods in harness methods if (isHarnessProcudure(implPair.Key)) { context.Program.AddDeclaration(createSuccessImplementation(implPair.Key, implPair.Value)); context.Program.Declarations.Remove(implPair.Value); } } // Create wrappers for public methods. foreach (var proc in proceduresInProgram.Values) { if (proceduresWithImpl.ContainsKey(proc.Name) && (isPublic(proc) || isConstructor(proc.Name))) { BoogieImplementation impl = proceduresWithImpl[proc.Name]; impl.StructuredStmts = new BoogieStmtList(); impl.LocalVars = new List <BoogieVariable>(); var exceptionVarName = "__exception"; var revertGlobalName = "revert"; impl.LocalVars.Add(new BoogieLocalVariable(new BoogieTypedIdent(exceptionVarName, BoogieType.Bool))); var stmtList = impl.StructuredStmts; stmtList.AddStatement(new BoogieHavocCmd(new BoogieIdentifierExpr(exceptionVarName))); stmtList.AddStatement(new BoogieAssignCmd(new BoogieIdentifierExpr(revertGlobalName), new BoogieLiteralExpr(false))); // Call Successful version. BoogieStmtList successCallStmtList = new BoogieStmtList(); if (isPayable(proc)) { successCallStmtList.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 successCallStmtList.AddStatement(new BoogieAssumeCmd(new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.GE, balnSender, msgVal))); //balance[msg.sender] = balance[msg.sender] - msg.value successCallStmtList.AddStatement(new BoogieAssignCmd(balnSender, new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.SUB, balnSender, msgVal))); //balance[this] = balance[this] + msg.value successCallStmtList.AddStatement(new BoogieAssignCmd(balnThis, new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.ADD, balnThis, msgVal))); successCallStmtList.AddStatement(new BoogieCommentCmd("---- Logic for payable function END ")); } successCallStmtList.AddStatement(new BoogieCallCmd(impl.Name + "__success", impl.InParams.Select(inParam => (BoogieExpr) new BoogieIdentifierExpr(inParam.Name)).ToList(), impl.OutParams.Select(outParam => new BoogieIdentifierExpr(outParam.Name)).ToList())); BoogieExpr successAssumePred = new BoogieUnaryOperation(BoogieUnaryOperation.Opcode.NOT, new BoogieIdentifierExpr(revertGlobalName)); if (context.TranslateFlags.InstrumentGas) { successAssumePred = new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.AND, successAssumePred, new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.GE, new BoogieIdentifierExpr("gas"), new BoogieLiteralExpr(0))); } successCallStmtList.AddStatement(new BoogieAssumeCmd(successAssumePred)); // Call fail version. BoogieStmtList failCallStmtList = new BoogieStmtList(); // Write global variables to temps foreach (var shadowGlobalPair in shadowGlobals) { string origVarName = shadowGlobalPair.Key; string shadowName = shadowGlobalPair.Value.Name; failCallStmtList.AddStatement(new BoogieAssignCmd(new BoogieIdentifierExpr(shadowName), new BoogieIdentifierExpr(origVarName))); } if (isPayable(proc)) { failCallStmtList.AddStatement(new BoogieCommentCmd("---- Logic for payable function START ")); var balnSender = new BoogieMapSelect(new BoogieIdentifierExpr(shadowGlobals["Balance"].Name), new BoogieIdentifierExpr("msgsender_MSG")); var balnThis = new BoogieMapSelect(new BoogieIdentifierExpr(shadowGlobals["Balance"].Name), new BoogieIdentifierExpr("this")); var msgVal = new BoogieIdentifierExpr("msgvalue_MSG"); //assume Balance[msg.sender] >= msg.value failCallStmtList.AddStatement(new BoogieAssumeCmd(new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.GE, balnSender, msgVal))); //balance[msg.sender] = balance[msg.sender] - msg.value failCallStmtList.AddStatement(new BoogieAssignCmd(balnSender, new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.SUB, balnSender, msgVal))); //balance[this] = balance[this] + msg.value failCallStmtList.AddStatement(new BoogieAssignCmd(balnThis, new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.ADD, balnThis, msgVal))); failCallStmtList.AddStatement(new BoogieCommentCmd("---- Logic for payable function END ")); } failCallStmtList.AddStatement(new BoogieCallCmd(impl.Name + "__fail", impl.InParams.Select(inParam => (BoogieExpr) new BoogieIdentifierExpr(inParam.Name)).ToList(), impl.OutParams.Select(outParam => new BoogieIdentifierExpr(outParam.Name)).ToList())); BoogieExpr failAssumePred = new BoogieIdentifierExpr(revertGlobalName); if (context.TranslateFlags.InstrumentGas) { failAssumePred = new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.OR, failAssumePred, new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.LT, new BoogieIdentifierExpr("gas"), new BoogieLiteralExpr(0))); } failCallStmtList.AddStatement(new BoogieAssumeCmd(failAssumePred)); stmtList.AddStatement(new BoogieIfCmd(new BoogieIdentifierExpr(exceptionVarName), failCallStmtList, successCallStmtList)); } } }
private BoogieImplementation 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); BoogieStmtList exceptionThen = new BoogieStmtList(); exceptionThen.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 exceptionThen.AddStatement(new BoogieAssignCmd(exBalFrom, new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.SUB, exBalFrom, exMsgVal))); //balance[this] = balance[this] + msg.value exceptionThen.AddStatement(new BoogieAssignCmd(exBalTo, new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.ADD, exBalTo, exMsgVal))); exceptionThen.AddStatement(new BoogieCommentCmd("---- Logic for payable function END ")); var callFailDispatch = new BoogieCallCmd("FallbackDispatch__fail", new List <BoogieExpr>() { fromId, toId, amtId }, null); exceptionThen.AddStatement(callFailDispatch); exceptionCase.AddStatement(new BoogieIfCmd(checkTmpBalGuard, exceptionThen, 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(); successCaseStmts.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 successCaseStmts.AddStatement(new BoogieAssignCmd(balFrom, new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.SUB, balFrom, msgVal))); //balance[this] = balance[this] + msg.value successCaseStmts.AddStatement(new BoogieAssignCmd(balTo, new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.ADD, balTo, msgVal))); successCaseStmts.AddStatement(new BoogieCommentCmd("---- Logic for payable function END ")); 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)); }
private BoogieStmtList CreateBodyOfUnknownFallback(List <BoogieVariable> fbLocalVars, List <BoogieVariable> inParams) { Debug.Assert(context.TranslateFlags.ModelStubsAsSkips() || context.TranslateFlags.ModelStubsAsCallbacks() || context.TranslateFlags.ModelStubsAsMultipleCallbacks(), "CreateBodyOfUnknownFallback called in unexpected context"); var procBody = new BoogieStmtList(); /*procBody.AddStatement(new BoogieCommentCmd("---- Logic for payable function START ")); * var balnSender = new BoogieMapSelect(new BoogieIdentifierExpr("Balance"), new BoogieIdentifierExpr(inParams[0].Name)); * var balnThis = new BoogieMapSelect(new BoogieIdentifierExpr("Balance"), new BoogieIdentifierExpr(inParams[1].Name)); * var msgVal = new BoogieIdentifierExpr("amount"); * //assume Balance[msg.sender] >= msg.value * procBody.AddStatement(new BoogieAssumeCmd(new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.GE, balnSender, msgVal))); * //balance[from] = balance[from] - msg.value * procBody.AddStatement(new BoogieAssignCmd(balnSender, new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.SUB, balnSender, msgVal))); * //balance[to] = balance[to] + msg.value * procBody.AddStatement(new BoogieAssignCmd(balnThis, new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.ADD, balnThis, msgVal))); * procBody.AddStatement(new BoogieCommentCmd("---- Logic for payable function END "));*/ BoogieStmtList body = procBody; if (context.TranslateFlags.ModelStubsAsCallbacks() || context.TranslateFlags.ModelStubsAsMultipleCallbacks()) { if (context.TranslateFlags.ModelReverts) { BoogieBinaryOperation revertGuard = new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.EQ, new BoogieIdentifierExpr("choice"), new BoogieLiteralExpr(BigInteger.Zero)); BoogieStmtList thenBody = new BoogieStmtList(); thenBody.AddStatement(new BoogieAssignCmd(new BoogieIdentifierExpr("revert"), new BoogieLiteralExpr(true))); thenBody.AddStatement(new BoogieReturnCmd()); BoogieIfCmd earlyExitCmd = new BoogieIfCmd(revertGuard, thenBody, null); body.AddStatement(earlyExitCmd); } if (context.TranslateFlags.InstrumentGas) { BoogieBinaryOperation gasGuard = new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.LT, new BoogieIdentifierExpr("gas"), new BoogieLiteralExpr(TranslatorContext.TX_GAS_COST)); BoogieIfCmd earlyExitCmd = new BoogieIfCmd(gasGuard, BoogieStmtList.MakeSingletonStmtList(new BoogieReturnCmd()), null); body.AddStatement(earlyExitCmd); } } if (context.TranslateFlags.ModelStubsAsMultipleCallbacks()) { fbLocalVars.Add(new BoogieLocalVariable(new BoogieTypedIdent("iterate", BoogieType.Bool))); BoogieBinaryOperation gasGuard = new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.GE, new BoogieIdentifierExpr("gas"), new BoogieLiteralExpr(TranslatorContext.TX_GAS_COST)); BoogieBinaryOperation guard = new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.AND, new BoogieIdentifierExpr("iterate"), gasGuard); BoogieStmtList loopBody = new BoogieStmtList(); procBody.AddStatement(new BoogieWhileCmd(guard, loopBody, new List <BoogieExpr>())); body = loopBody; } if (context.TranslateFlags.ModelStubsAsCallbacks() || context.TranslateFlags.ModelStubsAsMultipleCallbacks()) { List <BoogieVariable> localVars = TransUtils.CollectLocalVars(context.ContractDefinitions.ToList(), context); fbLocalVars.AddRange(localVars); // if (*) fn1(from, *, ...) // we only redirect the calling contract, but the msg.sender need not be to, as it can call into anohter contract that calls // into from if (context.TranslateFlags.ModelStubsAsMultipleCallbacks()) { body.AppendStmtList(HavocLocals(localVars)); body.AddStatement(new BoogieHavocCmd(new BoogieIdentifierExpr("iterate"))); } BoogieIfCmd typeIf = null; foreach (ContractDefinition curDef in context.ContractDefinitions.ToList()) { BoogieIfCmd reentrantCalls = TransUtils.GenerateChoiceBlock(new List <ContractDefinition>() { curDef }, context, false, Tuple.Create(inParams[0].Name, inParams[1].Name)); if (reentrantCalls == null) { continue; } BoogieExpr dtype = new BoogieMapSelect(new BoogieIdentifierExpr("DType"), new BoogieIdentifierExpr(inParams[0].Name)); BoogieBinaryOperation guard = new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.EQ, dtype, new BoogieIdentifierExpr(curDef.Name)); typeIf = new BoogieIfCmd(guard, BoogieStmtList.MakeSingletonStmtList(reentrantCalls), typeIf == null ? null : BoogieStmtList.MakeSingletonStmtList(typeIf)); } /*BoogieIfCmd ifCmd = null; * * if (context.TranslateFlags.ModelReverts) * { * BoogieExpr guard = new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.EQ, * new BoogieIdentifierExpr("choice"), * new BoogieLiteralExpr(choices.Item2 + 1)); * * BoogieAssignCmd assign = new BoogieAssignCmd(new BoogieIdentifierExpr("revert"), new BoogieLiteralExpr(true)); * ifCmd = new BoogieIfCmd(guard, BoogieStmtList.MakeSingletonStmtList(assign), BoogieStmtList.MakeSingletonStmtList(choices.Item1)); * } * else * { * ifCmd = choices.Item1; * }*/ body.AddStatement(typeIf); } return(procBody); }
private List <BoogieAxiom> GenerateVeriSolSumAxioms() { // axiom(forall m:[Ref]int :: (exists _a: Ref::m[_a] != 0) || _SumMapping_VeriSol(m) == 0); var qVar1 = QVarGenerator.NewQVar(0, 0); var qVar2 = QVarGenerator.NewQVar(0, 1); var ma = new BoogieMapSelect(qVar1, qVar2); var maEq0 = new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.NEQ, ma, new BoogieLiteralExpr(System.Numerics.BigInteger.Zero)); var existsMaNeq0 = new BoogieQuantifiedExpr(false, new List <BoogieIdentifierExpr>() { qVar2 }, new List <BoogieType>() { BoogieType.Ref }, maEq0, null); var sumM = new BoogieFuncCallExpr("_SumMapping_VeriSol", new List <BoogieExpr>() { qVar1 }); var sumMEq0 = new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.EQ, sumM, new BoogieLiteralExpr(System.Numerics.BigInteger.Zero)); var maEq0SumEq0 = new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.OR, existsMaNeq0, sumMEq0); var axiom1 = new BoogieQuantifiedExpr(true, new List <BoogieIdentifierExpr>() { qVar1 }, new List <BoogieType>() { new BoogieMapType(BoogieType.Ref, BoogieType.Int) }, maEq0SumEq0, null); // axiom(forall m:[Ref]int, _a: Ref, _b: int :: _SumMapping_VeriSol(m[_a:= _b]) == _SumMapping_VeriSol(m) - m[_a] + _b); var qVar3 = QVarGenerator.NewQVar(0, 2); var subExpr = new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.SUB, sumM, ma); var addExpr = new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.ADD, subExpr, qVar3); var updExpr = new BoogieMapUpdate(qVar1, qVar2, qVar3); var sumUpdExpr = new BoogieFuncCallExpr("_SumMapping_VeriSol", new List <BoogieExpr>() { updExpr }); var sumUpdEqExpr = new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.EQ, sumUpdExpr, addExpr); var axiom2 = new BoogieQuantifiedExpr(true, new List <BoogieIdentifierExpr>() { qVar1, qVar2, qVar3 }, new List <BoogieType>() { new BoogieMapType(BoogieType.Ref, BoogieType.Int), BoogieType.Ref, BoogieType.Int }, sumUpdEqExpr, null); return(new List <BoogieAxiom>() { new BoogieAxiom(axiom1), new BoogieAxiom(axiom2) }); }
private BoogieExpr dupAndReplaceExpr(BoogieExpr expr, bool isFail, bool inHarness) { List <BoogieExpr> dupAndReplaceExprList(List <BoogieExpr> exprs) { return(exprs.Select(e => dupAndReplaceExpr(e, isFail, inHarness)).ToList()); } if (expr is BoogieIdentifierExpr) { string idName = ((BoogieIdentifierExpr)expr).Name; if (isFail && shadowGlobals.ContainsKey(idName)) { return(new BoogieIdentifierExpr(shadowGlobals[idName].Name)); } return(expr); } if (expr is BoogieMapSelect) { BoogieMapSelect selectExpr = (BoogieMapSelect)expr; return(new BoogieMapSelect(dupAndReplaceExpr(selectExpr.BaseExpr, isFail, inHarness), dupAndReplaceExprList(selectExpr.Arguments))); } if (expr is BoogieMapUpdate) { BoogieMapUpdate updateExpr = (BoogieMapUpdate)expr; return(new BoogieMapUpdate(dupAndReplaceExpr(updateExpr.BaseExpr, isFail, inHarness), dupAndReplaceExprList(updateExpr.Arguments), dupAndReplaceExpr(updateExpr.Value, isFail, inHarness))); } if (expr is BoogieUnaryOperation) { BoogieUnaryOperation unaryOperation = (BoogieUnaryOperation)expr; return(new BoogieUnaryOperation(unaryOperation.Op, dupAndReplaceExpr(unaryOperation.Expr, isFail, inHarness))); } if (expr is BoogieBinaryOperation) { BoogieBinaryOperation binOperation = (BoogieBinaryOperation)expr; return(new BoogieBinaryOperation(binOperation.Op, dupAndReplaceExpr(binOperation.Lhs, isFail, inHarness), dupAndReplaceExpr(binOperation.Rhs, isFail, inHarness))); } if (expr is BoogieITE) { BoogieITE iteExpr = (BoogieITE)expr; return(new BoogieITE(dupAndReplaceExpr(iteExpr.Guard, isFail, inHarness), dupAndReplaceExpr(iteExpr.ThenExpr, isFail, inHarness), dupAndReplaceExpr(iteExpr.ElseExpr, isFail, inHarness))); } if (expr is BoogieQuantifiedExpr) { BoogieQuantifiedExpr quantifiedExpr = (BoogieQuantifiedExpr)expr; return(new BoogieQuantifiedExpr(quantifiedExpr.IsForall, quantifiedExpr.QVars, quantifiedExpr.QVarTypes, dupAndReplaceExpr(quantifiedExpr.BodyExpr, isFail, inHarness), quantifiedExpr.Trigger)); } if (expr is BoogieFuncCallExpr) { BoogieFuncCallExpr callExpr = (BoogieFuncCallExpr)expr; string calledFun = callExpr.Function; // TODO: handle this properly. // if (!isHarnessProcudure(calledFun) && procsWiltImplNames.Contains(calledFun)) // { // if (!inHarness || (!isConstructor(calledFun) && !isPublic(proceduresInProgram[calledFun]))) // calledFun = calledFun + (isFail ? "__fail" : "__success"); // } return(new BoogieFuncCallExpr(calledFun, dupAndReplaceExprList(callExpr.Arguments))); } if (expr is BoogieTupleExpr) { BoogieTupleExpr tupleExpr = (BoogieTupleExpr)expr; return(new BoogieTupleExpr(dupAndReplaceExprList(tupleExpr.Arguments))); } return(expr); }
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)); }