diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index b51f7805bdf9..c622c4beecf5 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -111,6 +111,8 @@ type BaseApp struct { //nolint: maligned // abciListeners for hooking into the ABCI message processing of the BaseApp // and exposing the requests and responses to external consumers abciListeners []ABCIListener + + LastTxManager LastMsgMarkerContainer } type appStore struct { @@ -742,8 +744,12 @@ func (app *BaseApp) runMsgs(ctx sdk.Context, msgs []sdk.Msg, mode runTxMode) (*s Data: make([]*sdk.MsgData, 0, len(msgs)), } + // Set the marker as false - future messages may toggle this flag + app.LastTxManager.SetMarker(false) + // NOTE: GasWanted is determined by the AnteHandler and GasUsed by the GasMeter. for i, msg := range msgs { + // skip actual execution for (Re)CheckTx mode if mode == runTxModeCheck || mode == runTxModeReCheck { break @@ -755,6 +761,10 @@ func (app *BaseApp) runMsgs(ctx sdk.Context, msgs []sdk.Msg, mode runTxMode) (*s err error ) + if app.LastTxManager.GetMarker() { + return nil, sdkerrors.Wrapf(sdkerrors.ErrLastTx, "message was attempted but last message was marked by a contract; message index: %d", i) + } + if handler := app.msgServiceRouter.Handler(msg); handler != nil { // ADR 031 request type routing msgResult, err = handler(ctx, msg) diff --git a/baseapp/last_message_marker.go b/baseapp/last_message_marker.go new file mode 100644 index 000000000000..745962cde568 --- /dev/null +++ b/baseapp/last_message_marker.go @@ -0,0 +1,13 @@ +package baseapp + +type LastMsgMarkerContainer struct { + marker bool +} + +func (mng *LastMsgMarkerContainer) SetMarker(value bool) { + mng.marker = value +} + +func (mng *LastMsgMarkerContainer) GetMarker() bool { + return mng.marker +} diff --git a/types/errors/errors.go b/types/errors/errors.go index 2c211f93d68f..a6ed9d1c8f09 100644 --- a/types/errors/errors.go +++ b/types/errors/errors.go @@ -147,6 +147,9 @@ var ( // ErrPanic is only set when we recover from a panic, so we know to // redact potentially sensitive system info ErrPanic = Register(UndefinedCodespace, 111222, "panic") + + // ErrLastTx defines an error occurred if we tried to execute another msg after the last one was set + ErrLastTx = Register(RootCodespace, 40404, "Cannot send messages after last tx marker was set") ) // Register returns an error instance that should be used as the base for