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(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 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)))); }
// generate a non-deterministic choice block to call every public visible functions except constructors private BoogieIfCmd GenerateChoiceBlock(ContractDefinition contract) { HashSet <FunctionDefinition> funcDefs = context.GetVisibleFunctionsByContract(contract); List <FunctionDefinition> publicFuncDefs = new List <FunctionDefinition>(); foreach (FunctionDefinition funcDef in funcDefs) { if (funcDef.IsConstructorForContract(contract.Name)) { continue; } if (funcDef.Visibility == EnumVisibility.PUBLIC || funcDef.Visibility == EnumVisibility.EXTERNAL) { publicFuncDefs.Add(funcDef); } } BoogieIfCmd ifCmd = null; for (int i = publicFuncDefs.Count - 1; i >= 0; --i) { BoogieExpr guard = new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.EQ, new BoogieIdentifierExpr("choice"), new BoogieLiteralExpr(i + 1)); BoogieStmtList thenBody = new BoogieStmtList(); FunctionDefinition funcDef = publicFuncDefs[i]; string callee = TransUtils.GetCanonicalFunctionName(funcDef, context); List <BoogieExpr> inputs = new List <BoogieExpr>() { new BoogieIdentifierExpr("this"), new BoogieIdentifierExpr("msgsender_MSG"), new BoogieIdentifierExpr("msgvalue_MSG"), }; foreach (VariableDeclaration param in funcDef.Parameters.Parameters) { string name = TransUtils.GetCanonicalLocalVariableName(param); 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" + funcDef.Name; string name = $"__ret_{retParamCount++}_" + funcDef.Name; if (!string.IsNullOrEmpty(param.Name)) { name = TransUtils.GetCanonicalLocalVariableName(param); } outputs.Add(new BoogieIdentifierExpr(name)); } 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); }
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); var callFailDispatch = new BoogieCallCmd("FallbackDispatch__fail", new List <BoogieExpr>() { fromId, toId, amtId }, null); exceptionCase.AddStatement(new BoogieIfCmd(checkTmpBalGuard, BoogieStmtList.MakeSingletonStmtList(callFailDispatch), 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(); 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)); }
/// <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, TranslatorContext 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.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 (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) : new BoogieIdentifierExpr("this"), callBackTarget != null ? new BoogieIdentifierExpr(callBackTarget.Item2) : new BoogieIdentifierExpr("msgsender_MSG"), new BoogieIdentifierExpr("msgvalue_MSG"), }; foreach (VariableDeclaration param in funcDef.Parameters.Parameters) { string name = TransUtils.GetCanonicalLocalVariableName(param); 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 = TransUtils.GetCanonicalLocalVariableName(param); } outputs.Add(new BoogieIdentifierExpr(name)); } if (context.TranslateFlags.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); }
private BoogieImplementation CreateSendFail() { // send__fail(from: Ref, to: Ref, amt: uint) returns (success: boolean) // { // var __exception: bool; // havoc __exception; // // if(__exception) // { // //save current temps // if ((__tmp__Balance[from]) >= (amt)) { // call FallbackDispatch__fail(from, to, amt); // } // // success := false; // assume(__revert); // // // restore old temps // revert := false; // } // else { // if ((__tmp__Balance[from]) >= (amt)) { // call FallbackDispatch__fail(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"); var body = new BoogieStmtList(); body.AddStatement(new BoogieHavocCmd(exceptionId)); var checkTmpBalGuard = new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.GE, new BoogieMapSelect(new BoogieIdentifierExpr(shadowGlobals["Balance"].Name), fromId), amtId); var callFailDispatch = new BoogieCallCmd("FallbackDispatch__fail", new List <BoogieExpr>() { fromId, toId, amtId }, null); var exceptionCase = new BoogieStmtList(); foreach (var shadowGlobalPair in shadowGlobals) { var shadowName = shadowGlobalPair.Value.Name; var tmpLocalName = "__snap_" + shadowName; locals.Add(new BoogieLocalVariable(new BoogieTypedIdent(tmpLocalName, shadowGlobalPair.Value.TypedIdent.Type))); exceptionCase.AddStatement(new BoogieAssignCmd(new BoogieIdentifierExpr(tmpLocalName), new BoogieIdentifierExpr(shadowName))); } BoogieStmtList exStmtList = new BoogieStmtList(); exStmtList.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 exStmtList.AddStatement(new BoogieAssignCmd(exBalFrom, new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.SUB, exBalFrom, exMsgVal))); //balance[this] = balance[this] + msg.value exStmtList.AddStatement(new BoogieAssignCmd(exBalTo, new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.ADD, exBalTo, exMsgVal))); exStmtList.AddStatement(new BoogieCommentCmd("---- Logic for payable function END ")); exStmtList.AddStatement(callFailDispatch); exceptionCase.AddStatement(new BoogieIfCmd(checkTmpBalGuard, exStmtList, 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)); foreach (var shadowGlobalPair in shadowGlobals) { var shadowName = shadowGlobalPair.Value.Name; var tmpLocalName = "__snap_" + shadowName; exceptionCase.AddStatement(new BoogieAssignCmd(new BoogieIdentifierExpr(shadowName), new BoogieIdentifierExpr(tmpLocalName))); } exceptionCase.AddStatement(new BoogieAssignCmd(revertId, new BoogieLiteralExpr(false))); var successCase = new BoogieStmtList(); var successDispatchCall = new BoogieStmtList(); successDispatchCall.AddStatement(new BoogieCommentCmd("---- Logic for payable function START ")); //balance[msg.sender] = balance[msg.sender] - msg.value successDispatchCall.AddStatement(new BoogieAssignCmd(exBalFrom, new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.SUB, exBalFrom, exMsgVal))); //balance[this] = balance[this] + msg.value successDispatchCall.AddStatement(new BoogieAssignCmd(exBalTo, new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.ADD, exBalTo, exMsgVal))); successDispatchCall.AddStatement(new BoogieCommentCmd("---- Logic for payable function END ")); successDispatchCall.AddStatement(callFailDispatch); successDispatchCall.AddStatement(new BoogieAssignCmd(successId, new BoogieLiteralExpr(true))); successCase.AddStatement(new BoogieIfCmd(checkTmpBalGuard, successDispatchCall, 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__fail", inParams, outParms, locals, body)); }
public void PerformModSetAnalysis() { BoogieProgram prog = context.Program; List <BoogieImplementation> impls = new List <BoogieImplementation>(); Dictionary <string, BoogieGlobalVariable> globals = new Dictionary <string, BoogieGlobalVariable>(); Dictionary <string, BoogieProcedure> procedures = new Dictionary <string, BoogieProcedure>(); foreach (var decl in prog.Declarations) { if (decl is BoogieImplementation) { impls.Add((BoogieImplementation)decl); } else if (decl is BoogieProcedure) { BoogieProcedure proc = (BoogieProcedure)decl; procedures.Add(proc.Name, proc); } else if (decl is BoogieGlobalVariable) { var globalVar = (BoogieGlobalVariable)decl; globals.Add(globalVar.Name, globalVar); } } calculateFlattenCmdLists(impls); foreach (var impl in impls) { HashSet <BoogieGlobalVariable> modSet = new HashSet <BoogieGlobalVariable>(); modSets.Add(impl.Name, modSet); foreach (var stmt in flattenedCmdLists[impl.Name]) { switch (stmt) { case BoogieHavocCmd havoc: foreach (var identifier in havoc.Vars) { var idName = identifier.Name; if (globals.ContainsKey(idName)) { modSet.Add(globals[idName]); } } break; case BoogieAssignCmd assign: switch (assign.Lhs) { case BoogieIdentifierExpr idExpr: { var idName = idExpr.Name; if (globals.ContainsKey(idName)) { modSet.Add(globals[idName]); } break; } case BoogieMapSelect mapSelect: { var idName = findOutermostIdentifierExpr(mapSelect).Name; if (globals.ContainsKey(idName)) { modSet.Add(globals[idName]); } break; } default: throw new RuntimeWrappedException("unexpected LHS"); } break; } } } bool modSetChange; do { modSetChange = false; foreach (var impl in impls) { HashSet <BoogieGlobalVariable> currModSet = modSets[impl.Name]; int oldSize = currModSet.Count; foreach (var stmt in flattenedCmdLists[impl.Name]) { if (stmt is BoogieCallCmd) { BoogieCallCmd callCmd = (BoogieCallCmd)stmt; if (modSets.ContainsKey(callCmd.Callee)) { currModSet.UnionWith(modSets[callCmd.Callee]); } } } if (currModSet.Count > oldSize) { modSetChange = true; } } } while (modSetChange); foreach (var impl in impls) { procedures[impl.Name].ModSet = modSets[impl.Name].ToList(); } }
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)); }