private void GenerateGlobalVariables() { BoogieTypedIdent dtypeId = new BoogieTypedIdent("DType", new BoogieMapType(BoogieType.Ref, contractType)); BoogieGlobalVariable dtype = new BoogieGlobalVariable(dtypeId); context.Program.AddDeclaration(dtype); BoogieTypedIdent allocId = new BoogieTypedIdent("Alloc", new BoogieMapType(BoogieType.Ref, BoogieType.Bool)); BoogieGlobalVariable alloc = new BoogieGlobalVariable(allocId); context.Program.AddDeclaration(alloc); BoogieTypedIdent addrBalanceId = new BoogieTypedIdent("balance_ADDR", new BoogieMapType(BoogieType.Ref, BoogieType.Int)); BoogieGlobalVariable addrBalance = new BoogieGlobalVariable(addrBalanceId); context.Program.AddDeclaration(addrBalance); // generate global variables for each array/mapping type to model memory GenerateMemoryVariables(); BoogieMapType type = new BoogieMapType(BoogieType.Ref, BoogieType.Int); BoogieTypedIdent arrayLengthId = new BoogieTypedIdent("Length", type); BoogieGlobalVariable arrayLength = new BoogieGlobalVariable(arrayLengthId); context.Program.AddDeclaration(arrayLength); if (context.TranslateFlags.ModelReverts) { BoogieTypedIdent revertId = new BoogieTypedIdent("revert", BoogieType.Bool); BoogieGlobalVariable revert = new BoogieGlobalVariable(revertId); context.Program.AddDeclaration(revert); } }
private void GenerateGlobalVariables() { BoogieTypedIdent balanceId = new BoogieTypedIdent("Balance", new BoogieMapType(BoogieType.Ref, BoogieType.Int)); BoogieGlobalVariable balanceVar = new BoogieGlobalVariable(balanceId); context.Program.AddDeclaration(balanceVar); BoogieTypedIdent dtypeId = new BoogieTypedIdent("DType", new BoogieMapType(BoogieType.Ref, contractType)); BoogieGlobalVariable dtype = new BoogieGlobalVariable(dtypeId); context.Program.AddDeclaration(dtype); BoogieTypedIdent allocId = new BoogieTypedIdent("Alloc", new BoogieMapType(BoogieType.Ref, BoogieType.Bool)); BoogieGlobalVariable alloc = new BoogieGlobalVariable(allocId); context.Program.AddDeclaration(alloc); BoogieTypedIdent addrBalanceId = new BoogieTypedIdent("balance_ADDR", new BoogieMapType(BoogieType.Ref, BoogieType.Int)); BoogieGlobalVariable addrBalance = new BoogieGlobalVariable(addrBalanceId); context.Program.AddDeclaration(addrBalance); // generate global variables for each array/mapping type to model memory GenerateMemoryVariables(); BoogieMapType type = new BoogieMapType(BoogieType.Ref, BoogieType.Int); BoogieTypedIdent arrayLengthId = new BoogieTypedIdent("Length", type); BoogieGlobalVariable arrayLength = new BoogieGlobalVariable(arrayLengthId); context.Program.AddDeclaration(arrayLength); if (context.TranslateFlags.ModelReverts) { BoogieTypedIdent revertId = new BoogieTypedIdent("revert", BoogieType.Bool); BoogieGlobalVariable revert = new BoogieGlobalVariable(revertId); context.Program.AddDeclaration(revert); } if (context.TranslateFlags.InstrumentGas) { BoogieTypedIdent gasId = new BoogieTypedIdent("gas", BoogieType.Int); BoogieGlobalVariable gas = new BoogieGlobalVariable(gasId); context.Program.AddDeclaration(gas); } if (context.TranslateFlags.InstrumentSums) { BoogieTypedIdent sumId = new BoogieTypedIdent("sum", new BoogieMapType(BoogieType.Ref, BoogieType.Int)); BoogieGlobalVariable sum = new BoogieGlobalVariable(sumId); context.Program.AddDeclaration(sum); } // Solidity-specific vars BoogieTypedIdent nowVar = new BoogieTypedIdent("now", BoogieType.Int); context.Program.AddDeclaration(new BoogieGlobalVariable(nowVar)); }
//Function to build standard global variables for Boogie expressions set. private void buildGlobalVariables() { BoogieTypedIdent balanceId = new BoogieTypedIdent("Balance", new BoogieMapType(BoogieType.Ref, BoogieType.Int)); BoogieGlobalVariable balanceVar = new BoogieGlobalVariable(balanceId); context.getProgram.AddBoogieDeclaration(balanceVar); BoogieTypedIdent dtypeId = new BoogieTypedIdent("DType", new BoogieMapType(BoogieType.Ref, new BoogieCtorType("ContractName"))); BoogieGlobalVariable dtype = new BoogieGlobalVariable(dtypeId); context.getProgram.AddBoogieDeclaration(dtype); BoogieTypedIdent addrBalanceId = new BoogieTypedIdent("balance_ADDR", new BoogieMapType(BoogieType.Ref, BoogieType.Int)); BoogieGlobalVariable addrBalance = new BoogieGlobalVariable(addrBalanceId); context.getProgram.AddBoogieDeclaration(addrBalance); BoogieTypedIdent allocId = new BoogieTypedIdent("Alloc", new BoogieMapType(BoogieType.Ref, BoogieType.Bool)); BoogieGlobalVariable alloc = new BoogieGlobalVariable(allocId); context.getProgram.AddBoogieDeclaration(alloc); // generate global variables for each array/mapping type to model memory ConstructMemoryVariables(); BoogieMapType type = new BoogieMapType(BoogieType.Ref, BoogieType.Int); BoogieTypedIdent arrayLengthId = new BoogieTypedIdent("Length", type); BoogieGlobalVariable arrayLength = new BoogieGlobalVariable(arrayLengthId); context.getProgram.AddBoogieDeclaration(arrayLength); if (context.TranslateFlags.ModelReverts == true) { BoogieTypedIdent revertId = new BoogieTypedIdent("revert", BoogieType.Bool); BoogieGlobalVariable revert = new BoogieGlobalVariable(revertId); context.getProgram.AddBoogieDeclaration(revert);// } if (Flags_HelperClass.InstrumentGas == true) { BoogieTypedIdent gasId = new BoogieTypedIdent("gas", BoogieType.Int); BoogieGlobalVariable gas = new BoogieGlobalVariable(gasId); context.getProgram.AddBoogieDeclaration(gas); } }
private void GenerateConstants() { BoogieConstant nullConstant = new BoogieConstant(new BoogieTypedIdent("null", BoogieType.Ref), true); context.Program.AddDeclaration(nullConstant); // constants for contract names BoogieCtorType tnameType = new BoogieCtorType("ContractName"); foreach (ContractDefinition contract in context.ContractDefinitions) { BoogieTypedIdent typedIdent = new BoogieTypedIdent(contract.Name, tnameType); BoogieConstant contractNameConstant = new BoogieConstant(typedIdent, true); context.Program.AddDeclaration(contractNameConstant); foreach (var node in contract.Nodes) { if (node is StructDefinition structDefn) { var structTypedIdent = new BoogieTypedIdent(structDefn.CanonicalName, tnameType); context.Program.AddDeclaration(new BoogieConstant(structTypedIdent, true)); } } } }
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]; context.Program.AddDeclaration(createFailImplementation(proc.Name, originalImpl)); context.Program.AddDeclaration(createSuccessImplementation(originalProcName + "__success", originalImpl)); // 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(); 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())); successCallStmtList.AddStatement(new BoogieAssumeCmd(new BoogieUnaryOperation(BoogieUnaryOperation.Opcode.NOT, new BoogieIdentifierExpr(revertGlobalName)))); // 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))); } 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())); failCallStmtList.AddStatement(new BoogieAssumeCmd(new BoogieIdentifierExpr(revertGlobalName))); stmtList.AddStatement(new BoogieIfCmd(new BoogieIdentifierExpr(exceptionVarName), failCallStmtList, successCallStmtList)); } } }