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); }
private void GenerateBoogieHarnessForContract(ContractDefinition contract, Dictionary <int, BoogieExpr> houdiniVarMap) { string harnessName = "BoogieEntry_" + contract.Name; List <BoogieVariable> inParams = new List <BoogieVariable>(); List <BoogieVariable> outParams = new List <BoogieVariable>(); BoogieProcedure harness = new BoogieProcedure(harnessName, inParams, outParams); context.Program.AddDeclaration(harness); List <BoogieVariable> localVars = TransUtils.CollectLocalVars(new List <ContractDefinition>() { contract }, context); BoogieStmtList harnessBody = new BoogieStmtList(); harnessBody.AddStatement(GenerateDynamicTypeAssumes(contract)); GenerateConstructorCall(contract).ForEach(x => harnessBody.AddStatement(x)); if (context.TranslateFlags.ModelReverts) { BoogieExpr assumePred = new BoogieUnaryOperation(BoogieUnaryOperation.Opcode.NOT, new BoogieIdentifierExpr("revert")); if (context.TranslateFlags.InstrumentGas) { assumePred = new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.AND, assumePred, new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.GE, new BoogieIdentifierExpr("gas"), new BoogieLiteralExpr(0))); } harnessBody.AddStatement(new BoogieAssumeCmd(assumePred)); } harnessBody.AddStatement(GenerateWhileLoop(contract, houdiniVarMap, localVars)); BoogieImplementation harnessImpl = new BoogieImplementation(harnessName, inParams, outParams, localVars, harnessBody); context.Program.AddDeclaration(harnessImpl); }
private void GenerateCorralChoiceProcForContract(ContractDefinition contract) { string procName = "CorralChoice_" + contract.Name; List <BoogieVariable> inParams = new List <BoogieVariable>() { new BoogieFormalParam(new BoogieTypedIdent("this", BoogieType.Ref)), }; List <BoogieVariable> outParams = new List <BoogieVariable>(); BoogieProcedure harness = new BoogieProcedure(procName, inParams, outParams); context.Program.AddDeclaration(harness); List <BoogieVariable> localVars = RemoveThisFromVariables(TransUtils.CollectLocalVars(new List <ContractDefinition>() { contract }, context)); BoogieStmtList procBody = GenerateHavocBlock(contract, localVars); procBody.AddStatement(TransUtils.GenerateChoiceBlock(new List <ContractDefinition>() { contract }, context)); BoogieImplementation procImpl = new BoogieImplementation(procName, inParams, outParams, localVars, procBody); context.Program.AddDeclaration(procImpl); }
private List <BoogieVariable> CollectLocalVars(ContractDefinition contract) { List <ContractDefinition> contracts = new List <ContractDefinition>() { contract }; if (context.TranslateFlags.TxnsOnFields) { HashSet <VariableDeclaration> contractFields = context.GetStateVarsByContract(contract); foreach (VariableDeclaration contractField in contractFields) { if (contractField.TypeDescriptions.IsContract() && contractField.TypeName is UserDefinedTypeName) { String fieldContractName = contractField.TypeName.ToString(); ContractDefinition fieldDef = context.GetContractByName(fieldContractName); contracts.Add(fieldDef); } } } return(TransUtils.CollectLocalVars(contracts, context)); }
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); }