From 9b31d202eb4d60a50e76ff104e98d74671e01656 Mon Sep 17 00:00:00 2001
From: Robert Zaremba <robert@zaremba.ch>
Date: Wed, 1 Dec 2021 11:03:50 +0100
Subject: [PATCH 1/6] chore: cleanup go mod and regenerate proto files (#10645)

## Description

Some tests are still failing, eg: https://github.com/cosmos/cosmos-sdk/runs/4350294236?check_suite_focus=true
With message:

> go: updates to go.mod needed, disabled by -mod=readonly; to update it:
>	go mod tidy
> test return:  1

Also, when using the latest version it cleanups the go mod.

Ref: https://github.com/cosmos/cosmos-sdk/pull/10616

---

### Author Checklist

*All items are required. Please add a note to the item if the item is not applicable and
please add links to any relevant follow up issues.*

I have...

- [x] included the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title
- [x] added `!` to the type prefix if API or client breaking change
- [ ] targeted the correct branch (see [PR Targeting](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#pr-targeting))
- [ ] provided a link to the relevant issue or specification
- [ ] followed the guidelines for [building modules](https://github.com/cosmos/cosmos-sdk/blob/master/docs/building-modules)
- [ ] included the necessary unit and integration [tests](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#testing)
- [ ] added a changelog entry to `CHANGELOG.md`
- [ ] included comments for [documenting Go code](https://blog.golang.org/godoc)
- [ ] updated the relevant documentation or specification
- [ ] reviewed "Files changed" and left comments if necessary
- [ ] confirmed all CI checks have passed

### Reviewers Checklist

*All items are required. Please add a note if the item is not applicable and please add
your handle next to the items reviewed if you only reviewed selected items.*

I have...

- [ ] confirmed the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title
- [ ] confirmed `!` in the type prefix if API or client breaking change
- [ ] confirmed all author checklist items have been addressed
- [ ] reviewed state machine logic
- [ ] reviewed API design and naming
- [ ] reviewed documentation is accurate
- [ ] reviewed tests and test coverage
- [ ] manually tested (if applicable)
---
 docs/core/proto-docs.md | 3 +++
 types/abci.pb.go        | 2 +-
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/docs/core/proto-docs.md b/docs/core/proto-docs.md
index 23241e26e49f..5d17dd708a68 100644
--- a/docs/core/proto-docs.md
+++ b/docs/core/proto-docs.md
@@ -2418,6 +2418,9 @@ tags are stringified and the log is JSON decoded.
 | `gas_used` | [int64](#int64) |  | Amount of gas consumed by transaction. |
 | `tx` | [google.protobuf.Any](#google.protobuf.Any) |  | The request transaction bytes. |
 | `timestamp` | [string](#string) |  | Time of the previous block. For heights > 1, it's the weighted median of the timestamps of the valid votes in the block.LastCommit. For height == 1, it's genesis time. |
+| `events` | [tendermint.abci.Event](#tendermint.abci.Event) | repeated | Events defines all the events emitted by processing a transaction. Note, these events include those emitted by processing all the messages and those emitted from the ante handler. Whereas Logs contains the events, with additional metadata, emitted only by processing the messages.
+
+Since: cosmos-sdk 0.42.11, 0.44.5, 0.45 |
 
 
 
diff --git a/types/abci.pb.go b/types/abci.pb.go
index 402df71d1580..a7bb327006aa 100644
--- a/types/abci.pb.go
+++ b/types/abci.pb.go
@@ -62,7 +62,7 @@ type TxResponse struct {
 	// emitted from the ante handler. Whereas Logs contains the events, with
 	// additional metadata, emitted only by processing the messages.
 	//
-	// Since: cosmos-sdk 0.45
+	// Since: cosmos-sdk 0.42.11, 0.44.5, 0.45
 	Events []types1.Event `protobuf:"bytes,13,rep,name=events,proto3" json:"events"`
 }
 

From 001be0fd5437236400cd6d6e3dcdd8bb82167844 Mon Sep 17 00:00:00 2001
From: Alexander Kolesov <alexandr.kolesov@cheqd.io>
Date: Wed, 1 Dec 2021 14:47:40 +0300
Subject: [PATCH 2/6] fix!: Add `--fee-payer` CLI flag, rename `--fee-account`
 to `--fee-granter` (#10625)

<!--
The default pull request template is for types feat, fix, or refactor.
For other templates, add one of the following parameters to the url:
- template=docs.md
- template=other.md
-->

## Description

Closes: #10626

<!-- Add a description of the changes that this PR introduces and the files that
are the most critical to review. -->

Changes:
- Added `--fee-payer` CLI flag:
  - The flag is used to populate the corresponding `context` property.
  - Context in its turn is used to set `fee-payer` during transaction building.
- `--fee-account` CLI flag is renamed to `--fee-granter`:
  - With the  flag added it becomes unclear whether `--fee-account` stands for `payer` or `granter`.
  - Renaming to `--fee-granter` makes things more explicit.
  - This is CLI breaking change.

---

### Author Checklist

*All items are required. Please add a note to the item if the item is not applicable and
please add links to any relevant follow up issues.*

I have...

- [x] included the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title
- [x] added `!` to the type prefix if API or client breaking change
- [x] targeted the correct branch (see [PR Targeting](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#pr-targeting))
- [x] provided a link to the relevant issue or specification
- [x] followed the guidelines for [building modules](https://github.com/cosmos/cosmos-sdk/blob/master/docs/building-modules)
- [x] included the necessary unit and integration [tests](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#testing)
- [x] added a changelog entry to `CHANGELOG.md`
- [x] included comments for [documenting Go code](https://blog.golang.org/godoc)
- [x] updated the relevant documentation or specification
- [x] reviewed "Files changed" and left comments if necessary
- [x] confirmed all CI checks have passed

### Reviewers Checklist

*All items are required. Please add a note if the item is not applicable and please add
your handle next to the items reviewed if you only reviewed selected items.*

I have...

- [ ] confirmed the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title
- [ ] confirmed `!` in the type prefix if API or client breaking change
- [ ] confirmed all author checklist items have been addressed
- [ ] reviewed state machine logic
- [ ] reviewed API design and naming
- [ ] reviewed documentation is accurate
- [ ] reviewed tests and test coverage
- [ ] manually tested (if applicable)
---
 CHANGELOG.md                        |  2 ++
 client/cmd.go                       | 17 +++++++++++++++--
 client/context.go                   |  8 ++++++++
 client/flags/flags.go               |  6 ++++--
 client/query.go                     |  5 +++++
 client/tx/tx.go                     |  1 +
 x/feegrant/client/testutil/suite.go |  8 ++++----
 x/feegrant/spec/01_concepts.md      |  6 +++---
 8 files changed, 42 insertions(+), 11 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9251e3418cf5..ef67961d2a50 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -123,6 +123,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
 * [\#9695](https://github.com/cosmos/cosmos-sdk/pull/9695) `<app> keys migrate` CLI command now takes no arguments
 * [\#9246](https://github.com/cosmos/cosmos-sdk/pull/9246) Removed the CLI flag `--setup-config-only` from the `testnet` command and added the subcommand `init-files`.
 * [\#9780](https://github.com/cosmos/cosmos-sdk/pull/9780) Use sigs.k8s.io for yaml, which might lead to minor YAML output changes
+* [\#10625](https://github.com/cosmos/cosmos-sdk/pull/10625) Rename `--fee-account` CLI flag to `--fee-granter`
 
 ### Improvements
 
@@ -138,6 +139,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
 * (genesis) [\#9697](https://github.com/cosmos/cosmos-sdk/pull/9697) Ensure `InitGenesis` returns with non-empty validator set.
 * [\#10341](https://github.com/cosmos/cosmos-sdk/pull/10341) Move from `io/ioutil` to `io` and `os` packages.
 * [\#10468](https://github.com/cosmos/cosmos-sdk/pull/10468) Allow futureOps to queue additional operations in simulations
+* [\#10625](https://github.com/cosmos/cosmos-sdk/pull/10625) Add `--fee-payer` CLI flag
 
 ### Bug Fixes
 
diff --git a/client/cmd.go b/client/cmd.go
index 0e401a9250f6..70f354bc2ddf 100644
--- a/client/cmd.go
+++ b/client/cmd.go
@@ -220,8 +220,21 @@ func readTxCommandFlags(clientCtx Context, flagSet *pflag.FlagSet) (Context, err
 		clientCtx = clientCtx.WithSignModeStr(signModeStr)
 	}
 
-	if clientCtx.FeeGranter == nil || flagSet.Changed(flags.FlagFeeAccount) {
-		granter, _ := flagSet.GetString(flags.FlagFeeAccount)
+	if clientCtx.FeePayer == nil || flagSet.Changed(flags.FlagFeePayer) {
+		payer, _ := flagSet.GetString(flags.FlagFeePayer)
+
+		if payer != "" {
+			payerAcc, err := sdk.AccAddressFromBech32(payer)
+			if err != nil {
+				return clientCtx, err
+			}
+
+			clientCtx = clientCtx.WithFeePayerAddress(payerAcc)
+		}
+	}
+
+	if clientCtx.FeeGranter == nil || flagSet.Changed(flags.FlagFeeGranter) {
+		granter, _ := flagSet.GetString(flags.FlagFeeGranter)
 
 		if granter != "" {
 			granterAcc, err := sdk.AccAddressFromBech32(granter)
diff --git a/client/context.go b/client/context.go
index 67096c33a310..56ef46ff0a88 100644
--- a/client/context.go
+++ b/client/context.go
@@ -46,6 +46,7 @@ type Context struct {
 	TxConfig          TxConfig
 	AccountRetriever  AccountRetriever
 	NodeURI           string
+	FeePayer          sdk.AccAddress
 	FeeGranter        sdk.AccAddress
 	Viper             *viper.Viper
 
@@ -181,6 +182,13 @@ func (ctx Context) WithFromAddress(addr sdk.AccAddress) Context {
 	return ctx
 }
 
+// WithFeePayerAddress returns a copy of the context with an updated fee payer account
+// address.
+func (ctx Context) WithFeePayerAddress(addr sdk.AccAddress) Context {
+	ctx.FeePayer = addr
+	return ctx
+}
+
 // WithFeeGranterAddress returns a copy of the context with an updated fee granter account
 // address.
 func (ctx Context) WithFeeGranterAddress(addr sdk.AccAddress) Context {
diff --git a/client/flags/flags.go b/client/flags/flags.go
index 49b805534efd..5ddffd453c57 100644
--- a/client/flags/flags.go
+++ b/client/flags/flags.go
@@ -70,7 +70,8 @@ const (
 	FlagCountTotal       = "count-total"
 	FlagTimeoutHeight    = "timeout-height"
 	FlagKeyAlgorithm     = "algo"
-	FlagFeeAccount       = "fee-account"
+	FlagFeePayer         = "fee-payer"
+	FlagFeeGranter       = "fee-granter"
 	FlagReverse          = "reverse"
 
 	// Tendermint logging flags
@@ -112,7 +113,8 @@ func AddTxFlagsToCmd(cmd *cobra.Command) {
 	cmd.Flags().String(FlagKeyringBackend, DefaultKeyringBackend, "Select keyring's backend (os|file|kwallet|pass|test|memory)")
 	cmd.Flags().String(FlagSignMode, "", "Choose sign mode (direct|amino-json), this is an advanced feature")
 	cmd.Flags().Uint64(FlagTimeoutHeight, 0, "Set a block timeout height to prevent the tx from being committed past a certain height")
-	cmd.Flags().String(FlagFeeAccount, "", "Fee account pays fees for the transaction instead of deducting from the signer")
+	cmd.Flags().String(FlagFeePayer, "", "Fee payer pays fees for the transaction instead of deducting from the signer")
+	cmd.Flags().String(FlagFeeGranter, "", "Fee granter grants fees for the transaction")
 
 	// --gas can accept integers and "auto"
 	cmd.Flags().String(FlagGas, "", fmt.Sprintf("gas limit to set per-transaction; set to %q to calculate sufficient gas automatically (default %d)", GasFlagAuto, DefaultGasLimit))
diff --git a/client/query.go b/client/query.go
index be603dfbf6e2..b10a0e348026 100644
--- a/client/query.go
+++ b/client/query.go
@@ -62,6 +62,11 @@ func (ctx Context) GetFromAddress() sdk.AccAddress {
 	return ctx.FromAddress
 }
 
+// GetFeePayerAddress returns the fee granter address from the context
+func (ctx Context) GetFeePayerAddress() sdk.AccAddress {
+	return ctx.FeePayer
+}
+
 // GetFeeGranterAddress returns the fee granter address from the context
 func (ctx Context) GetFeeGranterAddress() sdk.AccAddress {
 	return ctx.FeeGranter
diff --git a/client/tx/tx.go b/client/tx/tx.go
index 737a528cff0e..db787a774c51 100644
--- a/client/tx/tx.go
+++ b/client/tx/tx.go
@@ -93,6 +93,7 @@ func BroadcastTx(clientCtx client.Context, txf Factory, msgs ...sdk.Msg) error {
 	}
 
 	tx.SetFeeGranter(clientCtx.GetFeeGranterAddress())
+	tx.SetFeePayer(clientCtx.GetFeePayerAddress())
 	err = Sign(txf, clientCtx.GetFromName(), tx, true)
 	if err != nil {
 		return err
diff --git a/x/feegrant/client/testutil/suite.go b/x/feegrant/client/testutil/suite.go
index a12a473a209b..74380ab14fba 100644
--- a/x/feegrant/client/testutil/suite.go
+++ b/x/feegrant/client/testutil/suite.go
@@ -697,7 +697,7 @@ func (s *IntegrationTestSuite) TestTxWithFeeGrant() {
 	// any tx with it by using --fee-account shouldn't fail
 	out, err := govtestutil.MsgSubmitProposal(val.ClientCtx, grantee.String(),
 		"Text Proposal", "No desc", govtypes.ProposalTypeText,
-		fmt.Sprintf("--%s=%s", flags.FlagFeeAccount, granter.String()),
+		fmt.Sprintf("--%s=%s", flags.FlagFeeGranter, granter.String()),
 	)
 
 	s.Require().NoError(err)
@@ -837,7 +837,7 @@ func (s *IntegrationTestSuite) TestFilteredFeeAllowance() {
 			func() (testutil.BufferWriter, error) {
 				return govtestutil.MsgSubmitProposal(val.ClientCtx, grantee.String(),
 					"Text Proposal", "No desc", govtypes.ProposalTypeText,
-					fmt.Sprintf("--%s=%s", flags.FlagFeeAccount, granter.String()),
+					fmt.Sprintf("--%s=%s", flags.FlagFeeGranter, granter.String()),
 				)
 			},
 			&sdk.TxResponse{},
@@ -847,7 +847,7 @@ func (s *IntegrationTestSuite) TestFilteredFeeAllowance() {
 			"valid weighted_vote tx",
 			func() (testutil.BufferWriter, error) {
 				return govtestutil.MsgVote(val.ClientCtx, grantee.String(), "0", "yes",
-					fmt.Sprintf("--%s=%s", flags.FlagFeeAccount, granter.String()),
+					fmt.Sprintf("--%s=%s", flags.FlagFeeGranter, granter.String()),
 				)
 			},
 			&sdk.TxResponse{},
@@ -864,7 +864,7 @@ func (s *IntegrationTestSuite) TestFilteredFeeAllowance() {
 								grantee.String(),
 								"cosmos14cm33pvnrv2497tyt8sp9yavhmw83nwej3m0e8",
 								fmt.Sprintf("--%s=%s", cli.FlagSpendLimit, "100stake"),
-								fmt.Sprintf("--%s=%s", flags.FlagFeeAccount, granter),
+								fmt.Sprintf("--%s=%s", flags.FlagFeeGranter, granter),
 							},
 							commonFlags...,
 						)
diff --git a/x/feegrant/spec/01_concepts.md b/x/feegrant/spec/01_concepts.md
index e880c5e76ce0..6b22d46b68c4 100644
--- a/x/feegrant/spec/01_concepts.md
+++ b/x/feegrant/spec/01_concepts.md
@@ -49,9 +49,9 @@ There are two types of fee allowances present at the moment:
 
 - `period_reset` keeps track of when a next period reset should happen.
 
-## FeeAccount flag
+## FeeGranter flag
 
-`feegrant` module introduces a `FeeAccount` flag for CLI for the sake of executing transactions with fee granter. When this flag is set, `clientCtx` will append the granter account address for transactions generated through CLI.
+`feegrant` module introduces a `FeeGranter` flag for CLI for the sake of executing transactions with fee granter. When this flag is set, `clientCtx` will append the granter account address for transactions generated through CLI.
 
 +++ https://github.com/cosmos/cosmos-sdk/blob/d97e7907f176777ed8a464006d360bb3e1a223e4/client/cmd.go#L224-L235
 
@@ -64,7 +64,7 @@ There are two types of fee allowances present at the moment:
 Example cmd:
 
 ```go
-./simd tx gov submit-proposal --title="Test Proposal" --description="My awesome proposal" --type="Text" --from validator-key --fee-account=cosmos1xh44hxt7spr67hqaa7nyx5gnutrz5fraw6grxn --chain-id=testnet --fees="10stake"
+./simd tx gov submit-proposal --title="Test Proposal" --description="My awesome proposal" --type="Text" --from validator-key --fee-granter=cosmos1xh44hxt7spr67hqaa7nyx5gnutrz5fraw6grxn --chain-id=testnet --fees="10stake"
 ```
 
 ## Granted Fee Deductions

From 1fc592b48c252a13fad2eb91727fa1b51cc19bad Mon Sep 17 00:00:00 2001
From: arrayah <61775571+arrayah@users.noreply.github.com>
Date: Wed, 1 Dec 2021 15:44:54 +0300
Subject: [PATCH 3/6] build: add remote debugging with delve (#10587)

## Description

This is a feat and adds functionality for a developer to remote-debug a testnet node. This is made possible with `delve` remote debugging.

I received some help from here: https://kupczynski.info/2020/05/17/remote-debug-go-code.html

Also, @creachadair I made a tiny modification in the testnet file generation. I removed the `localnet` folder and simply let the `testnet init-files` to use the default `.testnets`, since this is also being `.gitignore`d in the repo, and we don't usually want these files in the main repo.

Let me know if there are any implications to your update that you made a few days ago.
---

### Author Checklist

*All items are required. Please add a note to the item if the item is not applicable and
please add links to any relevant follow up issues.*

I have...

- [ ] included the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title
- [ ] added `!` to the type prefix if API or client breaking change
- [ ] targeted the correct branch (see [PR Targeting](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#pr-targeting))
- [ ] provided a link to the relevant issue or specification
- [ ] followed the guidelines for [building modules](https://github.com/cosmos/cosmos-sdk/blob/master/docs/building-modules)
- [ ] included the necessary unit and integration [tests](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#testing)
- [ ] added a changelog entry to `CHANGELOG.md`
- [ ] included comments for [documenting Go code](https://blog.golang.org/godoc)
- [ ] updated the relevant documentation or specification
- [ ] reviewed "Files changed" and left comments if necessary
- [ ] confirmed all CI checks have passed

### Reviewers Checklist

*All items are required. Please add a note if the item is not applicable and please add
your handle next to the items reviewed if you only reviewed selected items.*

I have...

- [x] confirmed the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title
- [x] confirmed `!` in the type prefix if API or client breaking change
- [ ] confirmed all author checklist items have been addressed
- [ ] reviewed state machine logic
- [ ] reviewed API design and naming
- [ ] reviewed documentation is accurate
- [ ] reviewed tests and test coverage
- [x] manually tested (if applicable)
---
 Makefile                           | 28 ++++++++++++----
 contrib/images/Makefile            | 15 ++++++---
 contrib/images/simd-dlv/Dockerfile | 23 +++++++++++++
 contrib/images/simd-dlv/README.md  | 34 +++++++++++++++++++
 contrib/images/simd-dlv/wrapper.sh | 25 ++++++++++++++
 docker-compose.yml                 | 52 ++++++++++++++++++++++--------
 6 files changed, 153 insertions(+), 24 deletions(-)
 create mode 100644 contrib/images/simd-dlv/Dockerfile
 create mode 100644 contrib/images/simd-dlv/README.md
 create mode 100755 contrib/images/simd-dlv/wrapper.sh

diff --git a/Makefile b/Makefile
index 87cb85bad8ee..990d22ae8354 100644
--- a/Makefile
+++ b/Makefile
@@ -96,6 +96,11 @@ ifeq (,$(findstring nostrip,$(COSMOS_BUILD_OPTIONS)))
   BUILD_FLAGS += -trimpath
 endif
 
+# Check for debug option
+ifeq (debug,$(findstring debug,$(COSMOS_BUILD_OPTIONS)))
+  BUILD_FLAGS += -gcflags "all=-N -l"
+endif
+
 all: tools build lint test
 
 # The below include contains the tools and runsim targets.
@@ -472,17 +477,28 @@ proto-update-deps:
 ###                                Localnet                                 ###
 ###############################################################################
 
-# Run a 4-node testnet locally via docker compose
-localnet-start: localnet-stop
-	$(if $(shell $(DOCKER) inspect -f '{{ .Id }}' cosmossdk/simd-env 2>/dev/null),$(info found image cosmossdk/simd-env),$(MAKE) -C contrib/images simd-env)
-	$(DOCKER) run --rm -v $(CURDIR)/localnet:/data cosmossdk/simd-env \
-		testnet init-files --v 4 -o /data --starting-ip-address 192.168.10.2 --keyring-backend=test
+localnet-build-env:
+	$(MAKE) -C contrib/images simd-env
+localnet-build-dlv:
+	$(MAKE) -C contrib/images simd-dlv
+
+localnet-build-nodes:
+	$(DOCKER) run --rm -v $(CURDIR)/.testnets:/data cosmossdk/simd \
+    		  testnet init-files --v 4 --starting-ip-address 192.168.10.2 --keyring-backend=test
 	docker-compose up -d
 
 localnet-stop:
 	docker-compose down
 
-.PHONY: localnet-start localnet-stop
+# localnet-start will run a 4-node testnet locally. The nodes are
+# based off the docker images in: ./contrib/images/simd-env
+localnet-start: localnet-stop localnet-build-env localnet-build-nodes
+
+# localnet-debug will run a 4-node testnet locally in debug mode
+# you can read more about the debug mode here: ./contrib/images/simd-dlv/README.md
+localnet-debug: localnet-stop localnet-build-dlv localnet-build-nodes
+
+.PHONY: localnet-start localnet-stop localnet-debug localnet-build-env localnet-build-dlv localnet-build-nodes
 
 ###############################################################################
 ###                                rosetta                                  ###
diff --git a/contrib/images/Makefile b/contrib/images/Makefile
index 03d3f8be42e5..0c9364155113 100644
--- a/contrib/images/Makefile
+++ b/contrib/images/Makefile
@@ -1,7 +1,14 @@
 all: simd-env
 
-simd-env:
-	docker build --tag cosmossdk/simd-env -f simd-env/Dockerfile \
-		$(shell git rev-parse --show-toplevel)
+simd-env: simd-rmi
+	docker build --tag cosmossdk/simd -f simd-env/Dockerfile \
+    		$(shell git rev-parse --show-toplevel)
 
-.PHONY: all simd-env
+simd-dlv: simd-rmi
+	docker build --tag cosmossdk/simd -f simd-dlv/Dockerfile \
+        	$(shell git rev-parse --show-toplevel)
+
+simd-rmi:
+	docker rmi cosmossdk/simd 2>/dev/null; true
+
+.PHONY: all simd-env simd-dlv simd-rmi
\ No newline at end of file
diff --git a/contrib/images/simd-dlv/Dockerfile b/contrib/images/simd-dlv/Dockerfile
new file mode 100644
index 000000000000..89ebcea94a8f
--- /dev/null
+++ b/contrib/images/simd-dlv/Dockerfile
@@ -0,0 +1,23 @@
+FROM golang:1.17-alpine AS build
+RUN apk add build-base git linux-headers libc-dev
+RUN go install github.com/go-delve/delve/cmd/dlv@latest
+WORKDIR /work
+COPY go.mod go.sum /work/
+COPY db/go.mod db/go.sum /work/db/
+RUN go mod download
+COPY ./ /work
+RUN LEDGER_ENABLED=false make COSMOS_BUILD_OPTIONS="debug,nostrip" clean build
+
+FROM alpine:3.14 AS run
+RUN apk add bash curl jq
+COPY contrib/images/simd-dlv/wrapper.sh /usr/bin/wrapper.sh
+
+VOLUME /simd
+COPY --from=build /work/build/simd /simd/
+COPY --from=build /go/bin/dlv /usr/local/bin
+WORKDIR /simd
+
+EXPOSE 26656 26657 2345
+ENTRYPOINT ["/usr/bin/wrapper.sh"]
+CMD ["start", "--log_format", "plain"]
+STOPSIGNAL SIGTERM
\ No newline at end of file
diff --git a/contrib/images/simd-dlv/README.md b/contrib/images/simd-dlv/README.md
new file mode 100644
index 000000000000..86d09372a43d
--- /dev/null
+++ b/contrib/images/simd-dlv/README.md
@@ -0,0 +1,34 @@
+# Remote Debugging with go-delve
+
+[Delve](https://github.com/go-delve/delve) is a debugger for the Go programming language. The goal of the project is to provide a simple, full featured debugging tool for Go. Delve should be easy to invoke and easy to use. Chances are if you're using a debugger, things aren't going your way. With that in mind, Delve should stay out of your way as much as possible.
+
+## Use-case
+
+Cosmos-SDK provides you with a local network to bootstrap a chain in your machine, but how does one debug a node or module?
+
+If we start a single node, we won't be able to debug transactions as the machine will be in bootstrapping phase trying to find peers to connect too, thats why we need to start a local network.
+
+But the current `localnet-start` does not provide us with debugging tools so that's why there is a different image for debugging a local network, that is to avoid any issues in the future were debugging won't be needed.
+
+Both `simd-env` and `simd-dlv` work and run the same, except that `simd-dlv` uses `go-delve` to run the binaries.
+
+## How to use
+
+The command to start a local network in debug mode is:
+```shell
+# make localnet-debug
+```
+
+The command to stop the local network and destroy its containers is:
+```shell
+# make localnet-stop
+```
+__note: this works the same for both `localnet-start` and `localnet-debug`__
+
+Now, by default only `simdnode0` is run in debug mode, but you can run any of the other nodes in debug mode by changing the `DEBUG` environment variable to `1` in `docker-compose.yml`.
+
+## How to connect
+
+Delve will open a port on `2345` for `simdnode0` and it will increment for each of the other nodes that have `DEBUG` set to `1`.
+
+You can connect to the debugging server either through [GoLand IDE](https://www.jetbrains.com/help/go/attach-to-running-go-processes-with-debugger.html)  or you can use  [delve cli](https://github.com/go-delve/delve/blob/master/Documentation/usage/dlv_connect.md) command.
diff --git a/contrib/images/simd-dlv/wrapper.sh b/contrib/images/simd-dlv/wrapper.sh
new file mode 100755
index 000000000000..a1187ea7ec78
--- /dev/null
+++ b/contrib/images/simd-dlv/wrapper.sh
@@ -0,0 +1,25 @@
+#!/usr/bin/env sh
+set -euo pipefail
+set -x
+
+DEBUG=${DEBUG:-0}
+BINARY=/simd/${BINARY:-simd}
+ID=${ID:-0}
+LOG=${LOG:-simd.log}
+
+if ! [ -f "${BINARY}" ]; then
+	echo "The binary $(basename "${BINARY}") cannot be found. Please add the binary to the shared folder. Please use the BINARY environment variable if the name of the binary is not 'simd'"
+	exit 1
+fi
+
+export SIMDHOME="/data/node${ID}/simd"
+
+if [ "$DEBUG" -eq 1 ]; then
+  dlv --listen=:2345 --continue --headless=true --api-version=2 --accept-multiclient exec "${BINARY}" -- --home "${SIMDHOME}" "$@"
+elif [ "$DEBUG" -eq 1 ] && [ -d "$(dirname "${SIMDHOME}"/"${LOG}")" ]; then
+  dlv --listen=:2345 --continue --headless=true --api-version=2 --accept-multiclient exec "${BINARY}" -- --home "${SIMDHOME}" "$@" | tee "${SIMDHOME}/${LOG}"
+elif [ -d "$(dirname "${SIMDHOME}"/"${LOG}")" ]; then
+  "${BINARY}" --home "${SIMDHOME}" "$@" | tee "${SIMDHOME}/${LOG}"
+else
+  "${BINARY}" --home "${SIMDHOME}" "$@"
+fi
\ No newline at end of file
diff --git a/docker-compose.yml b/docker-compose.yml
index 4bb0fa82d705..13851c894e9f 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -3,64 +3,88 @@ version: "3"
 services:
   simdnode0:
     container_name: simdnode0
-    image: "cosmossdk/simd-env"
+    image: "cosmossdk/simd"
+    environment:
+      - DEBUG=1
+      - ID=0
+      - LOG=${LOG:-simd.log}
+    cap_add:
+      - SYS_PTRACE
+    security_opt:
+      - seccomp:unconfined
     ports:
       - "26656-26657:26656-26657"
       - "1317:1317"
       - "9090:9090"
-    environment:
-      - ID=0
-      - LOG=${LOG:-simd.log}
+      - "2345:2345"
     volumes:
-      - ./localnet:/data:Z
+      - ./.testnets:/data:Z
     networks:
       localnet:
         ipv4_address: 192.168.10.2
 
   simdnode1:
     container_name: simdnode1
-    image: "cosmossdk/simd-env"
+    image: "cosmossdk/simd"
+    environment:
+      - DEBUG=0
+      - ID=1
+      - LOG=${LOG:-simd.log}
+    cap_add:
+      - SYS_PTRACE
+    security_opt:
+      - seccomp:unconfined
     ports:
       - "26666-26667:26656-26657"
       - "1318:1317"
       - "9091:9090"
-    environment:
-      - ID=1
-      - LOG=${LOG:-simd.log}
+      - "2346:2345"
     volumes:
-      - ./localnet:/data:Z
+      - ./.testnets:/data:Z
     networks:
       localnet:
         ipv4_address: 192.168.10.3
 
   simdnode2:
     container_name: simdnode2
-    image: "cosmossdk/simd-env"
+    image: "cosmossdk/simd"
     environment:
+      - DEBUG=0
       - ID=2
       - LOG=${LOG:-simd.log}
+    cap_add:
+      - SYS_PTRACE
+    security_opt:
+      - seccomp:unconfined
     ports:
       - "26676-26677:26656-26657"
       - "1319:1317"
       - "9092:9090"
+      - "2347:2345"
     volumes:
-      - ./localnet:/data:Z
+      - ./.testnets:/data:Z
     networks:
       localnet:
         ipv4_address: 192.168.10.4
 
   simdnode3:
     container_name: simdnode3
-    image: "cosmossdk/simd-env"
+    image: "cosmossdk/simd"
     environment:
+      - DEBUG=0
       - ID=3
       - LOG=${LOG:-simd.log}
+    cap_add:
+      - SYS_PTRACE
+    security_opt:
+      - seccomp:unconfined
     ports:
       - "26686-26687:26656-26657"
       - "1320:1317"
       - "9093:9090"
+      - "2348:2345"
     volumes:
-      - ./localnet:/data:Z
+      - ./.testnets:/data:Z
     networks:
       localnet:
         ipv4_address: 192.168.10.5

From 06fd69c88900caf7e41302bafcdf7b32617d8743 Mon Sep 17 00:00:00 2001
From: billy rennekamp <billy.rennekamp@gmail.com>
Date: Wed, 1 Dec 2021 10:12:42 -0500
Subject: [PATCH 4/6] Update SECURITY.md (#10638)

* Update SECURITY.md

* Update SECURITY.md

* Update SECURITY.md

Co-authored-by: Marko <marbar3778@yahoo.com>
---
 SECURITY.md | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/SECURITY.md b/SECURITY.md
index 67de1f1d56c5..a84dde3ce89b 100644
--- a/SECURITY.md
+++ b/SECURITY.md
@@ -1,7 +1,7 @@
 # Security
 
-> **IMPORTANT**: If you find a security issue, you can contact our team directly at
-security@tendermint.com, or report it to our [bug bounty program](https://hackerone.com/tendermint) on HackerOne. *DO NOT* open a public issue on the repository.
+> **IMPORTANT**: If you find a security issue, you can
+report it to our [bug bounty program](https://hackerone.com/cosmos) on HackerOne. *DO NOT* open a public issue on the repository.
 
 ## Bug Bounty
 

From 25f3af2f0afaab2b826b950b8872b70ee836a755 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Thu, 2 Dec 2021 00:11:51 +0100
Subject: [PATCH 5/6] build(deps): Bump github.com/cosmos/iavl from 0.17.2 to
 0.17.3 (#10654)

Bumps [github.com/cosmos/iavl](https://github.com/cosmos/iavl) from 0.17.2 to 0.17.3.
- [Release notes](https://github.com/cosmos/iavl/releases)
- [Changelog](https://github.com/cosmos/iavl/blob/v0.17.3/CHANGELOG.md)
- [Commits](https://github.com/cosmos/iavl/compare/v0.17.2...v0.17.3)

---
updated-dependencies:
- dependency-name: github.com/cosmos/iavl
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
 go.mod | 2 +-
 go.sum | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/go.mod b/go.mod
index acb18470bbb3..7b97dd22015c 100644
--- a/go.mod
+++ b/go.mod
@@ -13,7 +13,7 @@ require (
 	github.com/cosmos/cosmos-proto v0.0.0-20211123144845-528f5002c9f8
 	github.com/cosmos/cosmos-sdk/db v0.0.0
 	github.com/cosmos/go-bip39 v1.0.0
-	github.com/cosmos/iavl v0.17.2
+	github.com/cosmos/iavl v0.17.3
 	github.com/cosmos/ledger-cosmos-go v0.11.1
 	github.com/gogo/gateway v1.1.0
 	github.com/gogo/protobuf v1.3.3
diff --git a/go.sum b/go.sum
index ead4b48b06fe..aa509aaaad4b 100644
--- a/go.sum
+++ b/go.sum
@@ -264,8 +264,8 @@ github.com/cosmos/cosmos-proto v0.0.0-20211123144845-528f5002c9f8/go.mod h1:msdD
 github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d/go.mod h1:tSxLoYXyBmiFeKpvmq4dzayMdCjCnu8uqmCysIGBT2Y=
 github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY=
 github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw=
-github.com/cosmos/iavl v0.17.2 h1:BT2u7DUvLLB+RYz9RItn/8n7Bt5xe5rj8QRTkk/PQU0=
-github.com/cosmos/iavl v0.17.2/go.mod h1:prJoErZFABYZGDHka1R6Oay4z9PrNeFFiMKHDAMOi4w=
+github.com/cosmos/iavl v0.17.3 h1:s2N819a2olOmiauVa0WAhoIJq9EhSXE9HDBAoR9k+8Y=
+github.com/cosmos/iavl v0.17.3/go.mod h1:prJoErZFABYZGDHka1R6Oay4z9PrNeFFiMKHDAMOi4w=
 github.com/cosmos/keyring v1.1.7-0.20210622111912-ef00f8ac3d76 h1:DdzS1m6o/pCqeZ8VOAit/gyATedRgjvkVI+UCrLpyuU=
 github.com/cosmos/keyring v1.1.7-0.20210622111912-ef00f8ac3d76/go.mod h1:0mkLWIoZuQ7uBoospo5Q9zIpqq6rYCPJDSUdeCJvPM8=
 github.com/cosmos/ledger-cosmos-go v0.11.1 h1:9JIYsGnXP613pb2vPjFeMMjBI5lEDsEaF6oYorTy6J4=

From 5d86db3ce593bcc8c8694f7f83418925f7e9568a Mon Sep 17 00:00:00 2001
From: atheeshp <59333759+atheeshp@users.noreply.github.com>
Date: Thu, 2 Dec 2021 12:24:38 +0530
Subject: [PATCH 6/6] refactor: middleware refactor to change tx.Handler
 interface (#10527)

<!--
The default pull request template is for types feat, fix, or refactor.
For other templates, add one of the following parameters to the url:
- template=docs.md
- template=other.md
-->

## Description

Closes: #10484

This PR makes the following big changes:

### 1. Change the tx.Handler interface

```diff
-	CheckTx(ctx context.Context, tx sdk.Tx, req abci.RequestCheckTx) (abci.ResponseCheckTx, error)
+	CheckTx(ctx context.Context, req tx.Request, checkReq tx.RequestCheckTx) (tx.Response, tx.ResponseCheckTx, error)
// same for Deliver and Simulate
```
 where:

```go
type Response struct {
	GasWanted uint64
	GasUsed   uint64
	// MsgResponses is an array containing each Msg service handler's response
	// type, packed in an Any. This will get proto-serialized into the `Data` field
	// in the ABCI Check/DeliverTx responses.
	MsgResponses []*codectypes.Any
	Log          string
	Events       []abci.Event
}
```

### 2. Change what gets passed into the ABCI Check/DeliverTx `Data` field

Before, we were passing the concatenation of MsgResponse bytes into the `Data`. Now we are passing the proto-serialiazation of this struct:

```proto
message TxMsgData {
  repeated google.protobuf.Any msg_responses = 2;
}
```

<!-- Add a description of the changes that this PR introduces and the files that
are the most critical to review. -->

---

### Author Checklist

*All items are required. Please add a note to the item if the item is not applicable and
please add links to any relevant follow up issues.*

I have...

- [ ] included the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title
- [ ] added `!` to the type prefix if API or client breaking change
- [ ] targeted the correct branch (see [PR Targeting](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#pr-targeting))
- [ ] provided a link to the relevant issue or specification
- [ ] followed the guidelines for [building modules](https://github.com/cosmos/cosmos-sdk/blob/master/docs/building-modules)
- [ ] included the necessary unit and integration [tests](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#testing)
- [ ] added a changelog entry to `CHANGELOG.md`
- [ ] included comments for [documenting Go code](https://blog.golang.org/godoc)
- [ ] updated the relevant documentation or specification
- [ ] reviewed "Files changed" and left comments if necessary
- [ ] confirmed all CI checks have passed

### Reviewers Checklist

*All items are required. Please add a note if the item is not applicable and please add
your handle next to the items reviewed if you only reviewed selected items.*

I have...

- [ ] confirmed the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title
- [ ] confirmed `!` in the type prefix if API or client breaking change
- [ ] confirmed all author checklist items have been addressed
- [ ] reviewed state machine logic
- [ ] reviewed API design and naming
- [ ] reviewed documentation is accurate
- [ ] reviewed tests and test coverage
- [ ] manually tested (if applicable)
---
 baseapp/abci.go                           |  70 +++++-
 baseapp/baseapp_test.go                   | 101 +++++++--
 baseapp/custom_txhandler_test.go          |  25 +--
 baseapp/test_helpers.go                   |  41 +++-
 docs/core/proto-docs.md                   |  10 +-
 proto/cosmos/base/abci/v1beta1/abci.proto |  18 +-
 server/mock/app.go                        |  11 +-
 server/mock/tx.go                         |  18 +-
 types/abci.pb.go                          | 255 +++++++++++++++++-----
 types/msgservice/msg_service.go           |  79 ++++---
 types/result.go                           |  10 +-
 types/result_test.go                      |   4 +-
 types/tx/middleware.go                    |  37 +++-
 types/tx/msgs.go                          |   9 +
 types/tx/types.go                         |   6 +-
 x/auth/middleware/basic.go                | 116 +++++-----
 x/auth/middleware/basic_test.go           |  17 +-
 x/auth/middleware/ext.go                  |  26 +--
 x/auth/middleware/ext_test.go             |   6 +-
 x/auth/middleware/fee.go                  |  50 ++---
 x/auth/middleware/fee_test.go             |  16 +-
 x/auth/middleware/feegrant_test.go        |   8 +-
 x/auth/middleware/gas.go                  |  48 ++--
 x/auth/middleware/gas_test.go             |  34 +--
 x/auth/middleware/index_events.go         |  24 +-
 x/auth/middleware/middleware.go           |   8 +-
 x/auth/middleware/middleware_test.go      |  27 +--
 x/auth/middleware/priority.go             |  26 +--
 x/auth/middleware/priority_test.go        |  10 +-
 x/auth/middleware/recovery.go             |  14 +-
 x/auth/middleware/run_msgs.go             |  65 ++----
 x/auth/middleware/run_msgs_test.go        |  19 +-
 x/auth/middleware/sigverify.go            | 142 ++++++------
 x/auth/middleware/sigverify_test.go       |  16 +-
 x/auth/middleware/testutil_test.go        |  17 +-
 x/auth/middleware/tips.go                 |  71 ++----
 x/auth/tx/service_test.go                 |   4 +-
 37 files changed, 886 insertions(+), 572 deletions(-)

diff --git a/baseapp/abci.go b/baseapp/abci.go
index d27251a0545a..b3569ff8f53c 100644
--- a/baseapp/abci.go
+++ b/baseapp/abci.go
@@ -21,6 +21,7 @@ import (
 	"github.com/cosmos/cosmos-sdk/telemetry"
 	sdk "github.com/cosmos/cosmos-sdk/types"
 	sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
+	"github.com/cosmos/cosmos-sdk/types/tx"
 )
 
 // InitChain implements the ABCI interface. It runs the initialization logic
@@ -249,18 +250,23 @@ func (app *BaseApp) CheckTx(req abci.RequestCheckTx) abci.ResponseCheckTx {
 		panic(fmt.Sprintf("unknown RequestCheckTx type: %s", req.Type))
 	}
 
-	tx, err := app.txDecoder(req.Tx)
+	reqTx, err := app.txDecoder(req.Tx)
 	if err != nil {
 		return sdkerrors.ResponseCheckTx(err, 0, 0, app.trace)
 	}
 
 	ctx := app.getContextForTx(mode, req.Tx)
-	res, err := app.txHandler.CheckTx(ctx, tx, req)
+	res, checkRes, err := app.txHandler.CheckTx(ctx, tx.Request{Tx: reqTx, TxBytes: req.Tx}, tx.RequestCheckTx{Type: req.Type})
 	if err != nil {
 		return sdkerrors.ResponseCheckTx(err, uint64(res.GasUsed), uint64(res.GasWanted), app.trace)
 	}
 
-	return res
+	abciRes, err := convertTxResponseToCheckTx(res, checkRes)
+	if err != nil {
+		return sdkerrors.ResponseCheckTx(err, uint64(res.GasUsed), uint64(res.GasWanted), app.trace)
+	}
+
+	return abciRes
 }
 
 // DeliverTx implements the ABCI interface and executes a tx in DeliverTx mode.
@@ -271,28 +277,34 @@ func (app *BaseApp) CheckTx(req abci.RequestCheckTx) abci.ResponseCheckTx {
 func (app *BaseApp) DeliverTx(req abci.RequestDeliverTx) abci.ResponseDeliverTx {
 	defer telemetry.MeasureSince(time.Now(), "abci", "deliver_tx")
 
-	var res abci.ResponseDeliverTx
+	var abciRes abci.ResponseDeliverTx
 	defer func() {
 		for _, streamingListener := range app.abciListeners {
-			if err := streamingListener.ListenDeliverTx(app.deliverState.ctx, req, res); err != nil {
+			if err := streamingListener.ListenDeliverTx(app.deliverState.ctx, req, abciRes); err != nil {
 				app.logger.Error("DeliverTx listening hook failed", "err", err)
 			}
 		}
 	}()
-	tx, err := app.txDecoder(req.Tx)
+	reqTx, err := app.txDecoder(req.Tx)
 	if err != nil {
-		res = sdkerrors.ResponseDeliverTx(err, 0, 0, app.trace)
-		return res
+		abciRes = sdkerrors.ResponseDeliverTx(err, 0, 0, app.trace)
+		return abciRes
 	}
 
 	ctx := app.getContextForTx(runTxModeDeliver, req.Tx)
-	res, err = app.txHandler.DeliverTx(ctx, tx, req)
+	res, err := app.txHandler.DeliverTx(ctx, tx.Request{Tx: reqTx, TxBytes: req.Tx})
 	if err != nil {
-		res = sdkerrors.ResponseDeliverTx(err, uint64(res.GasUsed), uint64(res.GasWanted), app.trace)
-		return res
+		abciRes = sdkerrors.ResponseDeliverTx(err, uint64(res.GasUsed), uint64(res.GasWanted), app.trace)
+		return abciRes
 	}
 
-	return res
+	abciRes, err = convertTxResponseToDeliverTx(res)
+	if err != nil {
+		return sdkerrors.ResponseDeliverTx(err, uint64(res.GasUsed), uint64(res.GasWanted), app.trace)
+	}
+
+	return abciRes
+
 }
 
 // Commit implements the ABCI interface. It will commit all state that exists in
@@ -894,3 +906,37 @@ func splitPath(requestPath string) (path []string) {
 
 	return path
 }
+
+// makeABCIData generates the Data field to be sent to ABCI Check/DeliverTx.
+func makeABCIData(txRes tx.Response) ([]byte, error) {
+	return proto.Marshal(&sdk.TxMsgData{MsgResponses: txRes.MsgResponses})
+}
+
+// convertTxResponseToCheckTx converts a tx.Response into a abci.ResponseCheckTx.
+func convertTxResponseToCheckTx(txRes tx.Response, checkRes tx.ResponseCheckTx) (abci.ResponseCheckTx, error) {
+	data, err := makeABCIData(txRes)
+	if err != nil {
+		return abci.ResponseCheckTx{}, nil
+	}
+
+	return abci.ResponseCheckTx{
+		Data:     data,
+		Log:      txRes.Log,
+		Events:   txRes.Events,
+		Priority: checkRes.Priority,
+	}, nil
+}
+
+// convertTxResponseToDeliverTx converts a tx.Response into a abci.ResponseDeliverTx.
+func convertTxResponseToDeliverTx(txRes tx.Response) (abci.ResponseDeliverTx, error) {
+	data, err := makeABCIData(txRes)
+	if err != nil {
+		return abci.ResponseDeliverTx{}, nil
+	}
+
+	return abci.ResponseDeliverTx{
+		Data:   data,
+		Log:    txRes.Log,
+		Events: txRes.Events,
+	}, nil
+}
diff --git a/baseapp/baseapp_test.go b/baseapp/baseapp_test.go
index 84fff39ab2f4..46051b38237b 100644
--- a/baseapp/baseapp_test.go
+++ b/baseapp/baseapp_test.go
@@ -23,6 +23,7 @@ import (
 
 	"github.com/cosmos/cosmos-sdk/baseapp"
 	"github.com/cosmos/cosmos-sdk/codec"
+	codectypes "github.com/cosmos/cosmos-sdk/codec/types"
 	"github.com/cosmos/cosmos-sdk/snapshots"
 	snapshottypes "github.com/cosmos/cosmos-sdk/snapshots/types"
 	"github.com/cosmos/cosmos-sdk/store/rootmulti"
@@ -148,7 +149,14 @@ func setupBaseAppWithSnapshots(t *testing.T, blocks uint, blockTxs int, options
 		legacyRouter.AddRoute(sdk.NewRoute(routeMsgKeyValue, func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) {
 			kv := msg.(*msgKeyValue)
 			bapp.CMS().GetCommitKVStore(capKey2).Set(kv.Key, kv.Value)
-			return &sdk.Result{}, nil
+			any, err := codectypes.NewAnyWithValue(msg)
+			if err != nil {
+				return nil, err
+			}
+
+			return &sdk.Result{
+				MsgResponses: []*codectypes.Any{any},
+			}, nil
 		}))
 		txHandler := testTxHandler(
 			middleware.TxHandlerOptions{
@@ -716,7 +724,7 @@ func (tx *txTest) setFailOnAnte(fail bool) {
 
 func (tx *txTest) setFailOnHandler(fail bool) {
 	for i, msg := range tx.Msgs {
-		tx.Msgs[i] = msgCounter{msg.(msgCounter).Counter, fail}
+		tx.Msgs[i] = &msgCounter{msg.(*msgCounter).Counter, fail}
 	}
 }
 
@@ -744,16 +752,16 @@ type msgCounter struct {
 }
 
 // dummy implementation of proto.Message
-func (msg msgCounter) Reset()         {}
-func (msg msgCounter) String() string { return "TODO" }
-func (msg msgCounter) ProtoMessage()  {}
+func (msg *msgCounter) Reset()         {}
+func (msg *msgCounter) String() string { return "TODO" }
+func (msg *msgCounter) ProtoMessage()  {}
 
 // Implements Msg
-func (msg msgCounter) Route() string                { return routeMsgCounter }
-func (msg msgCounter) Type() string                 { return "counter1" }
-func (msg msgCounter) GetSignBytes() []byte         { return nil }
-func (msg msgCounter) GetSigners() []sdk.AccAddress { return nil }
-func (msg msgCounter) ValidateBasic() error {
+func (msg *msgCounter) Route() string                { return routeMsgCounter }
+func (msg *msgCounter) Type() string                 { return "counter1" }
+func (msg *msgCounter) GetSignBytes() []byte         { return nil }
+func (msg *msgCounter) GetSigners() []sdk.AccAddress { return nil }
+func (msg *msgCounter) ValidateBasic() error {
 	if msg.Counter >= 0 {
 		return nil
 	}
@@ -763,7 +771,7 @@ func (msg msgCounter) ValidateBasic() error {
 func newTxCounter(counter int64, msgCounters ...int64) txTest {
 	msgs := make([]sdk.Msg, 0, len(msgCounters))
 	for _, c := range msgCounters {
-		msgs = append(msgs, msgCounter{c, false})
+		msgs = append(msgs, &msgCounter{c, false})
 	}
 
 	return txTest{msgs, counter, false, math.MaxUint64}
@@ -903,6 +911,14 @@ func handlerMsgCounter(t *testing.T, capKey storetypes.StoreKey, deliverKey []by
 		}
 
 		res.Events = ctx.EventManager().Events().ToABCIEvents()
+
+		any, err := codectypes.NewAnyWithValue(msg)
+		if err != nil {
+			return nil, err
+		}
+
+		res.MsgResponses = []*codectypes.Any{any}
+
 		return res, nil
 	}
 }
@@ -1153,7 +1169,15 @@ func TestSimulateTx(t *testing.T) {
 		legacyRouter := middleware.NewLegacyRouter()
 		r := sdk.NewRoute(routeMsgCounter, func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) {
 			ctx.GasMeter().ConsumeGas(gasConsumed, "test")
-			return &sdk.Result{}, nil
+			// Return dummy MsgResponse for msgCounter.
+			any, err := codectypes.NewAnyWithValue(&testdata.Dog{})
+			if err != nil {
+				return nil, err
+			}
+
+			return &sdk.Result{
+				MsgResponses: []*codectypes.Any{any},
+			}, nil
 		})
 		legacyRouter.AddRoute(r)
 		txHandler := testTxHandler(
@@ -1221,7 +1245,14 @@ func TestRunInvalidTransaction(t *testing.T) {
 	txHandlerOpt := func(bapp *baseapp.BaseApp) {
 		legacyRouter := middleware.NewLegacyRouter()
 		r := sdk.NewRoute(routeMsgCounter, func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) {
-			return &sdk.Result{}, nil
+			any, err := codectypes.NewAnyWithValue(msg)
+			if err != nil {
+				return nil, err
+			}
+
+			return &sdk.Result{
+				MsgResponses: []*codectypes.Any{any},
+			}, nil
 		})
 		legacyRouter.AddRoute(r)
 		txHandler := testTxHandler(
@@ -1269,7 +1300,7 @@ func TestRunInvalidTransaction(t *testing.T) {
 
 		for _, testCase := range testCases {
 			tx := testCase.tx
-			_, result, err := app.SimDeliver(aminoTxEncoder(), tx)
+			_, _, err := app.SimDeliver(aminoTxEncoder(), tx)
 
 			if testCase.fail {
 				require.Error(t, err)
@@ -1278,14 +1309,14 @@ func TestRunInvalidTransaction(t *testing.T) {
 				require.EqualValues(t, sdkerrors.ErrInvalidSequence.Codespace(), space, err)
 				require.EqualValues(t, sdkerrors.ErrInvalidSequence.ABCICode(), code, err)
 			} else {
-				require.NotNil(t, result)
+				require.NoError(t, err)
 			}
 		}
 	}
 
 	// transaction with no known route
 	{
-		unknownRouteTx := txTest{[]sdk.Msg{msgNoRoute{}}, 0, false, math.MaxUint64}
+		unknownRouteTx := txTest{[]sdk.Msg{&msgNoRoute{}}, 0, false, math.MaxUint64}
 		_, result, err := app.SimDeliver(aminoTxEncoder(), unknownRouteTx)
 		require.Error(t, err)
 		require.Nil(t, result)
@@ -1294,7 +1325,7 @@ func TestRunInvalidTransaction(t *testing.T) {
 		require.EqualValues(t, sdkerrors.ErrUnknownRequest.Codespace(), space, err)
 		require.EqualValues(t, sdkerrors.ErrUnknownRequest.ABCICode(), code, err)
 
-		unknownRouteTx = txTest{[]sdk.Msg{msgCounter{}, msgNoRoute{}}, 0, false, math.MaxUint64}
+		unknownRouteTx = txTest{[]sdk.Msg{&msgCounter{}, &msgNoRoute{}}, 0, false, math.MaxUint64}
 		_, result, err = app.SimDeliver(aminoTxEncoder(), unknownRouteTx)
 		require.Error(t, err)
 		require.Nil(t, result)
@@ -1307,7 +1338,7 @@ func TestRunInvalidTransaction(t *testing.T) {
 	// Transaction with an unregistered message
 	{
 		tx := newTxCounter(0, 0)
-		tx.Msgs = append(tx.Msgs, msgNoDecode{})
+		tx.Msgs = append(tx.Msgs, &msgNoDecode{})
 
 		// new codec so we can encode the tx, but we shouldn't be able to decode
 		newCdc := codec.NewLegacyAmino()
@@ -1336,9 +1367,16 @@ func TestTxGasLimits(t *testing.T) {
 	txHandlerOpt := func(bapp *baseapp.BaseApp) {
 		legacyRouter := middleware.NewLegacyRouter()
 		r := sdk.NewRoute(routeMsgCounter, func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) {
-			count := msg.(msgCounter).Counter
+			count := msg.(*msgCounter).Counter
 			ctx.GasMeter().ConsumeGas(uint64(count), "counter-handler")
-			return &sdk.Result{}, nil
+			any, err := codectypes.NewAnyWithValue(msg)
+			if err != nil {
+				return nil, err
+			}
+
+			return &sdk.Result{
+				MsgResponses: []*codectypes.Any{any},
+			}, nil
 		})
 		legacyRouter.AddRoute(r)
 		txHandler := testTxHandler(
@@ -1415,9 +1453,17 @@ func TestMaxBlockGasLimits(t *testing.T) {
 	txHandlerOpt := func(bapp *baseapp.BaseApp) {
 		legacyRouter := middleware.NewLegacyRouter()
 		r := sdk.NewRoute(routeMsgCounter, func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) {
-			count := msg.(msgCounter).Counter
+			count := msg.(*msgCounter).Counter
 			ctx.GasMeter().ConsumeGas(uint64(count), "counter-handler")
-			return &sdk.Result{}, nil
+
+			any, err := codectypes.NewAnyWithValue(msg)
+			if err != nil {
+				return nil, err
+			}
+
+			return &sdk.Result{
+				MsgResponses: []*codectypes.Any{any},
+			}, nil
 		})
 		legacyRouter.AddRoute(r)
 		txHandler := testTxHandler(
@@ -1595,7 +1641,7 @@ func TestGasConsumptionBadTx(t *testing.T) {
 	txHandlerOpt := func(bapp *baseapp.BaseApp) {
 		legacyRouter := middleware.NewLegacyRouter()
 		r := sdk.NewRoute(routeMsgCounter, func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) {
-			count := msg.(msgCounter).Counter
+			count := msg.(*msgCounter).Counter
 			ctx.GasMeter().ConsumeGas(uint64(count), "counter-handler")
 			return &sdk.Result{}, nil
 		})
@@ -1651,7 +1697,14 @@ func TestQuery(t *testing.T) {
 		r := sdk.NewRoute(routeMsgCounter, func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) {
 			store := ctx.KVStore(capKey1)
 			store.Set(key, value)
-			return &sdk.Result{}, nil
+
+			any, err := codectypes.NewAnyWithValue(msg)
+			if err != nil {
+				return nil, err
+			}
+			return &sdk.Result{
+				MsgResponses: []*codectypes.Any{any},
+			}, nil
 		})
 		legacyRouter.AddRoute(r)
 		txHandler := testTxHandler(
diff --git a/baseapp/custom_txhandler_test.go b/baseapp/custom_txhandler_test.go
index 6582dda66184..27cec992ed10 100644
--- a/baseapp/custom_txhandler_test.go
+++ b/baseapp/custom_txhandler_test.go
@@ -6,7 +6,6 @@ import (
 
 	sdk "github.com/cosmos/cosmos-sdk/types"
 	"github.com/cosmos/cosmos-sdk/types/tx"
-	abci "github.com/tendermint/tendermint/abci/types"
 	"github.com/tendermint/tendermint/crypto/tmhash"
 )
 
@@ -31,33 +30,33 @@ func CustomTxHandlerMiddleware(handler handlerFun) tx.Middleware {
 }
 
 // CheckTx implements tx.Handler.CheckTx method.
-func (txh customTxHandler) CheckTx(ctx context.Context, tx sdk.Tx, req abci.RequestCheckTx) (abci.ResponseCheckTx, error) {
-	sdkCtx, err := txh.runHandler(ctx, tx, req.Tx, false)
+func (txh customTxHandler) CheckTx(ctx context.Context, req tx.Request, checkReq tx.RequestCheckTx) (tx.Response, tx.ResponseCheckTx, error) {
+	sdkCtx, err := txh.runHandler(ctx, req.Tx, req.TxBytes, false)
 	if err != nil {
-		return abci.ResponseCheckTx{}, err
+		return tx.Response{}, tx.ResponseCheckTx{}, err
 	}
 
-	return txh.next.CheckTx(sdk.WrapSDKContext(sdkCtx), tx, req)
+	return txh.next.CheckTx(sdk.WrapSDKContext(sdkCtx), req, checkReq)
 }
 
 // DeliverTx implements tx.Handler.DeliverTx method.
-func (txh customTxHandler) DeliverTx(ctx context.Context, tx sdk.Tx, req abci.RequestDeliverTx) (abci.ResponseDeliverTx, error) {
-	sdkCtx, err := txh.runHandler(ctx, tx, req.Tx, false)
+func (txh customTxHandler) DeliverTx(ctx context.Context, req tx.Request) (tx.Response, error) {
+	sdkCtx, err := txh.runHandler(ctx, req.Tx, req.TxBytes, false)
 	if err != nil {
-		return abci.ResponseDeliverTx{}, err
+		return tx.Response{}, err
 	}
 
-	return txh.next.DeliverTx(sdk.WrapSDKContext(sdkCtx), tx, req)
+	return txh.next.DeliverTx(sdk.WrapSDKContext(sdkCtx), req)
 }
 
 // SimulateTx implements tx.Handler.SimulateTx method.
-func (txh customTxHandler) SimulateTx(ctx context.Context, sdkTx sdk.Tx, req tx.RequestSimulateTx) (tx.ResponseSimulateTx, error) {
-	sdkCtx, err := txh.runHandler(ctx, sdkTx, req.TxBytes, true)
+func (txh customTxHandler) SimulateTx(ctx context.Context, req tx.Request) (tx.Response, error) {
+	sdkCtx, err := txh.runHandler(ctx, req.Tx, req.TxBytes, true)
 	if err != nil {
-		return tx.ResponseSimulateTx{}, err
+		return tx.Response{}, err
 	}
 
-	return txh.next.SimulateTx(sdk.WrapSDKContext(sdkCtx), sdkTx, req)
+	return txh.next.SimulateTx(sdk.WrapSDKContext(sdkCtx), req)
 }
 
 func (txh customTxHandler) runHandler(ctx context.Context, tx sdk.Tx, txBytes []byte, isSimulate bool) (sdk.Context, error) {
diff --git a/baseapp/test_helpers.go b/baseapp/test_helpers.go
index 64924523493e..bc837e3cc595 100644
--- a/baseapp/test_helpers.go
+++ b/baseapp/test_helpers.go
@@ -10,23 +10,28 @@ import (
 )
 
 // SimCheck defines a CheckTx helper function that used in tests and simulations.
-func (app *BaseApp) SimCheck(txEncoder sdk.TxEncoder, tx sdk.Tx) (sdk.GasInfo, *sdk.Result, error) {
+func (app *BaseApp) SimCheck(txEncoder sdk.TxEncoder, sdkTx sdk.Tx) (sdk.GasInfo, *sdk.Result, error) {
 	// CheckTx expects tx bytes as argument, so we encode the tx argument into
 	// bytes. Note that CheckTx will actually decode those bytes again. But since
 	// this helper is only used in tests/simulation, it's fine.
-	bz, err := txEncoder(tx)
+	bz, err := txEncoder(sdkTx)
 	if err != nil {
 		return sdk.GasInfo{}, nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "%s", err)
 	}
 
 	ctx := app.getContextForTx(runTxModeDeliver, bz)
-	res, err := app.txHandler.CheckTx(ctx, tx, abci.RequestCheckTx{Tx: bz, Type: abci.CheckTxType_New})
+	res, _, err := app.txHandler.CheckTx(ctx, tx.Request{Tx: sdkTx, TxBytes: bz}, tx.RequestCheckTx{Type: abci.CheckTxType_New})
 	gInfo := sdk.GasInfo{GasWanted: uint64(res.GasWanted), GasUsed: uint64(res.GasUsed)}
 	if err != nil {
 		return gInfo, nil, err
 	}
 
-	return gInfo, &sdk.Result{Data: res.Data, Log: res.Log, Events: res.Events}, nil
+	data, err := makeABCIData(res)
+	if err != nil {
+		return gInfo, nil, err
+	}
+
+	return gInfo, &sdk.Result{Data: data, Log: res.Log, Events: res.Events, MsgResponses: res.MsgResponses}, nil
 }
 
 // Simulate executes a tx in simulate mode to get result and gas info.
@@ -37,31 +42,45 @@ func (app *BaseApp) Simulate(txBytes []byte) (sdk.GasInfo, *sdk.Result, error) {
 	}
 
 	ctx := app.getContextForTx(runTxModeSimulate, txBytes)
-	res, err := app.txHandler.SimulateTx(ctx, sdkTx, tx.RequestSimulateTx{TxBytes: txBytes})
+	res, err := app.txHandler.SimulateTx(ctx, tx.Request{Tx: sdkTx, TxBytes: txBytes})
+	gasInfo := sdk.GasInfo{
+		GasWanted: res.GasWanted,
+		GasUsed:   res.GasUsed,
+	}
+	if err != nil {
+		return gasInfo, nil, err
+	}
+
+	data, err := makeABCIData(res)
 	if err != nil {
-		return res.GasInfo, nil, err
+		return gasInfo, nil, err
 	}
 
-	return res.GasInfo, res.Result, nil
+	return gasInfo, &sdk.Result{Data: data, Log: res.Log, Events: res.Events, MsgResponses: res.MsgResponses}, nil
 }
 
 // SimDeliver defines a DeliverTx helper function that used in tests and
 // simulations.
-func (app *BaseApp) SimDeliver(txEncoder sdk.TxEncoder, tx sdk.Tx) (sdk.GasInfo, *sdk.Result, error) {
+func (app *BaseApp) SimDeliver(txEncoder sdk.TxEncoder, sdkTx sdk.Tx) (sdk.GasInfo, *sdk.Result, error) {
 	// See comment for Check().
-	bz, err := txEncoder(tx)
+	bz, err := txEncoder(sdkTx)
 	if err != nil {
 		return sdk.GasInfo{}, nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "%s", err)
 	}
 
 	ctx := app.getContextForTx(runTxModeDeliver, bz)
-	res, err := app.txHandler.DeliverTx(ctx, tx, abci.RequestDeliverTx{Tx: bz})
+	res, err := app.txHandler.DeliverTx(ctx, tx.Request{Tx: sdkTx, TxBytes: bz})
 	gInfo := sdk.GasInfo{GasWanted: uint64(res.GasWanted), GasUsed: uint64(res.GasUsed)}
 	if err != nil {
 		return gInfo, nil, err
 	}
 
-	return gInfo, &sdk.Result{Data: res.Data, Log: res.Log, Events: res.Events}, nil
+	data, err := makeABCIData(res)
+	if err != nil {
+		return gInfo, nil, err
+	}
+
+	return gInfo, &sdk.Result{Data: data, Log: res.Log, Events: res.Events, MsgResponses: res.MsgResponses}, nil
 }
 
 // Context with current {check, deliver}State of the app used by tests.
diff --git a/docs/core/proto-docs.md b/docs/core/proto-docs.md
index 5d17dd708a68..7dd29cfbd7d2 100644
--- a/docs/core/proto-docs.md
+++ b/docs/core/proto-docs.md
@@ -2318,9 +2318,12 @@ Result is the union of ResponseFormat and ResponseCheckTx.
 
 | Field | Type | Label | Description |
 | ----- | ---- | ----- | ----------- |
-| `data` | [bytes](#bytes) |  | Data is any data returned from message or handler execution. It MUST be length prefixed in order to separate data from multiple message executions. |
+| `data` | [bytes](#bytes) |  | **Deprecated.** Data is any data returned from message or handler execution. It MUST be length prefixed in order to separate data from multiple message executions. Deprecated. This field is still populated, but prefer msg_response instead because it also contains the Msg response typeURL. |
 | `log` | [string](#string) |  | Log contains the log information from message or handler execution. |
 | `events` | [tendermint.abci.Event](#tendermint.abci.Event) | repeated | Events contains a slice of Event objects that were emitted during message or handler execution. |
+| `msg_responses` | [google.protobuf.Any](#google.protobuf.Any) | repeated | msg_responses contains the Msg handler responses type packed in Anys.
+
+Since: cosmos-sdk 0.45 |
 
 
 
@@ -2390,7 +2393,10 @@ for each message.
 
 | Field | Type | Label | Description |
 | ----- | ---- | ----- | ----------- |
-| `data` | [MsgData](#cosmos.base.abci.v1beta1.MsgData) | repeated |  |
+| `data` | [MsgData](#cosmos.base.abci.v1beta1.MsgData) | repeated | **Deprecated.** data field is deprecated and not populated. |
+| `msg_responses` | [google.protobuf.Any](#google.protobuf.Any) | repeated | msg_responses contains the Msg handler responses packed into Anys.
+
+Since: cosmos-sdk 0.45 |
 
 
 
diff --git a/proto/cosmos/base/abci/v1beta1/abci.proto b/proto/cosmos/base/abci/v1beta1/abci.proto
index 1376761b38b8..b9a5ae1a83bc 100644
--- a/proto/cosmos/base/abci/v1beta1/abci.proto
+++ b/proto/cosmos/base/abci/v1beta1/abci.proto
@@ -91,7 +91,9 @@ message Result {
 
   // Data is any data returned from message or handler execution. It MUST be
   // length prefixed in order to separate data from multiple message executions.
-  bytes data = 1;
+  // Deprecated. This field is still populated, but prefer msg_response instead
+  // because it also contains the Msg response typeURL.
+  bytes data = 1 [deprecated = true];
 
   // Log contains the log information from message or handler execution.
   string log = 2;
@@ -99,6 +101,11 @@ message Result {
   // Events contains a slice of Event objects that were emitted during message
   // or handler execution.
   repeated tendermint.abci.Event events = 3 [(gogoproto.nullable) = false];
+
+  // msg_responses contains the Msg handler responses type packed in Anys.
+  //
+  // Since: cosmos-sdk 0.45
+  repeated google.protobuf.Any msg_responses = 4;
 }
 
 // SimulationResponse defines the response generated when a transaction is
@@ -111,6 +118,7 @@ message SimulationResponse {
 // MsgData defines the data returned in a Result object during message
 // execution.
 message MsgData {
+  option deprecated = true;
   option (gogoproto.stringer) = true;
 
   string msg_type = 1;
@@ -122,7 +130,13 @@ message MsgData {
 message TxMsgData {
   option (gogoproto.stringer) = true;
 
-  repeated MsgData data = 1;
+  // data field is deprecated and not populated.
+  repeated MsgData data = 1 [deprecated = true];
+
+  // msg_responses contains the Msg handler responses packed into Anys.
+  //
+  // Since: cosmos-sdk 0.45
+  repeated google.protobuf.Any msg_responses = 2;
 }
 
 // SearchTxsResult defines a structure for querying txs pageable
diff --git a/server/mock/app.go b/server/mock/app.go
index 779b9c5c320c..ff4a58fa829c 100644
--- a/server/mock/app.go
+++ b/server/mock/app.go
@@ -12,6 +12,7 @@ import (
 
 	bam "github.com/cosmos/cosmos-sdk/baseapp"
 	"github.com/cosmos/cosmos-sdk/codec"
+	codectypes "github.com/cosmos/cosmos-sdk/codec/types"
 	"github.com/cosmos/cosmos-sdk/simapp"
 	storetypes "github.com/cosmos/cosmos-sdk/store/types"
 	sdk "github.com/cosmos/cosmos-sdk/types"
@@ -74,7 +75,7 @@ func NewApp(rootDir string, logger log.Logger) (abci.Application, error) {
 // them to the db
 func KVStoreHandler(storeKey storetypes.StoreKey) sdk.Handler {
 	return func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) {
-		dTx, ok := msg.(kvstoreTx)
+		dTx, ok := msg.(*kvstoreTx)
 		if !ok {
 			return nil, errors.New("KVStoreHandler should only receive kvstoreTx")
 		}
@@ -86,8 +87,14 @@ func KVStoreHandler(storeKey storetypes.StoreKey) sdk.Handler {
 		store := ctx.KVStore(storeKey)
 		store.Set(key, value)
 
+		any, err := codectypes.NewAnyWithValue(msg)
+		if err != nil {
+			return nil, err
+		}
+
 		return &sdk.Result{
-			Log: fmt.Sprintf("set %s=%s", key, value),
+			Log:          fmt.Sprintf("set %s=%s", key, value),
+			MsgResponses: []*codectypes.Any{any},
 		}, nil
 	}
 }
diff --git a/server/mock/tx.go b/server/mock/tx.go
index afa3c266b7b2..bfa6e6ad6b4b 100644
--- a/server/mock/tx.go
+++ b/server/mock/tx.go
@@ -21,13 +21,13 @@ type kvstoreTx struct {
 }
 
 // dummy implementation of proto.Message
-func (msg kvstoreTx) Reset()         {}
-func (msg kvstoreTx) String() string { return "TODO" }
-func (msg kvstoreTx) ProtoMessage()  {}
+func (msg *kvstoreTx) Reset()         {}
+func (msg *kvstoreTx) String() string { return "TODO" }
+func (msg *kvstoreTx) ProtoMessage()  {}
 
-var _ sdk.Tx = kvstoreTx{}
-var _ sdk.Msg = kvstoreTx{}
-var _ middleware.GasTx = kvstoreTx{}
+var _ sdk.Tx = &kvstoreTx{}
+var _ sdk.Msg = &kvstoreTx{}
+var _ middleware.GasTx = &kvstoreTx{}
 
 func NewTx(key, value string) kvstoreTx {
 	bytes := fmt.Sprintf("%s=%s", key, value)
@@ -46,7 +46,7 @@ func (tx kvstoreTx) Type() string {
 	return "kvstore_tx"
 }
 
-func (tx kvstoreTx) GetMsgs() []sdk.Msg {
+func (tx *kvstoreTx) GetMsgs() []sdk.Msg {
 	return []sdk.Msg{tx}
 }
 
@@ -79,10 +79,10 @@ func decodeTx(txBytes []byte) (sdk.Tx, error) {
 	split := bytes.Split(txBytes, []byte("="))
 	if len(split) == 1 {
 		k := split[0]
-		tx = kvstoreTx{k, k, txBytes}
+		tx = &kvstoreTx{k, k, txBytes}
 	} else if len(split) == 2 {
 		k, v := split[0], split[1]
-		tx = kvstoreTx{k, v, txBytes}
+		tx = &kvstoreTx{k, v, txBytes}
 	} else {
 		return nil, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "too many '='")
 	}
diff --git a/types/abci.pb.go b/types/abci.pb.go
index a7bb327006aa..834b221c9006 100644
--- a/types/abci.pb.go
+++ b/types/abci.pb.go
@@ -324,12 +324,18 @@ func (m *GasInfo) GetGasUsed() uint64 {
 type Result struct {
 	// Data is any data returned from message or handler execution. It MUST be
 	// length prefixed in order to separate data from multiple message executions.
-	Data []byte `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"`
+	// Deprecated. This field is still populated, but prefer msg_response instead
+	// because it also contains the Msg response typeURL.
+	Data []byte `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"` // Deprecated: Do not use.
 	// Log contains the log information from message or handler execution.
 	Log string `protobuf:"bytes,2,opt,name=log,proto3" json:"log,omitempty"`
 	// Events contains a slice of Event objects that were emitted during message
 	// or handler execution.
 	Events []types1.Event `protobuf:"bytes,3,rep,name=events,proto3" json:"events"`
+	// msg_responses contains the Msg handler responses type packed in Anys.
+	//
+	// Since: cosmos-sdk 0.45
+	MsgResponses []*types.Any `protobuf:"bytes,4,rep,name=msg_responses,json=msgResponses,proto3" json:"msg_responses,omitempty"`
 }
 
 func (m *Result) Reset()      { *m = Result{} }
@@ -412,6 +418,8 @@ func (m *SimulationResponse) GetResult() *Result {
 
 // MsgData defines the data returned in a Result object during message
 // execution.
+//
+// Deprecated: Do not use.
 type MsgData struct {
 	MsgType string `protobuf:"bytes,1,opt,name=msg_type,json=msgType,proto3" json:"msg_type,omitempty"`
 	Data    []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"`
@@ -466,7 +474,12 @@ func (m *MsgData) GetData() []byte {
 // TxMsgData defines a list of MsgData. A transaction will have a MsgData object
 // for each message.
 type TxMsgData struct {
-	Data []*MsgData `protobuf:"bytes,1,rep,name=data,proto3" json:"data,omitempty"`
+	// data field is deprecated and not populated.
+	Data []*MsgData `protobuf:"bytes,1,rep,name=data,proto3" json:"data,omitempty"` // Deprecated: Do not use.
+	// msg_responses contains the Msg handler responses packed into Anys.
+	//
+	// Since: cosmos-sdk 0.45
+	MsgResponses []*types.Any `protobuf:"bytes,2,rep,name=msg_responses,json=msgResponses,proto3" json:"msg_responses,omitempty"`
 }
 
 func (m *TxMsgData) Reset()      { *m = TxMsgData{} }
@@ -501,6 +514,7 @@ func (m *TxMsgData) XXX_DiscardUnknown() {
 
 var xxx_messageInfo_TxMsgData proto.InternalMessageInfo
 
+// Deprecated: Do not use.
 func (m *TxMsgData) GetData() []*MsgData {
 	if m != nil {
 		return m.Data
@@ -508,6 +522,13 @@ func (m *TxMsgData) GetData() []*MsgData {
 	return nil
 }
 
+func (m *TxMsgData) GetMsgResponses() []*types.Any {
+	if m != nil {
+		return m.MsgResponses
+	}
+	return nil
+}
+
 // SearchTxsResult defines a structure for querying txs pageable
 type SearchTxsResult struct {
 	// Count of all txs
@@ -616,63 +637,65 @@ func init() {
 }
 
 var fileDescriptor_4e37629bc7eb0df8 = []byte{
-	// 881 bytes of a gzipped FileDescriptorProto
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x55, 0xbd, 0x8f, 0x1b, 0x45,
-	0x14, 0xf7, 0xda, 0xce, 0xfa, 0xf6, 0xf9, 0x2e, 0x87, 0x46, 0xa7, 0x64, 0x2f, 0x01, 0xdb, 0x38,
-	0x41, 0x72, 0x93, 0x35, 0xb9, 0x04, 0x84, 0x28, 0x10, 0xf1, 0xf1, 0x91, 0x93, 0x12, 0x8a, 0x39,
-	0x47, 0x48, 0x34, 0xd6, 0xd8, 0x9e, 0x8c, 0x97, 0x78, 0x77, 0xac, 0x9d, 0xd9, 0xbb, 0xbd, 0x8e,
-	0x92, 0x0a, 0x51, 0x51, 0x50, 0x51, 0xf3, 0x97, 0xa4, 0xa0, 0xb8, 0x32, 0x05, 0x32, 0x70, 0xd7,
-	0xe5, 0xaf, 0x40, 0xf3, 0x66, 0xfc, 0x71, 0x44, 0x8e, 0x44, 0xe5, 0xf7, 0xf1, 0x9b, 0x37, 0xef,
-	0xf7, 0x7b, 0xcf, 0xb3, 0x70, 0x67, 0x24, 0x55, 0x22, 0x55, 0x77, 0xc8, 0x14, 0xef, 0xb2, 0xe1,
-	0x28, 0xee, 0x9e, 0xdc, 0x1f, 0x72, 0xcd, 0xee, 0xa3, 0x13, 0xcd, 0x32, 0xa9, 0x25, 0x09, 0x2d,
-	0x28, 0x32, 0xa0, 0x08, 0xe3, 0x0e, 0x74, 0x6b, 0x4f, 0x48, 0x21, 0x11, 0xd4, 0x35, 0x96, 0xc5,
-	0xdf, 0xba, 0xad, 0x79, 0x3a, 0xe6, 0x59, 0x12, 0xa7, 0xda, 0xd6, 0xd4, 0x67, 0x33, 0xae, 0x5c,
-	0x72, 0x5f, 0x48, 0x29, 0xa6, 0xbc, 0x8b, 0xde, 0x30, 0x7f, 0xde, 0x65, 0xe9, 0x99, 0x4d, 0xb5,
-	0xff, 0xa8, 0x00, 0xf4, 0x0b, 0xca, 0xd5, 0x4c, 0xa6, 0x8a, 0x93, 0x1b, 0xe0, 0x4f, 0x78, 0x2c,
-	0x26, 0x3a, 0xf4, 0x5a, 0x5e, 0xa7, 0x42, 0x9d, 0x47, 0xda, 0xe0, 0xeb, 0x62, 0xc2, 0xd4, 0x24,
-	0x2c, 0xb7, 0xbc, 0x4e, 0xd0, 0x83, 0x8b, 0x79, 0xd3, 0xef, 0x17, 0x8f, 0x99, 0x9a, 0x50, 0x97,
-	0x21, 0xef, 0x42, 0x30, 0x92, 0x63, 0xae, 0x66, 0x6c, 0xc4, 0xc3, 0x8a, 0x81, 0xd1, 0x55, 0x80,
-	0x10, 0xa8, 0x1a, 0x27, 0xac, 0xb6, 0xbc, 0xce, 0x0e, 0x45, 0xdb, 0xc4, 0xc6, 0x4c, 0xb3, 0xf0,
-	0x1a, 0x82, 0xd1, 0x26, 0x37, 0xa1, 0x96, 0xb1, 0xd3, 0xc1, 0x54, 0x8a, 0xd0, 0xc7, 0xb0, 0x9f,
-	0xb1, 0xd3, 0x27, 0x52, 0x90, 0x67, 0x50, 0x9d, 0x4a, 0xa1, 0xc2, 0x5a, 0xab, 0xd2, 0xa9, 0x1f,
-	0x74, 0xa2, 0x4d, 0x02, 0x45, 0x8f, 0x7a, 0x87, 0x47, 0x4f, 0xb9, 0x52, 0x4c, 0xf0, 0x27, 0x52,
-	0xf4, 0x6e, 0xbe, 0x9c, 0x37, 0x4b, 0xbf, 0xff, 0xd5, 0xdc, 0xbd, 0x1a, 0x57, 0x14, 0xcb, 0x99,
-	0x1e, 0xe2, 0xf4, 0xb9, 0x0c, 0xb7, 0x6c, 0x0f, 0xc6, 0x26, 0xef, 0x01, 0x08, 0xa6, 0x06, 0xa7,
-	0x2c, 0xd5, 0x7c, 0x1c, 0x06, 0xa8, 0x44, 0x20, 0x98, 0xfa, 0x16, 0x03, 0x64, 0x1f, 0xb6, 0x4c,
-	0x3a, 0x57, 0x7c, 0x1c, 0x02, 0x26, 0x6b, 0x82, 0xa9, 0x67, 0x8a, 0x8f, 0xc9, 0x5d, 0x28, 0xeb,
-	0x22, 0xac, 0xb7, 0xbc, 0x4e, 0xfd, 0x60, 0x2f, 0xb2, 0xb2, 0x47, 0x0b, 0xd9, 0xa3, 0x47, 0xe9,
-	0x19, 0x2d, 0xeb, 0xc2, 0x28, 0xa5, 0xe3, 0x84, 0x2b, 0xcd, 0x92, 0x59, 0xb8, 0x6d, 0x95, 0x5a,
-	0x06, 0xc8, 0x43, 0xf0, 0xf9, 0x09, 0x4f, 0xb5, 0x0a, 0x77, 0x90, 0xea, 0x8d, 0x68, 0x35, 0x5b,
-	0xcb, 0xf4, 0x4b, 0x93, 0xee, 0x55, 0x0d, 0x31, 0xea, 0xb0, 0x9f, 0x56, 0x7f, 0xfc, 0xad, 0x59,
-	0x6a, 0xff, 0xea, 0xc1, 0xf5, 0xab, 0x3c, 0xc9, 0x6d, 0x08, 0x12, 0x25, 0x06, 0x71, 0x3a, 0xe6,
-	0x05, 0x4e, 0x75, 0x87, 0x6e, 0x25, 0x4a, 0x1c, 0x19, 0x9f, 0xbc, 0x03, 0x15, 0xa3, 0x34, 0x0e,
-	0x95, 0x1a, 0x93, 0x1c, 0x2f, 0x6f, 0xaf, 0xe0, 0xed, 0x1f, 0x6c, 0x16, 0xfa, 0x58, 0x67, 0x71,
-	0x2a, 0x6c, 0x33, 0x7b, 0x4e, 0xe5, 0xed, 0xb5, 0xa0, 0x5a, 0x35, 0xf7, 0xc3, 0x9f, 0x2d, 0xaf,
-	0x9d, 0x41, 0x7d, 0x2d, 0x6b, 0x94, 0x37, 0x4b, 0x8a, 0x3d, 0x05, 0x14, 0x6d, 0x72, 0x04, 0xc0,
-	0xb4, 0xce, 0xe2, 0x61, 0xae, 0xb9, 0x0a, 0xcb, 0xd8, 0xc1, 0x9d, 0xb7, 0x8c, 0x7a, 0x81, 0x75,
-	0x62, 0xac, 0x1d, 0x76, 0x77, 0x3e, 0x80, 0x60, 0x09, 0x32, 0x6c, 0x5f, 0xf0, 0x33, 0x77, 0xa1,
-	0x31, 0xc9, 0x1e, 0x5c, 0x3b, 0x61, 0xd3, 0x9c, 0x3b, 0x05, 0xac, 0xd3, 0x3e, 0x84, 0xda, 0xd7,
-	0x4c, 0x1d, 0xbd, 0xb9, 0x0a, 0xe6, 0x64, 0x75, 0xd3, 0x2a, 0x94, 0x31, 0xb9, 0x58, 0x85, 0xf6,
-	0xf7, 0xe0, 0x53, 0xae, 0xf2, 0xa9, 0x5e, 0xae, 0xb9, 0x39, 0xbd, 0xed, 0xd6, 0xfc, 0x4d, 0xe1,
-	0x1f, 0xfe, 0x47, 0xf8, 0xff, 0x33, 0xf6, 0x5f, 0x3c, 0x20, 0xc7, 0x71, 0x92, 0x4f, 0x99, 0x8e,
-	0x65, 0xba, 0xfc, 0x37, 0x7f, 0x65, 0xbb, 0xc3, 0xfd, 0xf6, 0x70, 0x27, 0xdf, 0xdf, 0xac, 0xa5,
-	0x63, 0xdc, 0xdb, 0x32, 0xf5, 0xcf, 0xe7, 0x4d, 0x0f, 0xa9, 0xa0, 0x08, 0x9f, 0x80, 0x9f, 0x21,
-	0x15, 0xec, 0xb7, 0x7e, 0xd0, 0xda, 0x5c, 0xc5, 0x52, 0xa6, 0x0e, 0xdf, 0xfe, 0x0c, 0x6a, 0x4f,
-	0x95, 0xf8, 0xc2, 0x30, 0xde, 0x07, 0xb3, 0x76, 0x83, 0xb5, 0x91, 0xd7, 0x12, 0x25, 0xfa, 0x66,
-	0xea, 0x0b, 0x81, 0xca, 0x2b, 0x81, 0xdc, 0xf8, 0x1e, 0x43, 0xd0, 0x2f, 0x16, 0x15, 0x3e, 0x5a,
-	0xea, 0x58, 0x79, 0x3b, 0x15, 0x77, 0xe0, 0x4a, 0xa5, 0x9f, 0xca, 0xb0, 0x7b, 0xcc, 0x59, 0x36,
-	0x9a, 0xf4, 0x0b, 0xe5, 0x06, 0xf3, 0x21, 0xd4, 0xb5, 0xd4, 0x6c, 0x3a, 0x18, 0xc9, 0x3c, 0xb5,
-	0x4f, 0x5e, 0xb5, 0xb7, 0xfb, 0x7a, 0xde, 0x5c, 0x0f, 0x53, 0x40, 0xe7, 0xd0, 0xd8, 0x66, 0x5f,
-	0x2c, 0xd6, 0x0e, 0xdb, 0x3a, 0xa6, 0xce, 0x8c, 0x09, 0x3e, 0x48, 0xf3, 0x64, 0xc8, 0x33, 0x7c,
-	0xfb, 0x5c, 0x9d, 0xb5, 0x30, 0x05, 0xe3, 0x7c, 0x83, 0x36, 0xb9, 0x07, 0xe8, 0x0d, 0xb0, 0x34,
-	0xbe, 0x89, 0xd5, 0xde, 0xf5, 0xd7, 0xf3, 0xe6, 0x5a, 0x94, 0x06, 0xc6, 0xee, 0x1b, 0xd3, 0x5c,
-	0x3b, 0x8d, 0x93, 0x58, 0xe3, 0x4b, 0x59, 0xa5, 0xd6, 0x21, 0x1f, 0x43, 0x45, 0x17, 0x2a, 0xf4,
-	0x51, 0x8e, 0xbb, 0x9b, 0xe5, 0x58, 0xbd, 0xef, 0xd4, 0x1c, 0xb0, 0x82, 0xf4, 0x3e, 0x7f, 0xf5,
-	0x4f, 0xa3, 0xf4, 0xf2, 0xa2, 0xe1, 0x9d, 0x5f, 0x34, 0xbc, 0xbf, 0x2f, 0x1a, 0xde, 0xcf, 0x97,
-	0x8d, 0xd2, 0xf9, 0x65, 0xa3, 0xf4, 0xea, 0xb2, 0x51, 0xfa, 0xae, 0x2d, 0x62, 0x3d, 0xc9, 0x87,
-	0xd1, 0x48, 0x26, 0x5d, 0xf7, 0xbd, 0xb2, 0x3f, 0xf7, 0xd4, 0xf8, 0x85, 0xfd, 0xb8, 0x0c, 0x7d,
-	0x7c, 0xd8, 0x1e, 0xfc, 0x1b, 0x00, 0x00, 0xff, 0xff, 0xf9, 0xed, 0x2a, 0x80, 0xd1, 0x06, 0x00,
-	0x00,
+	// 924 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x55, 0x3f, 0x6f, 0x1b, 0x37,
+	0x14, 0xd7, 0x49, 0x97, 0x93, 0xf5, 0x24, 0xc7, 0x05, 0x61, 0x38, 0x74, 0xd2, 0x4a, 0xaa, 0x92,
+	0x02, 0x5a, 0x72, 0x6a, 0x9c, 0xa0, 0x68, 0x32, 0x25, 0x72, 0xff, 0x19, 0x48, 0x3a, 0x9c, 0x15,
+	0x14, 0xe8, 0x22, 0x50, 0x12, 0x43, 0x1d, 0xa2, 0x3b, 0x0a, 0x47, 0xca, 0x3e, 0x6f, 0xdd, 0xda,
+	0xa9, 0xe8, 0xd4, 0xa1, 0x53, 0xd7, 0xf6, 0x93, 0x64, 0xe8, 0xe0, 0x31, 0x43, 0xa1, 0xb6, 0xf6,
+	0x96, 0x4f, 0x51, 0xf0, 0x91, 0x92, 0x95, 0xba, 0x0a, 0x3c, 0xdd, 0xfb, 0xc7, 0xc7, 0xf7, 0x7e,
+	0xef, 0x77, 0x8f, 0x70, 0x7b, 0x28, 0x55, 0x22, 0x55, 0x67, 0xc0, 0x14, 0xef, 0xb0, 0xc1, 0x30,
+	0xee, 0x1c, 0xdd, 0x1b, 0x70, 0xcd, 0xee, 0xa1, 0x12, 0x4e, 0x33, 0xa9, 0x25, 0xa1, 0x36, 0x28,
+	0x34, 0x41, 0x21, 0xda, 0x5d, 0xd0, 0xcd, 0x6d, 0x21, 0x85, 0xc4, 0xa0, 0x8e, 0x91, 0x6c, 0xfc,
+	0xcd, 0x5b, 0x9a, 0xa7, 0x23, 0x9e, 0x25, 0x71, 0xaa, 0x6d, 0x4e, 0x7d, 0x32, 0xe5, 0xca, 0x39,
+	0x77, 0x85, 0x94, 0x62, 0xc2, 0x3b, 0xa8, 0x0d, 0x66, 0x2f, 0x3a, 0x2c, 0x3d, 0xb1, 0xae, 0xd6,
+	0x1f, 0x25, 0x80, 0x5e, 0x1e, 0x71, 0x35, 0x95, 0xa9, 0xe2, 0x64, 0x07, 0x82, 0x31, 0x8f, 0xc5,
+	0x58, 0x53, 0xaf, 0xe9, 0xb5, 0x4b, 0x91, 0xd3, 0x48, 0x0b, 0x02, 0x9d, 0x8f, 0x99, 0x1a, 0xd3,
+	0x62, 0xd3, 0x6b, 0x57, 0xba, 0x70, 0x36, 0x6f, 0x04, 0xbd, 0xfc, 0x2b, 0xa6, 0xc6, 0x91, 0xf3,
+	0x90, 0xf7, 0xa1, 0x32, 0x94, 0x23, 0xae, 0xa6, 0x6c, 0xc8, 0x69, 0xc9, 0x84, 0x45, 0x17, 0x06,
+	0x42, 0xc0, 0x37, 0x0a, 0xf5, 0x9b, 0x5e, 0x7b, 0x33, 0x42, 0xd9, 0xd8, 0x46, 0x4c, 0x33, 0x7a,
+	0x0d, 0x83, 0x51, 0x26, 0x37, 0xa0, 0x9c, 0xb1, 0xe3, 0xfe, 0x44, 0x0a, 0x1a, 0xa0, 0x39, 0xc8,
+	0xd8, 0xf1, 0x53, 0x29, 0xc8, 0x73, 0xf0, 0x27, 0x52, 0x28, 0x5a, 0x6e, 0x96, 0xda, 0xd5, 0xbd,
+	0x76, 0xb8, 0x0e, 0xa0, 0xf0, 0x49, 0x77, 0xff, 0xe0, 0x19, 0x57, 0x8a, 0x09, 0xfe, 0x54, 0x8a,
+	0xee, 0x8d, 0x57, 0xf3, 0x46, 0xe1, 0xf7, 0xbf, 0x1a, 0x5b, 0x6f, 0xdb, 0x55, 0x84, 0xe9, 0x4c,
+	0x0d, 0x71, 0xfa, 0x42, 0xd2, 0x0d, 0x5b, 0x83, 0x91, 0xc9, 0x07, 0x00, 0x82, 0xa9, 0xfe, 0x31,
+	0x4b, 0x35, 0x1f, 0xd1, 0x0a, 0x22, 0x51, 0x11, 0x4c, 0x7d, 0x83, 0x06, 0xb2, 0x0b, 0x1b, 0xc6,
+	0x3d, 0x53, 0x7c, 0x44, 0x01, 0x9d, 0x65, 0xc1, 0xd4, 0x73, 0xc5, 0x47, 0xe4, 0x0e, 0x14, 0x75,
+	0x4e, 0xab, 0x4d, 0xaf, 0x5d, 0xdd, 0xdb, 0x0e, 0x2d, 0xec, 0xe1, 0x02, 0xf6, 0xf0, 0x49, 0x7a,
+	0x12, 0x15, 0x75, 0x6e, 0x90, 0xd2, 0x71, 0xc2, 0x95, 0x66, 0xc9, 0x94, 0xd6, 0x2c, 0x52, 0x4b,
+	0x03, 0x79, 0x00, 0x01, 0x3f, 0xe2, 0xa9, 0x56, 0x74, 0x13, 0x5b, 0xdd, 0x09, 0x2f, 0x66, 0x6b,
+	0x3b, 0xfd, 0xdc, 0xb8, 0xbb, 0xbe, 0x69, 0x2c, 0x72, 0xb1, 0x8f, 0xfc, 0x1f, 0x7e, 0x6d, 0x14,
+	0x5a, 0xbf, 0x78, 0x70, 0xfd, 0xed, 0x3e, 0xc9, 0x2d, 0xa8, 0x24, 0x4a, 0xf4, 0xe3, 0x74, 0xc4,
+	0x73, 0x9c, 0xea, 0x66, 0xb4, 0x91, 0x28, 0x71, 0x60, 0x74, 0xf2, 0x1e, 0x94, 0x0c, 0xd2, 0x38,
+	0xd4, 0xc8, 0x88, 0xe4, 0x70, 0x79, 0x7b, 0x09, 0x6f, 0xff, 0x68, 0x3d, 0xd0, 0x87, 0x3a, 0x8b,
+	0x53, 0x61, 0x8b, 0xd9, 0x76, 0x28, 0xd7, 0x56, 0x8c, 0xea, 0xa2, 0xb8, 0xef, 0xfe, 0x6c, 0x7a,
+	0xad, 0x0c, 0xaa, 0x2b, 0x5e, 0x83, 0xbc, 0x21, 0x29, 0xd6, 0x54, 0x89, 0x50, 0x26, 0x07, 0x00,
+	0x4c, 0xeb, 0x2c, 0x1e, 0xcc, 0x34, 0x57, 0xb4, 0x88, 0x15, 0xdc, 0x7e, 0xc7, 0xa8, 0x17, 0xb1,
+	0x0e, 0x8c, 0x95, 0xc3, 0xee, 0xce, 0xfb, 0x50, 0x59, 0x06, 0x99, 0x6e, 0x5f, 0xf2, 0x13, 0x77,
+	0xa1, 0x11, 0xc9, 0x36, 0x5c, 0x3b, 0x62, 0x93, 0x19, 0x77, 0x08, 0x58, 0xa5, 0xb5, 0x0f, 0xe5,
+	0x2f, 0x99, 0x3a, 0xb8, 0x4c, 0x05, 0x73, 0xd2, 0x5f, 0x47, 0x85, 0x22, 0x3a, 0x17, 0x54, 0x68,
+	0xfd, 0xe6, 0x41, 0x10, 0x71, 0x35, 0x9b, 0x68, 0xb2, 0xe3, 0x78, 0x6e, 0x8e, 0xd7, 0xba, 0x45,
+	0xea, 0x39, 0xae, 0x5f, 0x46, 0xff, 0xc1, 0x7f, 0xd0, 0xbf, 0xd2, 0xec, 0xc9, 0x43, 0xd8, 0x34,
+	0x23, 0xce, 0xdc, 0x5f, 0xac, 0xa8, 0x8f, 0x87, 0xff, 0x9f, 0x80, 0xb5, 0x44, 0x89, 0xc5, 0xff,
+	0xbe, 0xa0, 0xcd, 0xcf, 0x1e, 0x90, 0xc3, 0x38, 0x99, 0x4d, 0x98, 0x8e, 0x65, 0xba, 0xdc, 0x06,
+	0x5f, 0xd8, 0xee, 0xf0, 0xff, 0xf0, 0x90, 0xd3, 0x1f, 0xae, 0x9f, 0x85, 0x43, 0xac, 0xbb, 0x61,
+	0x4a, 0x3b, 0x9d, 0x37, 0x3c, 0x84, 0x02, 0x41, 0xfc, 0x14, 0x82, 0x0c, 0x91, 0xc0, 0x56, 0xab,
+	0x7b, 0xcd, 0xf5, 0x59, 0x2c, 0x62, 0x91, 0x8b, 0x6f, 0x3d, 0x86, 0xf2, 0x33, 0x25, 0x3e, 0x33,
+	0x60, 0xed, 0x82, 0xa1, 0x6d, 0x7f, 0x85, 0x32, 0xe5, 0x44, 0x89, 0x9e, 0x61, 0xcd, 0x62, 0x8f,
+	0x98, 0xec, 0x35, 0x8b, 0xed, 0xa3, 0xc0, 0x8c, 0x9f, 0x7a, 0xad, 0xef, 0x3d, 0xa8, 0xf4, 0xf2,
+	0x45, 0x92, 0x87, 0xcb, 0x49, 0x94, 0xde, 0xdd, 0x8d, 0x3b, 0xb0, 0x32, 0xac, 0x4b, 0x20, 0x17,
+	0xaf, 0x0e, 0x32, 0x52, 0xf1, 0xc7, 0x22, 0x6c, 0x1d, 0x72, 0x96, 0x0d, 0xc7, 0xbd, 0x5c, 0x39,
+	0x66, 0x7c, 0x0c, 0x55, 0x2d, 0x35, 0x9b, 0xf4, 0x87, 0x72, 0x96, 0xda, 0xa5, 0xeb, 0x77, 0xb7,
+	0xde, 0xcc, 0x1b, 0xab, 0xe6, 0x08, 0x50, 0xd9, 0x37, 0xb2, 0x61, 0xac, 0x8d, 0xb5, 0x74, 0xb3,
+	0x8a, 0xc9, 0x33, 0x65, 0x82, 0xf7, 0xd3, 0x59, 0x32, 0xe0, 0x19, 0x6e, 0x5f, 0x97, 0x67, 0xc5,
+	0x1c, 0x81, 0x51, 0xbe, 0x46, 0x99, 0xdc, 0x05, 0xd4, 0xfa, 0x98, 0x1a, 0xb7, 0xb2, 0xdf, 0xbd,
+	0xfe, 0x66, 0xde, 0x58, 0xb1, 0x46, 0x15, 0x23, 0xf7, 0x8c, 0x68, 0xae, 0x9d, 0xc4, 0x49, 0xac,
+	0x71, 0x57, 0xfb, 0x91, 0x55, 0xc8, 0x27, 0x50, 0xd2, 0xb9, 0xa2, 0x01, 0x22, 0x71, 0x67, 0x3d,
+	0x9a, 0x17, 0x2f, 0x4c, 0x64, 0x0e, 0x58, 0x40, 0xba, 0x8f, 0x5f, 0xff, 0x53, 0x2f, 0xbc, 0x3a,
+	0xab, 0x7b, 0xa7, 0x67, 0x75, 0xef, 0xef, 0xb3, 0xba, 0xf7, 0xd3, 0x79, 0xbd, 0x70, 0x7a, 0x5e,
+	0x2f, 0xbc, 0x3e, 0xaf, 0x17, 0xbe, 0x6d, 0x89, 0x58, 0x8f, 0x67, 0x83, 0x70, 0x28, 0x93, 0x8e,
+	0x7b, 0x31, 0xed, 0xe7, 0xae, 0x1a, 0xbd, 0xb4, 0xcf, 0xdb, 0x20, 0x40, 0xd0, 0xef, 0xff, 0x1b,
+	0x00, 0x00, 0xff, 0xff, 0x41, 0x3c, 0xca, 0x00, 0x53, 0x07, 0x00, 0x00,
 }
 
 func (m *TxResponse) Marshal() (dAtA []byte, err error) {
@@ -983,6 +1006,20 @@ func (m *Result) MarshalToSizedBuffer(dAtA []byte) (int, error) {
 	_ = i
 	var l int
 	_ = l
+	if len(m.MsgResponses) > 0 {
+		for iNdEx := len(m.MsgResponses) - 1; iNdEx >= 0; iNdEx-- {
+			{
+				size, err := m.MsgResponses[iNdEx].MarshalToSizedBuffer(dAtA[:i])
+				if err != nil {
+					return 0, err
+				}
+				i -= size
+				i = encodeVarintAbci(dAtA, i, uint64(size))
+			}
+			i--
+			dAtA[i] = 0x22
+		}
+	}
 	if len(m.Events) > 0 {
 		for iNdEx := len(m.Events) - 1; iNdEx >= 0; iNdEx-- {
 			{
@@ -1116,6 +1153,20 @@ func (m *TxMsgData) MarshalToSizedBuffer(dAtA []byte) (int, error) {
 	_ = i
 	var l int
 	_ = l
+	if len(m.MsgResponses) > 0 {
+		for iNdEx := len(m.MsgResponses) - 1; iNdEx >= 0; iNdEx-- {
+			{
+				size, err := m.MsgResponses[iNdEx].MarshalToSizedBuffer(dAtA[:i])
+				if err != nil {
+					return 0, err
+				}
+				i -= size
+				i = encodeVarintAbci(dAtA, i, uint64(size))
+			}
+			i--
+			dAtA[i] = 0x12
+		}
+	}
 	if len(m.Data) > 0 {
 		for iNdEx := len(m.Data) - 1; iNdEx >= 0; iNdEx-- {
 			{
@@ -1360,6 +1411,12 @@ func (m *Result) Size() (n int) {
 			n += 1 + l + sovAbci(uint64(l))
 		}
 	}
+	if len(m.MsgResponses) > 0 {
+		for _, e := range m.MsgResponses {
+			l = e.Size()
+			n += 1 + l + sovAbci(uint64(l))
+		}
+	}
 	return n
 }
 
@@ -1407,6 +1464,12 @@ func (m *TxMsgData) Size() (n int) {
 			n += 1 + l + sovAbci(uint64(l))
 		}
 	}
+	if len(m.MsgResponses) > 0 {
+		for _, e := range m.MsgResponses {
+			l = e.Size()
+			n += 1 + l + sovAbci(uint64(l))
+		}
+	}
 	return n
 }
 
@@ -1499,8 +1562,14 @@ func (this *TxMsgData) String() string {
 		repeatedStringForData += strings.Replace(f.String(), "MsgData", "MsgData", 1) + ","
 	}
 	repeatedStringForData += "}"
+	repeatedStringForMsgResponses := "[]*Any{"
+	for _, f := range this.MsgResponses {
+		repeatedStringForMsgResponses += strings.Replace(fmt.Sprintf("%v", f), "Any", "types.Any", 1) + ","
+	}
+	repeatedStringForMsgResponses += "}"
 	s := strings.Join([]string{`&TxMsgData{`,
 		`Data:` + repeatedStringForData + `,`,
+		`MsgResponses:` + repeatedStringForMsgResponses + `,`,
 		`}`,
 	}, "")
 	return s
@@ -2537,6 +2606,40 @@ func (m *Result) Unmarshal(dAtA []byte) error {
 				return err
 			}
 			iNdEx = postIndex
+		case 4:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field MsgResponses", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowAbci
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthAbci
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthAbci
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.MsgResponses = append(m.MsgResponses, &types.Any{})
+			if err := m.MsgResponses[len(m.MsgResponses)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
 		default:
 			iNdEx = preIndex
 			skippy, err := skipAbci(dAtA[iNdEx:])
@@ -2856,6 +2959,40 @@ func (m *TxMsgData) Unmarshal(dAtA []byte) error {
 				return err
 			}
 			iNdEx = postIndex
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field MsgResponses", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowAbci
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthAbci
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthAbci
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.MsgResponses = append(m.MsgResponses, &types.Any{})
+			if err := m.MsgResponses[len(m.MsgResponses)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
 		default:
 			iNdEx = preIndex
 			skippy, err := skipAbci(dAtA[iNdEx:])
diff --git a/types/msgservice/msg_service.go b/types/msgservice/msg_service.go
index 382913590cad..f8dc5aff5029 100644
--- a/types/msgservice/msg_service.go
+++ b/types/msgservice/msg_service.go
@@ -1,44 +1,73 @@
 package msgservice
 
 import (
-	"context"
+	"bytes"
+	"compress/gzip"
 	"fmt"
+	"io/ioutil"
+	"reflect"
 
+	"github.com/gogo/protobuf/proto"
 	"google.golang.org/grpc"
+	proto2 "google.golang.org/protobuf/proto"
+	"google.golang.org/protobuf/reflect/protodesc"
+	"google.golang.org/protobuf/reflect/protoreflect"
+	"google.golang.org/protobuf/types/descriptorpb"
 
 	codectypes "github.com/cosmos/cosmos-sdk/codec/types"
 	sdk "github.com/cosmos/cosmos-sdk/types"
+	"github.com/cosmos/cosmos-sdk/types/tx"
 )
 
 // RegisterMsgServiceDesc registers all type_urls from Msg services described
 // in `sd` into the registry.
 func RegisterMsgServiceDesc(registry codectypes.InterfaceRegistry, sd *grpc.ServiceDesc) {
-	// Adds a top-level type_url based on the Msg service name.
-	for _, method := range sd.Methods {
-		fqMethod := fmt.Sprintf("/%s/%s", sd.ServiceName, method.MethodName)
-		methodHandler := method.Handler
-
-		// NOTE: This is how we pull the concrete request type for each handler for registering in the InterfaceRegistry.
-		// This approach is maybe a bit hacky, but less hacky than reflecting on the handler object itself.
-		// We use a no-op interceptor to avoid actually calling into the handler itself.
-		_, _ = methodHandler(nil, context.Background(), func(i interface{}) error {
-			msg, ok := i.(sdk.Msg)
-			if !ok {
-				// We panic here because there is no other alternative and the app cannot be initialized correctly
-				// this should only happen if there is a problem with code generation in which case the app won't
-				// work correctly anyway.
-				panic(fmt.Errorf("can't register request type %T for service method %s", i, fqMethod))
-			}
-
-			registry.RegisterImplementations((*sdk.Msg)(nil), msg)
-
-			return nil
-		}, noopInterceptor)
+	fdBytesUnzipped := unzip(proto.FileDescriptor(sd.Metadata.(string)))
+	if fdBytesUnzipped == nil {
+		panic(fmt.Errorf("error unzipping file description for MsgService %s", sd.ServiceName))
+	}
+
+	fdRaw := &descriptorpb.FileDescriptorProto{}
+	err := proto2.Unmarshal(fdBytesUnzipped, fdRaw)
+	if err != nil {
+		panic(err)
+	}
+
+	fd, err := protodesc.FileOptions{
+		AllowUnresolvable: true,
+	}.New(fdRaw, nil)
+	if err != nil {
+		panic(err)
+	}
+
+	prefSd := fd.Services().ByName(protoreflect.FullName(sd.ServiceName).Name())
+	for i := 0; i < prefSd.Methods().Len(); i++ {
+		md := prefSd.Methods().Get(i)
+		requestDesc := md.Input()
+		responseDesc := md.Output()
 
+		reqTyp := proto.MessageType(string(requestDesc.FullName()))
+		respTyp := proto.MessageType(string(responseDesc.FullName()))
+
+		// Register sdk.Msg and sdk.MsgResponse to the registry.
+		registry.RegisterImplementations((*sdk.Msg)(nil), reflect.New(reqTyp).Elem().Interface().(proto.Message))
+		registry.RegisterImplementations((*tx.MsgResponse)(nil), reflect.New(respTyp).Elem().Interface().(proto.Message))
 	}
 }
 
-// gRPC NOOP interceptor
-func noopInterceptor(_ context.Context, _ interface{}, _ *grpc.UnaryServerInfo, _ grpc.UnaryHandler) (interface{}, error) {
-	return nil, nil
+func unzip(b []byte) []byte {
+	if b == nil {
+		return nil
+	}
+	r, err := gzip.NewReader(bytes.NewReader(b))
+	if err != nil {
+		panic(err)
+	}
+
+	unzipped, err := ioutil.ReadAll(r)
+	if err != nil {
+		panic(err)
+	}
+
+	return unzipped
 }
diff --git a/types/result.go b/types/result.go
index 4e7b15bf5b05..38787e8eb5eb 100644
--- a/types/result.go
+++ b/types/result.go
@@ -238,6 +238,11 @@ func WrapServiceResult(ctx Context, res proto.Message, err error) (*Result, erro
 		return nil, err
 	}
 
+	any, err := codectypes.NewAnyWithValue(res)
+	if err != nil {
+		return nil, err
+	}
+
 	var data []byte
 	if res != nil {
 		data, err = proto.Marshal(res)
@@ -252,7 +257,8 @@ func WrapServiceResult(ctx Context, res proto.Message, err error) (*Result, erro
 	}
 
 	return &Result{
-		Data:   data,
-		Events: events,
+		Data:         data,
+		Events:       events,
+		MsgResponses: []*codectypes.Any{any},
 	}, nil
 }
diff --git a/types/result_test.go b/types/result_test.go
index e9fd9f4a4adf..8364f166f77c 100644
--- a/types/result_test.go
+++ b/types/result_test.go
@@ -229,14 +229,14 @@ func TestWrapServiceResult(t *testing.T) {
 	require.Nil(t, res)
 	require.NotNil(t, err)
 
-	res, err = sdk.WrapServiceResult(ctx, nil, nil)
+	res, err = sdk.WrapServiceResult(ctx, &testdata.Dog{}, nil)
 	require.NotNil(t, res)
 	require.Nil(t, err)
 	require.Empty(t, res.Events)
 
 	ctx = ctx.WithEventManager(sdk.NewEventManager())
 	ctx.EventManager().EmitEvent(sdk.NewEvent("test"))
-	res, err = sdk.WrapServiceResult(ctx, nil, nil)
+	res, err = sdk.WrapServiceResult(ctx, &testdata.Dog{}, nil)
 	require.NotNil(t, res)
 	require.Nil(t, err)
 	require.Len(t, res.Events, 1)
diff --git a/types/tx/middleware.go b/types/tx/middleware.go
index c99df63d95c6..e67b783796d9 100644
--- a/types/tx/middleware.go
+++ b/types/tx/middleware.go
@@ -3,6 +3,7 @@ package tx
 import (
 	context "context"
 
+	codectypes "github.com/cosmos/cosmos-sdk/codec/types"
 	abci "github.com/tendermint/tendermint/abci/types"
 
 	sdk "github.com/cosmos/cosmos-sdk/types"
@@ -21,12 +22,42 @@ type ResponseSimulateTx struct {
 	Result  *sdk.Result
 }
 
+// Response is the tx response type used in middlewares.
+type Response struct {
+	GasWanted uint64
+	GasUsed   uint64
+	// MsgResponses is an array containing each Msg service handler's response
+	// type, packed in an Any. This will get proto-serialized into the `Data` field
+	// in the ABCI Check/DeliverTx responses.
+	MsgResponses []*codectypes.Any
+	Log          string
+	Events       []abci.Event
+}
+
+// Request is the tx request type used in middlewares.
+type Request struct {
+	Tx      sdk.Tx
+	TxBytes []byte
+}
+
+// RequestCheckTx is the additional request type used in middlewares CheckTx
+// method.
+type RequestCheckTx struct {
+	Type abci.CheckTxType
+}
+
+// RequestCheckTx is the additional response type used in middlewares CheckTx
+// method.
+type ResponseCheckTx struct {
+	Priority int64
+}
+
 // TxHandler defines the baseapp's CheckTx, DeliverTx and Simulate respective
 // handlers. It is designed as a middleware stack.
 type Handler interface {
-	CheckTx(ctx context.Context, tx sdk.Tx, req abci.RequestCheckTx) (abci.ResponseCheckTx, error)
-	DeliverTx(ctx context.Context, tx sdk.Tx, req abci.RequestDeliverTx) (abci.ResponseDeliverTx, error)
-	SimulateTx(ctx context.Context, tx sdk.Tx, req RequestSimulateTx) (ResponseSimulateTx, error)
+	CheckTx(ctx context.Context, req Request, checkReq RequestCheckTx) (Response, ResponseCheckTx, error)
+	DeliverTx(ctx context.Context, req Request) (Response, error)
+	SimulateTx(ctx context.Context, req Request) (Response, error)
 }
 
 // TxMiddleware defines one layer of the TxHandler middleware stack.
diff --git a/types/tx/msgs.go b/types/tx/msgs.go
index 4c4ad9dcd04a..25e79c4457f8 100644
--- a/types/tx/msgs.go
+++ b/types/tx/msgs.go
@@ -7,6 +7,15 @@ import (
 	sdk "github.com/cosmos/cosmos-sdk/types"
 )
 
+const (
+	msgResponseInterfaceProtoName = "cosmos.tx.v1beta1.MsgResponse"
+)
+
+// MsgResponse is the interface all Msg server handlers' response types need to
+// implement. It's the interface that's representing all Msg responses packed
+// in Anys.
+type MsgResponse interface{}
+
 // SetMsgs takes a slice of sdk.Msg's and turn them into Any's.
 func SetMsgs(msgs []sdk.Msg) ([]*types.Any, error) {
 	anys := make([]*types.Any, len(msgs))
diff --git a/types/tx/types.go b/types/tx/types.go
index 43982731f1c4..006941b35f17 100644
--- a/types/tx/types.go
+++ b/types/tx/types.go
@@ -192,8 +192,12 @@ func (m *SignerInfo) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error {
 	return unpacker.UnpackAny(m.PublicKey, new(cryptotypes.PubKey))
 }
 
-// RegisterInterfaces registers the sdk.Tx interface.
+// RegisterInterfaces registers the sdk.Tx and MsgResponse interfaces.
+// Note: the registration of sdk.Msg is done in sdk.RegisterInterfaces, but it
+// could be moved inside this function.
 func RegisterInterfaces(registry codectypes.InterfaceRegistry) {
+	registry.RegisterInterface(msgResponseInterfaceProtoName, (*MsgResponse)(nil))
+
 	registry.RegisterInterface("cosmos.tx.v1beta1.Tx", (*sdk.Tx)(nil))
 	registry.RegisterImplementations((*sdk.Tx)(nil), &Tx{})
 }
diff --git a/x/auth/middleware/basic.go b/x/auth/middleware/basic.go
index 84654d390c3a..429c9a39537f 100644
--- a/x/auth/middleware/basic.go
+++ b/x/auth/middleware/basic.go
@@ -49,47 +49,47 @@ func validateBasicTxMsgs(msgs []sdk.Msg) error {
 }
 
 // CheckTx implements tx.Handler.CheckTx.
-func (txh validateBasicTxHandler) CheckTx(ctx context.Context, tx sdk.Tx, req abci.RequestCheckTx) (abci.ResponseCheckTx, error) {
+func (txh validateBasicTxHandler) CheckTx(ctx context.Context, req tx.Request, checkReq tx.RequestCheckTx) (tx.Response, tx.ResponseCheckTx, error) {
 	// no need to validate basic on recheck tx, call next middleware
-	if req.Type == abci.CheckTxType_Recheck {
-		return txh.next.CheckTx(ctx, tx, req)
+	if checkReq.Type == abci.CheckTxType_Recheck {
+		return txh.next.CheckTx(ctx, req, checkReq)
 	}
 
-	if err := validateBasicTxMsgs(tx.GetMsgs()); err != nil {
-		return abci.ResponseCheckTx{}, err
+	if err := validateBasicTxMsgs(req.Tx.GetMsgs()); err != nil {
+		return tx.Response{}, tx.ResponseCheckTx{}, err
 	}
 
-	if err := tx.ValidateBasic(); err != nil {
-		return abci.ResponseCheckTx{}, err
+	if err := req.Tx.ValidateBasic(); err != nil {
+		return tx.Response{}, tx.ResponseCheckTx{}, err
 	}
 
-	return txh.next.CheckTx(ctx, tx, req)
+	return txh.next.CheckTx(ctx, req, checkReq)
 }
 
 // DeliverTx implements tx.Handler.DeliverTx.
-func (txh validateBasicTxHandler) DeliverTx(ctx context.Context, tx sdk.Tx, req abci.RequestDeliverTx) (abci.ResponseDeliverTx, error) {
-	if err := tx.ValidateBasic(); err != nil {
-		return abci.ResponseDeliverTx{}, err
+func (txh validateBasicTxHandler) DeliverTx(ctx context.Context, req tx.Request) (tx.Response, error) {
+	if err := req.Tx.ValidateBasic(); err != nil {
+		return tx.Response{}, err
 	}
 
-	if err := validateBasicTxMsgs(tx.GetMsgs()); err != nil {
-		return abci.ResponseDeliverTx{}, err
+	if err := validateBasicTxMsgs(req.Tx.GetMsgs()); err != nil {
+		return tx.Response{}, err
 	}
 
-	return txh.next.DeliverTx(ctx, tx, req)
+	return txh.next.DeliverTx(ctx, req)
 }
 
 // SimulateTx implements tx.Handler.SimulateTx.
-func (txh validateBasicTxHandler) SimulateTx(ctx context.Context, sdkTx sdk.Tx, req tx.RequestSimulateTx) (tx.ResponseSimulateTx, error) {
-	if err := sdkTx.ValidateBasic(); err != nil {
-		return tx.ResponseSimulateTx{}, err
+func (txh validateBasicTxHandler) SimulateTx(ctx context.Context, req tx.Request) (tx.Response, error) {
+	if err := req.Tx.ValidateBasic(); err != nil {
+		return tx.Response{}, err
 	}
 
-	if err := validateBasicTxMsgs(sdkTx.GetMsgs()); err != nil {
-		return tx.ResponseSimulateTx{}, err
+	if err := validateBasicTxMsgs(req.Tx.GetMsgs()); err != nil {
+		return tx.Response{}, err
 	}
 
-	return txh.next.SimulateTx(ctx, sdkTx, req)
+	return txh.next.SimulateTx(ctx, req)
 }
 
 var _ tx.Handler = txTimeoutHeightTxHandler{}
@@ -124,30 +124,30 @@ func checkTimeout(ctx context.Context, tx sdk.Tx) error {
 }
 
 // CheckTx implements tx.Handler.CheckTx.
-func (txh txTimeoutHeightTxHandler) CheckTx(ctx context.Context, tx sdk.Tx, req abci.RequestCheckTx) (abci.ResponseCheckTx, error) {
-	if err := checkTimeout(ctx, tx); err != nil {
-		return abci.ResponseCheckTx{}, err
+func (txh txTimeoutHeightTxHandler) CheckTx(ctx context.Context, req tx.Request, checkReq tx.RequestCheckTx) (tx.Response, tx.ResponseCheckTx, error) {
+	if err := checkTimeout(ctx, req.Tx); err != nil {
+		return tx.Response{}, tx.ResponseCheckTx{}, err
 	}
 
-	return txh.next.CheckTx(ctx, tx, req)
+	return txh.next.CheckTx(ctx, req, checkReq)
 }
 
 // DeliverTx implements tx.Handler.DeliverTx.
-func (txh txTimeoutHeightTxHandler) DeliverTx(ctx context.Context, tx sdk.Tx, req abci.RequestDeliverTx) (abci.ResponseDeliverTx, error) {
-	if err := checkTimeout(ctx, tx); err != nil {
-		return abci.ResponseDeliverTx{}, err
+func (txh txTimeoutHeightTxHandler) DeliverTx(ctx context.Context, req tx.Request) (tx.Response, error) {
+	if err := checkTimeout(ctx, req.Tx); err != nil {
+		return tx.Response{}, err
 	}
 
-	return txh.next.DeliverTx(ctx, tx, req)
+	return txh.next.DeliverTx(ctx, req)
 }
 
 // SimulateTx implements tx.Handler.SimulateTx.
-func (txh txTimeoutHeightTxHandler) SimulateTx(ctx context.Context, sdkTx sdk.Tx, req tx.RequestSimulateTx) (tx.ResponseSimulateTx, error) {
-	if err := checkTimeout(ctx, sdkTx); err != nil {
-		return tx.ResponseSimulateTx{}, err
+func (txh txTimeoutHeightTxHandler) SimulateTx(ctx context.Context, req tx.Request) (tx.Response, error) {
+	if err := checkTimeout(ctx, req.Tx); err != nil {
+		return tx.Response{}, err
 	}
 
-	return txh.next.SimulateTx(ctx, sdkTx, req)
+	return txh.next.SimulateTx(ctx, req)
 }
 
 type validateMemoTxHandler struct {
@@ -190,30 +190,30 @@ func (vmm validateMemoTxHandler) checkForValidMemo(ctx context.Context, tx sdk.T
 }
 
 // CheckTx implements tx.Handler.CheckTx method.
-func (vmm validateMemoTxHandler) CheckTx(ctx context.Context, tx sdk.Tx, req abci.RequestCheckTx) (abci.ResponseCheckTx, error) {
-	if err := vmm.checkForValidMemo(ctx, tx); err != nil {
-		return abci.ResponseCheckTx{}, err
+func (vmm validateMemoTxHandler) CheckTx(ctx context.Context, req tx.Request, checkReq tx.RequestCheckTx) (tx.Response, tx.ResponseCheckTx, error) {
+	if err := vmm.checkForValidMemo(ctx, req.Tx); err != nil {
+		return tx.Response{}, tx.ResponseCheckTx{}, err
 	}
 
-	return vmm.next.CheckTx(ctx, tx, req)
+	return vmm.next.CheckTx(ctx, req, checkReq)
 }
 
 // DeliverTx implements tx.Handler.DeliverTx method.
-func (vmm validateMemoTxHandler) DeliverTx(ctx context.Context, tx sdk.Tx, req abci.RequestDeliverTx) (abci.ResponseDeliverTx, error) {
-	if err := vmm.checkForValidMemo(ctx, tx); err != nil {
-		return abci.ResponseDeliverTx{}, err
+func (vmm validateMemoTxHandler) DeliverTx(ctx context.Context, req tx.Request) (tx.Response, error) {
+	if err := vmm.checkForValidMemo(ctx, req.Tx); err != nil {
+		return tx.Response{}, err
 	}
 
-	return vmm.next.DeliverTx(ctx, tx, req)
+	return vmm.next.DeliverTx(ctx, req)
 }
 
 // SimulateTx implements tx.Handler.SimulateTx method.
-func (vmm validateMemoTxHandler) SimulateTx(ctx context.Context, sdkTx sdk.Tx, req tx.RequestSimulateTx) (tx.ResponseSimulateTx, error) {
-	if err := vmm.checkForValidMemo(ctx, sdkTx); err != nil {
-		return tx.ResponseSimulateTx{}, err
+func (vmm validateMemoTxHandler) SimulateTx(ctx context.Context, req tx.Request) (tx.Response, error) {
+	if err := vmm.checkForValidMemo(ctx, req.Tx); err != nil {
+		return tx.Response{}, err
 	}
 
-	return vmm.next.SimulateTx(ctx, sdkTx, req)
+	return vmm.next.SimulateTx(ctx, req)
 }
 
 var _ tx.Handler = consumeTxSizeGasTxHandler{}
@@ -305,34 +305,34 @@ func (cgts consumeTxSizeGasTxHandler) consumeTxSizeGas(ctx context.Context, _ sd
 }
 
 // CheckTx implements tx.Handler.CheckTx.
-func (cgts consumeTxSizeGasTxHandler) CheckTx(ctx context.Context, tx sdk.Tx, req abci.RequestCheckTx) (abci.ResponseCheckTx, error) {
-	if err := cgts.consumeTxSizeGas(ctx, tx, req.GetTx()); err != nil {
-		return abci.ResponseCheckTx{}, err
+func (cgts consumeTxSizeGasTxHandler) CheckTx(ctx context.Context, req tx.Request, checkReq tx.RequestCheckTx) (tx.Response, tx.ResponseCheckTx, error) {
+	if err := cgts.consumeTxSizeGas(ctx, req.Tx, req.TxBytes); err != nil {
+		return tx.Response{}, tx.ResponseCheckTx{}, err
 	}
 
-	return cgts.next.CheckTx(ctx, tx, req)
+	return cgts.next.CheckTx(ctx, req, checkReq)
 }
 
 // DeliverTx implements tx.Handler.DeliverTx.
-func (cgts consumeTxSizeGasTxHandler) DeliverTx(ctx context.Context, tx sdk.Tx, req abci.RequestDeliverTx) (abci.ResponseDeliverTx, error) {
-	if err := cgts.consumeTxSizeGas(ctx, tx, req.GetTx()); err != nil {
-		return abci.ResponseDeliverTx{}, err
+func (cgts consumeTxSizeGasTxHandler) DeliverTx(ctx context.Context, req tx.Request) (tx.Response, error) {
+	if err := cgts.consumeTxSizeGas(ctx, req.Tx, req.TxBytes); err != nil {
+		return tx.Response{}, err
 	}
 
-	return cgts.next.DeliverTx(ctx, tx, req)
+	return cgts.next.DeliverTx(ctx, req)
 }
 
 // SimulateTx implements tx.Handler.SimulateTx.
-func (cgts consumeTxSizeGasTxHandler) SimulateTx(ctx context.Context, sdkTx sdk.Tx, req tx.RequestSimulateTx) (tx.ResponseSimulateTx, error) {
-	if err := cgts.consumeTxSizeGas(ctx, sdkTx, req.TxBytes); err != nil {
-		return tx.ResponseSimulateTx{}, err
+func (cgts consumeTxSizeGasTxHandler) SimulateTx(ctx context.Context, req tx.Request) (tx.Response, error) {
+	if err := cgts.consumeTxSizeGas(ctx, req.Tx, req.TxBytes); err != nil {
+		return tx.Response{}, err
 	}
 
-	if err := cgts.simulateSigGasCost(ctx, sdkTx); err != nil {
-		return tx.ResponseSimulateTx{}, err
+	if err := cgts.simulateSigGasCost(ctx, req.Tx); err != nil {
+		return tx.Response{}, err
 	}
 
-	return cgts.next.SimulateTx(ctx, sdkTx, req)
+	return cgts.next.SimulateTx(ctx, req)
 }
 
 // isIncompleteSignature tests whether SignatureData is fully filled in for simulation purposes
diff --git a/x/auth/middleware/basic_test.go b/x/auth/middleware/basic_test.go
index 8e1ad1db6a30..6e067306691a 100644
--- a/x/auth/middleware/basic_test.go
+++ b/x/auth/middleware/basic_test.go
@@ -10,7 +10,6 @@ import (
 	"github.com/cosmos/cosmos-sdk/types/tx"
 	"github.com/cosmos/cosmos-sdk/types/tx/signing"
 	"github.com/cosmos/cosmos-sdk/x/auth/middleware"
-	"github.com/tendermint/tendermint/abci/types"
 )
 
 func (s *MWTestSuite) TestValidateBasic() {
@@ -34,21 +33,21 @@ func (s *MWTestSuite) TestValidateBasic() {
 	invalidTx, _, err := s.createTestTx(txBuilder, privs, accNums, accSeqs, ctx.ChainID())
 	s.Require().NoError(err)
 
-	_, err = txHandler.DeliverTx(sdk.WrapSDKContext(ctx), invalidTx, types.RequestDeliverTx{})
+	_, err = txHandler.DeliverTx(sdk.WrapSDKContext(ctx), tx.Request{Tx: invalidTx})
 	s.Require().NotNil(err, "Did not error on invalid tx")
 
 	privs, accNums, accSeqs = []cryptotypes.PrivKey{priv1}, []uint64{0}, []uint64{0}
 	validTx, _, err := s.createTestTx(txBuilder, privs, accNums, accSeqs, ctx.ChainID())
 	s.Require().NoError(err)
 
-	_, err = txHandler.DeliverTx(sdk.WrapSDKContext(ctx), validTx, types.RequestDeliverTx{})
+	_, err = txHandler.DeliverTx(sdk.WrapSDKContext(ctx), tx.Request{Tx: validTx})
 	s.Require().Nil(err, "ValidateBasicMiddleware returned error on valid tx. err: %v", err)
 
 	// test middleware skips on recheck
 	ctx = ctx.WithIsReCheckTx(true)
 
 	// middleware should skip processing invalidTx on recheck and thus return nil-error
-	_, err = txHandler.DeliverTx(sdk.WrapSDKContext(ctx), invalidTx, types.RequestDeliverTx{})
+	_, err = txHandler.DeliverTx(sdk.WrapSDKContext(ctx), tx.Request{Tx: invalidTx})
 	s.Require().Nil(err, "ValidateBasicMiddleware ran on ReCheck")
 }
 
@@ -74,7 +73,7 @@ func (s *MWTestSuite) TestValidateMemo() {
 	s.Require().NoError(err)
 
 	// require that long memos get rejected
-	_, err = txHandler.DeliverTx(sdk.WrapSDKContext(ctx), invalidTx, types.RequestDeliverTx{})
+	_, err = txHandler.DeliverTx(sdk.WrapSDKContext(ctx), tx.Request{Tx: invalidTx})
 
 	s.Require().NotNil(err, "Did not error on tx with high memo")
 
@@ -83,7 +82,7 @@ func (s *MWTestSuite) TestValidateMemo() {
 	s.Require().NoError(err)
 
 	// require small memos pass ValidateMemo middleware
-	_, err = txHandler.DeliverTx(sdk.WrapSDKContext(ctx), validTx, types.RequestDeliverTx{})
+	_, err = txHandler.DeliverTx(sdk.WrapSDKContext(ctx), tx.Request{Tx: validTx})
 	s.Require().Nil(err, "ValidateBasicMiddleware returned error on valid tx. err: %v", err)
 }
 
@@ -137,7 +136,7 @@ func (s *MWTestSuite) TestConsumeGasForTxSize() {
 			expectedGas += afterGas - beforeGas
 
 			beforeGas = ctx.GasMeter().GasConsumed()
-			_, err = txHandler.DeliverTx(sdk.WrapSDKContext(ctx), testTx, types.RequestDeliverTx{Tx: txBytes})
+			_, err = txHandler.DeliverTx(sdk.WrapSDKContext(ctx), tx.Request{Tx: testTx, TxBytes: txBytes})
 
 			s.Require().Nil(err, "ConsumeTxSizeGasMiddleware returned error: %v", err)
 
@@ -162,7 +161,7 @@ func (s *MWTestSuite) TestConsumeGasForTxSize() {
 			beforeSimGas := ctx.GasMeter().GasConsumed()
 
 			// run txhandler in simulate mode
-			_, err = txHandler.SimulateTx(sdk.WrapSDKContext(ctx), testTx, tx.RequestSimulateTx{TxBytes: simTxBytes})
+			_, err = txHandler.SimulateTx(sdk.WrapSDKContext(ctx), tx.Request{Tx: testTx, TxBytes: simTxBytes})
 			consumedSimGas := ctx.GasMeter().GasConsumed() - beforeSimGas
 
 			// require that txhandler passes and does not underestimate middleware cost
@@ -215,7 +214,7 @@ func (s *MWTestSuite) TestTxHeightTimeoutMiddleware() {
 			s.Require().NoError(err)
 
 			ctx := ctx.WithBlockHeight(tc.height)
-			_, err = txHandler.SimulateTx(sdk.WrapSDKContext(ctx), testTx, tx.RequestSimulateTx{})
+			_, err = txHandler.SimulateTx(sdk.WrapSDKContext(ctx), tx.Request{Tx: testTx})
 			s.Require().Equal(tc.expectErr, err != nil, err)
 		})
 	}
diff --git a/x/auth/middleware/ext.go b/x/auth/middleware/ext.go
index 3fec1f674a47..783c3bbc476b 100644
--- a/x/auth/middleware/ext.go
+++ b/x/auth/middleware/ext.go
@@ -3,8 +3,6 @@ package middleware
 import (
 	"context"
 
-	abci "github.com/tendermint/tendermint/abci/types"
-
 	codectypes "github.com/cosmos/cosmos-sdk/codec/types"
 	sdk "github.com/cosmos/cosmos-sdk/types"
 	sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
@@ -44,28 +42,28 @@ func checkExtOpts(tx sdk.Tx) error {
 }
 
 // CheckTx implements tx.Handler.CheckTx.
-func (txh rejectExtensionOptionsTxHandler) CheckTx(ctx context.Context, tx sdk.Tx, req abci.RequestCheckTx) (abci.ResponseCheckTx, error) {
-	if err := checkExtOpts(tx); err != nil {
-		return abci.ResponseCheckTx{}, err
+func (txh rejectExtensionOptionsTxHandler) CheckTx(ctx context.Context, req tx.Request, checkReq tx.RequestCheckTx) (tx.Response, tx.ResponseCheckTx, error) {
+	if err := checkExtOpts(req.Tx); err != nil {
+		return tx.Response{}, tx.ResponseCheckTx{}, err
 	}
 
-	return txh.next.CheckTx(ctx, tx, req)
+	return txh.next.CheckTx(ctx, req, checkReq)
 }
 
 // DeliverTx implements tx.Handler.DeliverTx.
-func (txh rejectExtensionOptionsTxHandler) DeliverTx(ctx context.Context, tx sdk.Tx, req abci.RequestDeliverTx) (abci.ResponseDeliverTx, error) {
-	if err := checkExtOpts(tx); err != nil {
-		return abci.ResponseDeliverTx{}, err
+func (txh rejectExtensionOptionsTxHandler) DeliverTx(ctx context.Context, req tx.Request) (tx.Response, error) {
+	if err := checkExtOpts(req.Tx); err != nil {
+		return tx.Response{}, err
 	}
 
-	return txh.next.DeliverTx(ctx, tx, req)
+	return txh.next.DeliverTx(ctx, req)
 }
 
 // SimulateTx implements tx.Handler.SimulateTx method.
-func (txh rejectExtensionOptionsTxHandler) SimulateTx(ctx context.Context, sdkTx sdk.Tx, req tx.RequestSimulateTx) (tx.ResponseSimulateTx, error) {
-	if err := checkExtOpts(sdkTx); err != nil {
-		return tx.ResponseSimulateTx{}, err
+func (txh rejectExtensionOptionsTxHandler) SimulateTx(ctx context.Context, req tx.Request) (tx.Response, error) {
+	if err := checkExtOpts(req.Tx); err != nil {
+		return tx.Response{}, err
 	}
 
-	return txh.next.SimulateTx(ctx, sdkTx, req)
+	return txh.next.SimulateTx(ctx, req)
 }
diff --git a/x/auth/middleware/ext_test.go b/x/auth/middleware/ext_test.go
index a2fd323e3bb8..db2714536463 100644
--- a/x/auth/middleware/ext_test.go
+++ b/x/auth/middleware/ext_test.go
@@ -4,9 +4,9 @@ import (
 	"github.com/cosmos/cosmos-sdk/codec/types"
 	"github.com/cosmos/cosmos-sdk/testutil/testdata"
 	sdk "github.com/cosmos/cosmos-sdk/types"
+	typestx "github.com/cosmos/cosmos-sdk/types/tx"
 	"github.com/cosmos/cosmos-sdk/x/auth/middleware"
 	"github.com/cosmos/cosmos-sdk/x/auth/tx"
-	abci "github.com/tendermint/tendermint/abci/types"
 )
 
 func (s *MWTestSuite) TestRejectExtensionOptionsMiddleware() {
@@ -17,7 +17,7 @@ func (s *MWTestSuite) TestRejectExtensionOptionsMiddleware() {
 
 	// no extension options should not trigger an error
 	theTx := txBuilder.GetTx()
-	_, err := txHandler.CheckTx(sdk.WrapSDKContext(ctx), theTx, abci.RequestCheckTx{})
+	_, _, err := txHandler.CheckTx(sdk.WrapSDKContext(ctx), typestx.Request{Tx: theTx}, typestx.RequestCheckTx{})
 	s.Require().NoError(err)
 
 	extOptsTxBldr, ok := txBuilder.(tx.ExtensionOptionsTxBuilder)
@@ -31,6 +31,6 @@ func (s *MWTestSuite) TestRejectExtensionOptionsMiddleware() {
 	s.Require().NoError(err)
 	extOptsTxBldr.SetExtensionOptions(any)
 	theTx = txBuilder.GetTx()
-	_, err = txHandler.CheckTx(sdk.WrapSDKContext(ctx), theTx, abci.RequestCheckTx{})
+	_, _, err = txHandler.CheckTx(sdk.WrapSDKContext(ctx), typestx.Request{Tx: theTx}, typestx.RequestCheckTx{})
 	s.Require().EqualError(err, "unknown extension options")
 }
diff --git a/x/auth/middleware/fee.go b/x/auth/middleware/fee.go
index 4d980fb059a5..426631b60d43 100644
--- a/x/auth/middleware/fee.go
+++ b/x/auth/middleware/fee.go
@@ -4,8 +4,6 @@ import (
 	"context"
 	"fmt"
 
-	abci "github.com/tendermint/tendermint/abci/types"
-
 	sdk "github.com/cosmos/cosmos-sdk/types"
 	sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
 	"github.com/cosmos/cosmos-sdk/types/tx"
@@ -36,12 +34,12 @@ func MempoolFeeMiddleware(txh tx.Handler) tx.Handler {
 // and the transaction does not meet the minimum, the transaction is rejected.
 //
 // Recall, a transaction's fee is determined by ceil(minGasPrice * gasLimit).
-func (txh mempoolFeeTxHandler) CheckTx(ctx context.Context, tx sdk.Tx, req abci.RequestCheckTx) (abci.ResponseCheckTx, error) {
+func (txh mempoolFeeTxHandler) CheckTx(ctx context.Context, req tx.Request, checkReq tx.RequestCheckTx) (tx.Response, tx.ResponseCheckTx, error) {
 	sdkCtx := sdk.UnwrapSDKContext(ctx)
 
-	feeTx, ok := tx.(sdk.FeeTx)
+	feeTx, ok := req.Tx.(sdk.FeeTx)
 	if !ok {
-		return abci.ResponseCheckTx{}, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "Tx must be a FeeTx")
+		return tx.Response{}, tx.ResponseCheckTx{}, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "Tx must be a FeeTx")
 	}
 
 	feeCoins := feeTx.GetFee()
@@ -63,21 +61,21 @@ func (txh mempoolFeeTxHandler) CheckTx(ctx context.Context, tx sdk.Tx, req abci.
 		}
 
 		if !feeCoins.IsAnyGTE(requiredFees) {
-			return abci.ResponseCheckTx{}, sdkerrors.Wrapf(sdkerrors.ErrInsufficientFee, "insufficient fees; got: %s required: %s", feeCoins, requiredFees)
+			return tx.Response{}, tx.ResponseCheckTx{}, sdkerrors.Wrapf(sdkerrors.ErrInsufficientFee, "insufficient fees; got: %s required: %s", feeCoins, requiredFees)
 		}
 	}
 
-	return txh.next.CheckTx(ctx, tx, req)
+	return txh.next.CheckTx(ctx, req, checkReq)
 }
 
 // DeliverTx implements tx.Handler.DeliverTx.
-func (txh mempoolFeeTxHandler) DeliverTx(ctx context.Context, tx sdk.Tx, req abci.RequestDeliverTx) (abci.ResponseDeliverTx, error) {
-	return txh.next.DeliverTx(ctx, tx, req)
+func (txh mempoolFeeTxHandler) DeliverTx(ctx context.Context, req tx.Request) (tx.Response, error) {
+	return txh.next.DeliverTx(ctx, req)
 }
 
 // SimulateTx implements tx.Handler.SimulateTx.
-func (txh mempoolFeeTxHandler) SimulateTx(ctx context.Context, tx sdk.Tx, req tx.RequestSimulateTx) (tx.ResponseSimulateTx, error) {
-	return txh.next.SimulateTx(ctx, tx, req)
+func (txh mempoolFeeTxHandler) SimulateTx(ctx context.Context, req tx.Request) (tx.Response, error) {
+	return txh.next.SimulateTx(ctx, req)
 }
 
 var _ tx.Handler = deductFeeTxHandler{}
@@ -104,9 +102,9 @@ func DeductFeeMiddleware(ak AccountKeeper, bk types.BankKeeper, fk FeegrantKeepe
 	}
 }
 
-func (dfd deductFeeTxHandler) checkDeductFee(ctx context.Context, tx sdk.Tx) error {
+func (dfd deductFeeTxHandler) checkDeductFee(ctx context.Context, sdkTx sdk.Tx) error {
 	sdkCtx := sdk.UnwrapSDKContext(ctx)
-	feeTx, ok := tx.(sdk.FeeTx)
+	feeTx, ok := sdkTx.(sdk.FeeTx)
 	if !ok {
 		return sdkerrors.Wrap(sdkerrors.ErrTxDecode, "Tx must be a FeeTx")
 	}
@@ -127,7 +125,7 @@ func (dfd deductFeeTxHandler) checkDeductFee(ctx context.Context, tx sdk.Tx) err
 		if dfd.feegrantKeeper == nil {
 			return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "fee grants are not enabled")
 		} else if !feeGranter.Equals(feePayer) {
-			err := dfd.feegrantKeeper.UseGrantedFees(sdkCtx, feeGranter, feePayer, fee, tx.GetMsgs())
+			err := dfd.feegrantKeeper.UseGrantedFees(sdkCtx, feeGranter, feePayer, fee, sdkTx.GetMsgs())
 
 			if err != nil {
 				return sdkerrors.Wrapf(err, "%s not allowed to pay fees from %s", feeGranter, feePayer)
@@ -159,29 +157,29 @@ func (dfd deductFeeTxHandler) checkDeductFee(ctx context.Context, tx sdk.Tx) err
 }
 
 // CheckTx implements tx.Handler.CheckTx.
-func (dfd deductFeeTxHandler) CheckTx(ctx context.Context, tx sdk.Tx, req abci.RequestCheckTx) (abci.ResponseCheckTx, error) {
-	if err := dfd.checkDeductFee(ctx, tx); err != nil {
-		return abci.ResponseCheckTx{}, err
+func (dfd deductFeeTxHandler) CheckTx(ctx context.Context, req tx.Request, checkReq tx.RequestCheckTx) (tx.Response, tx.ResponseCheckTx, error) {
+	if err := dfd.checkDeductFee(ctx, req.Tx); err != nil {
+		return tx.Response{}, tx.ResponseCheckTx{}, err
 	}
 
-	return dfd.next.CheckTx(ctx, tx, req)
+	return dfd.next.CheckTx(ctx, req, checkReq)
 }
 
 // DeliverTx implements tx.Handler.DeliverTx.
-func (dfd deductFeeTxHandler) DeliverTx(ctx context.Context, tx sdk.Tx, req abci.RequestDeliverTx) (abci.ResponseDeliverTx, error) {
-	if err := dfd.checkDeductFee(ctx, tx); err != nil {
-		return abci.ResponseDeliverTx{}, err
+func (dfd deductFeeTxHandler) DeliverTx(ctx context.Context, req tx.Request) (tx.Response, error) {
+	if err := dfd.checkDeductFee(ctx, req.Tx); err != nil {
+		return tx.Response{}, err
 	}
 
-	return dfd.next.DeliverTx(ctx, tx, req)
+	return dfd.next.DeliverTx(ctx, req)
 }
 
-func (dfd deductFeeTxHandler) SimulateTx(ctx context.Context, sdkTx sdk.Tx, req tx.RequestSimulateTx) (tx.ResponseSimulateTx, error) {
-	if err := dfd.checkDeductFee(ctx, sdkTx); err != nil {
-		return tx.ResponseSimulateTx{}, err
+func (dfd deductFeeTxHandler) SimulateTx(ctx context.Context, req tx.Request) (tx.Response, error) {
+	if err := dfd.checkDeductFee(ctx, req.Tx); err != nil {
+		return tx.Response{}, err
 	}
 
-	return dfd.next.SimulateTx(ctx, sdkTx, req)
+	return dfd.next.SimulateTx(ctx, req)
 }
 
 // DeductFees deducts fees from the given account.
diff --git a/x/auth/middleware/fee_test.go b/x/auth/middleware/fee_test.go
index 219d790d0d61..3a60558e0da0 100644
--- a/x/auth/middleware/fee_test.go
+++ b/x/auth/middleware/fee_test.go
@@ -4,9 +4,9 @@ import (
 	cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
 	"github.com/cosmos/cosmos-sdk/testutil/testdata"
 	sdk "github.com/cosmos/cosmos-sdk/types"
+	"github.com/cosmos/cosmos-sdk/types/tx"
 	"github.com/cosmos/cosmos-sdk/x/auth/middleware"
 	"github.com/cosmos/cosmos-sdk/x/bank/testutil"
-	abci "github.com/tendermint/tendermint/abci/types"
 )
 
 func (s *MWTestSuite) TestEnsureMempoolFees() {
@@ -27,7 +27,7 @@ func (s *MWTestSuite) TestEnsureMempoolFees() {
 	txBuilder.SetGasLimit(gasLimit)
 
 	privs, accNums, accSeqs := []cryptotypes.PrivKey{priv1}, []uint64{0}, []uint64{0}
-	tx, _, err := s.createTestTx(txBuilder, privs, accNums, accSeqs, ctx.ChainID())
+	testTx, _, err := s.createTestTx(txBuilder, privs, accNums, accSeqs, ctx.ChainID())
 	s.Require().NoError(err)
 
 	// Set high gas price so standard test fee fails
@@ -36,18 +36,18 @@ func (s *MWTestSuite) TestEnsureMempoolFees() {
 	ctx = ctx.WithMinGasPrices(highGasPrice)
 
 	// txHandler errors with insufficient fees
-	_, err = txHandler.CheckTx(sdk.WrapSDKContext(ctx), tx, abci.RequestCheckTx{})
+	_, _, err = txHandler.CheckTx(sdk.WrapSDKContext(ctx), tx.Request{Tx: testTx}, tx.RequestCheckTx{})
 	s.Require().NotNil(err, "Middleware should have errored on too low fee for local gasPrice")
 
 	// txHandler should not error since we do not check minGasPrice in DeliverTx
-	_, err = txHandler.DeliverTx(sdk.WrapSDKContext(ctx), tx, abci.RequestDeliverTx{})
+	_, err = txHandler.DeliverTx(sdk.WrapSDKContext(ctx), tx.Request{Tx: testTx})
 	s.Require().Nil(err, "MempoolFeeMiddleware returned error in DeliverTx")
 
 	atomPrice = sdk.NewDecCoinFromDec("atom", sdk.NewDec(0).Quo(sdk.NewDec(100000)))
 	lowGasPrice := []sdk.DecCoin{atomPrice}
 	ctx = ctx.WithMinGasPrices(lowGasPrice)
 
-	_, err = txHandler.CheckTx(sdk.WrapSDKContext(ctx), tx, abci.RequestCheckTx{})
+	_, _, err = txHandler.CheckTx(sdk.WrapSDKContext(ctx), tx.Request{Tx: testTx}, tx.RequestCheckTx{})
 	s.Require().Nil(err, "Middleware should not have errored on fee higher than local gasPrice")
 }
 
@@ -75,7 +75,7 @@ func (s *MWTestSuite) TestDeductFees() {
 	txBuilder.SetGasLimit(gasLimit)
 
 	privs, accNums, accSeqs := []cryptotypes.PrivKey{priv1}, []uint64{0}, []uint64{0}
-	tx, _, err := s.createTestTx(txBuilder, privs, accNums, accSeqs, ctx.ChainID())
+	testTx, _, err := s.createTestTx(txBuilder, privs, accNums, accSeqs, ctx.ChainID())
 	s.Require().NoError(err)
 
 	// Set account with insufficient funds
@@ -85,7 +85,7 @@ func (s *MWTestSuite) TestDeductFees() {
 	err = testutil.FundAccount(s.app.BankKeeper, ctx, addr1, coins)
 	s.Require().NoError(err)
 
-	_, err = txHandler.DeliverTx(sdk.WrapSDKContext(ctx), tx, abci.RequestDeliverTx{})
+	_, err = txHandler.DeliverTx(sdk.WrapSDKContext(ctx), tx.Request{Tx: testTx})
 	s.Require().NotNil(err, "Tx did not error when fee payer had insufficient funds")
 
 	// Set account with sufficient funds
@@ -93,7 +93,7 @@ func (s *MWTestSuite) TestDeductFees() {
 	err = testutil.FundAccount(s.app.BankKeeper, ctx, addr1, sdk.NewCoins(sdk.NewCoin("atom", sdk.NewInt(200))))
 	s.Require().NoError(err)
 
-	_, err = txHandler.DeliverTx(sdk.WrapSDKContext(ctx), tx, abci.RequestDeliverTx{})
+	_, err = txHandler.DeliverTx(sdk.WrapSDKContext(ctx), tx.Request{Tx: testTx})
 
 	s.Require().Nil(err, "Tx errored after account has been set with sufficient funds")
 }
diff --git a/x/auth/middleware/feegrant_test.go b/x/auth/middleware/feegrant_test.go
index c76b3ec825e4..e9e1db2ced29 100644
--- a/x/auth/middleware/feegrant_test.go
+++ b/x/auth/middleware/feegrant_test.go
@@ -5,7 +5,6 @@ import (
 	"testing"
 	"time"
 
-	abci "github.com/tendermint/tendermint/abci/types"
 	"github.com/tendermint/tendermint/crypto"
 
 	"github.com/cosmos/cosmos-sdk/client"
@@ -15,6 +14,7 @@ import (
 	"github.com/cosmos/cosmos-sdk/testutil/testdata"
 	sdk "github.com/cosmos/cosmos-sdk/types"
 	"github.com/cosmos/cosmos-sdk/types/simulation"
+	txtypes "github.com/cosmos/cosmos-sdk/types/tx"
 	"github.com/cosmos/cosmos-sdk/types/tx/signing"
 	"github.com/cosmos/cosmos-sdk/x/auth/middleware"
 	authsign "github.com/cosmos/cosmos-sdk/x/auth/signing"
@@ -145,11 +145,11 @@ func (s *MWTestSuite) TestDeductFeesNoDelegation() {
 				accNums, seqs = []uint64{acc.GetAccountNumber()}, []uint64{acc.GetSequence()}
 			}
 
-			tx, err := genTxWithFeeGranter(protoTxCfg, msgs, fee, helpers.DefaultGenTxGas, ctx.ChainID(), accNums, seqs, tc.feeAccount, privs...)
+			testTx, err := genTxWithFeeGranter(protoTxCfg, msgs, fee, helpers.DefaultGenTxGas, ctx.ChainID(), accNums, seqs, tc.feeAccount, privs...)
 			s.Require().NoError(err)
 
 			// tests only feegrant middleware
-			_, err = txHandler.DeliverTx(sdk.WrapSDKContext(ctx), tx, abci.RequestDeliverTx{})
+			_, err = txHandler.DeliverTx(sdk.WrapSDKContext(ctx), txtypes.Request{Tx: testTx})
 			if tc.valid {
 				s.Require().NoError(err)
 			} else {
@@ -157,7 +157,7 @@ func (s *MWTestSuite) TestDeductFeesNoDelegation() {
 			}
 
 			// tests while stack
-			_, err = s.txHandler.DeliverTx(sdk.WrapSDKContext(ctx), tx, abci.RequestDeliverTx{})
+			_, err = s.txHandler.DeliverTx(sdk.WrapSDKContext(ctx), txtypes.Request{Tx: testTx})
 			if tc.valid {
 				s.Require().NoError(err)
 			} else {
diff --git a/x/auth/middleware/gas.go b/x/auth/middleware/gas.go
index b49ce43702cc..ee31fc1bff89 100644
--- a/x/auth/middleware/gas.go
+++ b/x/auth/middleware/gas.go
@@ -3,8 +3,6 @@ package middleware
 import (
 	"context"
 
-	abci "github.com/tendermint/tendermint/abci/types"
-
 	sdk "github.com/cosmos/cosmos-sdk/types"
 	sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
 	"github.com/cosmos/cosmos-sdk/types/tx"
@@ -30,47 +28,47 @@ func GasTxMiddleware(txh tx.Handler) tx.Handler {
 var _ tx.Handler = gasTxHandler{}
 
 // CheckTx implements tx.Handler.CheckTx.
-func (txh gasTxHandler) CheckTx(ctx context.Context, tx sdk.Tx, req abci.RequestCheckTx) (abci.ResponseCheckTx, error) {
-	sdkCtx, err := gasContext(sdk.UnwrapSDKContext(ctx), tx, false)
+func (txh gasTxHandler) CheckTx(ctx context.Context, req tx.Request, checkReq tx.RequestCheckTx) (tx.Response, tx.ResponseCheckTx, error) {
+	sdkCtx, err := gasContext(sdk.UnwrapSDKContext(ctx), req.Tx, false)
 	if err != nil {
-		return abci.ResponseCheckTx{}, err
+		return tx.Response{}, tx.ResponseCheckTx{}, err
 	}
 
-	res, err := txh.next.CheckTx(sdk.WrapSDKContext(sdkCtx), tx, req)
-	res.GasUsed = int64(sdkCtx.GasMeter().GasConsumed())
-	res.GasWanted = int64(sdkCtx.GasMeter().Limit())
+	res, resCheckTx, err := txh.next.CheckTx(sdk.WrapSDKContext(sdkCtx), req, checkReq)
 
-	return res, err
+	return populateGas(res, sdkCtx), resCheckTx, err
 }
 
 // DeliverTx implements tx.Handler.DeliverTx.
-func (txh gasTxHandler) DeliverTx(ctx context.Context, tx sdk.Tx, req abci.RequestDeliverTx) (abci.ResponseDeliverTx, error) {
-	sdkCtx, err := gasContext(sdk.UnwrapSDKContext(ctx), tx, false)
+func (txh gasTxHandler) DeliverTx(ctx context.Context, req tx.Request) (tx.Response, error) {
+	sdkCtx, err := gasContext(sdk.UnwrapSDKContext(ctx), req.Tx, false)
 	if err != nil {
-		return abci.ResponseDeliverTx{}, err
+		return tx.Response{}, err
 	}
 
-	res, err := txh.next.DeliverTx(sdk.WrapSDKContext(sdkCtx), tx, req)
-	res.GasUsed = int64(sdkCtx.GasMeter().GasConsumed())
-	res.GasWanted = int64(sdkCtx.GasMeter().Limit())
+	res, err := txh.next.DeliverTx(sdk.WrapSDKContext(sdkCtx), req)
 
-	return res, err
+	return populateGas(res, sdkCtx), err
 }
 
 // SimulateTx implements tx.Handler.SimulateTx method.
-func (txh gasTxHandler) SimulateTx(ctx context.Context, sdkTx sdk.Tx, req tx.RequestSimulateTx) (tx.ResponseSimulateTx, error) {
-	sdkCtx, err := gasContext(sdk.UnwrapSDKContext(ctx), sdkTx, true)
+func (txh gasTxHandler) SimulateTx(ctx context.Context, req tx.Request) (tx.Response, error) {
+	sdkCtx, err := gasContext(sdk.UnwrapSDKContext(ctx), req.Tx, true)
 	if err != nil {
-		return tx.ResponseSimulateTx{}, err
+		return tx.Response{}, err
 	}
 
-	res, err := txh.next.SimulateTx(sdk.WrapSDKContext(sdkCtx), sdkTx, req)
-	res.GasInfo = sdk.GasInfo{
-		GasWanted: sdkCtx.GasMeter().Limit(),
-		GasUsed:   sdkCtx.GasMeter().GasConsumed(),
-	}
+	res, err := txh.next.SimulateTx(sdk.WrapSDKContext(sdkCtx), req)
+
+	return populateGas(res, sdkCtx), err
+}
+
+// populateGas returns a new tx.Response with gas fields populated.
+func populateGas(res tx.Response, sdkCtx sdk.Context) tx.Response {
+	res.GasWanted = sdkCtx.GasMeter().Limit()
+	res.GasUsed = sdkCtx.GasMeter().GasConsumed()
 
-	return res, err
+	return res
 }
 
 // gasContext returns a new context with a gas meter set from a given context.
diff --git a/x/auth/middleware/gas_test.go b/x/auth/middleware/gas_test.go
index 30534ad7e8ad..f89492f16f6c 100644
--- a/x/auth/middleware/gas_test.go
+++ b/x/auth/middleware/gas_test.go
@@ -4,8 +4,6 @@ import (
 	"context"
 	"errors"
 
-	abci "github.com/tendermint/tendermint/abci/types"
-
 	cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
 	"github.com/cosmos/cosmos-sdk/testutil/testdata"
 	sdk "github.com/cosmos/cosmos-sdk/types"
@@ -51,7 +49,7 @@ func (s *MWTestSuite) setupGasTx() (signing.Tx, []byte, sdk.Context, uint64) {
 }
 
 func (s *MWTestSuite) TestSetup() {
-	tx, _, ctx, gasLimit := s.setupGasTx()
+	testTx, _, ctx, gasLimit := s.setupGasTx()
 	txHandler := middleware.ComposeMiddlewares(noopTxHandler{}, middleware.GasTxMiddleware)
 
 	testcases := []struct {
@@ -62,11 +60,11 @@ func (s *MWTestSuite) TestSetup() {
 		errorStr    string
 	}{
 		{"not a gas tx", txTest{}, 0, true, "Tx must be GasTx: tx parse error"},
-		{"tx with its own gas limit", tx, gasLimit, false, ""},
+		{"tx with its own gas limit", testTx, gasLimit, false, ""},
 	}
 	for _, tc := range testcases {
 		s.Run(tc.name, func() {
-			res, err := txHandler.CheckTx(sdk.WrapSDKContext(ctx), tc.tx, abci.RequestCheckTx{})
+			res, _, err := txHandler.CheckTx(sdk.WrapSDKContext(ctx), tx.Request{Tx: tc.tx}, tx.RequestCheckTx{})
 			if tc.expErr {
 				s.Require().EqualError(err, tc.errorStr)
 			} else {
@@ -78,15 +76,17 @@ func (s *MWTestSuite) TestSetup() {
 }
 
 func (s *MWTestSuite) TestRecoverPanic() {
-	tx, txBytes, ctx, gasLimit := s.setupGasTx()
+	testTx, txBytes, ctx, gasLimit := s.setupGasTx()
 	txHandler := middleware.ComposeMiddlewares(outOfGasTxHandler{}, middleware.GasTxMiddleware, middleware.RecoveryTxMiddleware)
-	res, err := txHandler.CheckTx(sdk.WrapSDKContext(ctx), tx, abci.RequestCheckTx{Tx: txBytes})
+	res, _, err := txHandler.CheckTx(sdk.WrapSDKContext(ctx), tx.Request{Tx: testTx, TxBytes: txBytes}, tx.RequestCheckTx{})
 	s.Require().Error(err, "Did not return error on OutOfGas panic")
 	s.Require().True(errors.Is(sdkerrors.ErrOutOfGas, err), "Returned error is not an out of gas error")
 	s.Require().Equal(gasLimit, uint64(res.GasWanted))
 
 	txHandler = middleware.ComposeMiddlewares(outOfGasTxHandler{}, middleware.GasTxMiddleware)
-	s.Require().Panics(func() { txHandler.CheckTx(sdk.WrapSDKContext(ctx), tx, abci.RequestCheckTx{Tx: txBytes}) }, "Recovered from non-Out-of-Gas panic")
+	s.Require().Panics(func() {
+		txHandler.CheckTx(sdk.WrapSDKContext(ctx), tx.Request{Tx: testTx, TxBytes: txBytes}, tx.RequestCheckTx{})
+	}, "Recovered from non-Out-of-Gas panic")
 }
 
 // outOfGasTxHandler is a test middleware that will throw OutOfGas panic.
@@ -94,7 +94,7 @@ type outOfGasTxHandler struct{}
 
 var _ tx.Handler = outOfGasTxHandler{}
 
-func (txh outOfGasTxHandler) DeliverTx(ctx context.Context, _ sdk.Tx, _ abci.RequestDeliverTx) (abci.ResponseDeliverTx, error) {
+func (txh outOfGasTxHandler) DeliverTx(ctx context.Context, _ tx.Request) (tx.Response, error) {
 	sdkCtx := sdk.UnwrapSDKContext(ctx)
 	overLimit := sdkCtx.GasMeter().Limit() + 1
 
@@ -103,7 +103,7 @@ func (txh outOfGasTxHandler) DeliverTx(ctx context.Context, _ sdk.Tx, _ abci.Req
 
 	panic("not reached")
 }
-func (txh outOfGasTxHandler) CheckTx(ctx context.Context, _ sdk.Tx, _ abci.RequestCheckTx) (abci.ResponseCheckTx, error) {
+func (txh outOfGasTxHandler) CheckTx(ctx context.Context, _ tx.Request, _ tx.RequestCheckTx) (tx.Response, tx.ResponseCheckTx, error) {
 	sdkCtx := sdk.UnwrapSDKContext(ctx)
 	overLimit := sdkCtx.GasMeter().Limit() + 1
 
@@ -112,7 +112,7 @@ func (txh outOfGasTxHandler) CheckTx(ctx context.Context, _ sdk.Tx, _ abci.Reque
 
 	panic("not reached")
 }
-func (txh outOfGasTxHandler) SimulateTx(ctx context.Context, _ sdk.Tx, _ tx.RequestSimulateTx) (tx.ResponseSimulateTx, error) {
+func (txh outOfGasTxHandler) SimulateTx(ctx context.Context, _ tx.Request) (tx.Response, error) {
 	sdkCtx := sdk.UnwrapSDKContext(ctx)
 	overLimit := sdkCtx.GasMeter().Limit() + 1
 
@@ -127,12 +127,12 @@ type noopTxHandler struct{}
 
 var _ tx.Handler = noopTxHandler{}
 
-func (txh noopTxHandler) CheckTx(_ context.Context, _ sdk.Tx, _ abci.RequestCheckTx) (abci.ResponseCheckTx, error) {
-	return abci.ResponseCheckTx{}, nil
+func (txh noopTxHandler) CheckTx(_ context.Context, _ tx.Request, _ tx.RequestCheckTx) (tx.Response, tx.ResponseCheckTx, error) {
+	return tx.Response{}, tx.ResponseCheckTx{}, nil
 }
-func (txh noopTxHandler) SimulateTx(_ context.Context, _ sdk.Tx, _ tx.RequestSimulateTx) (tx.ResponseSimulateTx, error) {
-	return tx.ResponseSimulateTx{}, nil
+func (txh noopTxHandler) SimulateTx(_ context.Context, _ tx.Request) (tx.Response, error) {
+	return tx.Response{}, nil
 }
-func (txh noopTxHandler) DeliverTx(ctx context.Context, _ sdk.Tx, _ abci.RequestDeliverTx) (abci.ResponseDeliverTx, error) {
-	return abci.ResponseDeliverTx{}, nil
+func (txh noopTxHandler) DeliverTx(ctx context.Context, _ tx.Request) (tx.Response, error) {
+	return tx.Response{}, nil
 }
diff --git a/x/auth/middleware/index_events.go b/x/auth/middleware/index_events.go
index 30c7aea40158..2dd831417c2e 100644
--- a/x/auth/middleware/index_events.go
+++ b/x/auth/middleware/index_events.go
@@ -3,8 +3,6 @@ package middleware
 import (
 	"context"
 
-	abci "github.com/tendermint/tendermint/abci/types"
-
 	sdk "github.com/cosmos/cosmos-sdk/types"
 	"github.com/cosmos/cosmos-sdk/types/tx"
 )
@@ -13,7 +11,7 @@ type indexEventsTxHandler struct {
 	// indexEvents defines the set of events in the form {eventType}.{attributeKey},
 	// which informs Tendermint what to index. If empty, all events will be indexed.
 	indexEvents map[string]struct{}
-	inner       tx.Handler
+	next        tx.Handler
 }
 
 // NewIndexEventsTxMiddleware defines a middleware to optionally only index a
@@ -22,7 +20,7 @@ func NewIndexEventsTxMiddleware(indexEvents map[string]struct{}) tx.Middleware {
 	return func(txHandler tx.Handler) tx.Handler {
 		return indexEventsTxHandler{
 			indexEvents: indexEvents,
-			inner:       txHandler,
+			next:        txHandler,
 		}
 	}
 }
@@ -30,19 +28,19 @@ func NewIndexEventsTxMiddleware(indexEvents map[string]struct{}) tx.Middleware {
 var _ tx.Handler = indexEventsTxHandler{}
 
 // CheckTx implements tx.Handler.CheckTx method.
-func (txh indexEventsTxHandler) CheckTx(ctx context.Context, tx sdk.Tx, req abci.RequestCheckTx) (abci.ResponseCheckTx, error) {
-	res, err := txh.inner.CheckTx(ctx, tx, req)
+func (txh indexEventsTxHandler) CheckTx(ctx context.Context, req tx.Request, checkReq tx.RequestCheckTx) (tx.Response, tx.ResponseCheckTx, error) {
+	res, resCheckTx, err := txh.next.CheckTx(ctx, req, checkReq)
 	if err != nil {
-		return res, err
+		return res, tx.ResponseCheckTx{}, err
 	}
 
 	res.Events = sdk.MarkEventsToIndex(res.Events, txh.indexEvents)
-	return res, nil
+	return res, resCheckTx, nil
 }
 
 // DeliverTx implements tx.Handler.DeliverTx method.
-func (txh indexEventsTxHandler) DeliverTx(ctx context.Context, tx sdk.Tx, req abci.RequestDeliverTx) (abci.ResponseDeliverTx, error) {
-	res, err := txh.inner.DeliverTx(ctx, tx, req)
+func (txh indexEventsTxHandler) DeliverTx(ctx context.Context, req tx.Request) (tx.Response, error) {
+	res, err := txh.next.DeliverTx(ctx, req)
 	if err != nil {
 		return res, err
 	}
@@ -52,12 +50,12 @@ func (txh indexEventsTxHandler) DeliverTx(ctx context.Context, tx sdk.Tx, req ab
 }
 
 // SimulateTx implements tx.Handler.SimulateTx method.
-func (txh indexEventsTxHandler) SimulateTx(ctx context.Context, tx sdk.Tx, req tx.RequestSimulateTx) (tx.ResponseSimulateTx, error) {
-	res, err := txh.inner.SimulateTx(ctx, tx, req)
+func (txh indexEventsTxHandler) SimulateTx(ctx context.Context, req tx.Request) (tx.Response, error) {
+	res, err := txh.next.SimulateTx(ctx, req)
 	if err != nil {
 		return res, err
 	}
 
-	res.Result.Events = sdk.MarkEventsToIndex(res.Result.Events, txh.indexEvents)
+	res.Events = sdk.MarkEventsToIndex(res.Events, txh.indexEvents)
 	return res, nil
 }
diff --git a/x/auth/middleware/middleware.go b/x/auth/middleware/middleware.go
index 365d7441ed02..a17cdd291ed7 100644
--- a/x/auth/middleware/middleware.go
+++ b/x/auth/middleware/middleware.go
@@ -50,15 +50,15 @@ type TxHandlerOptions struct {
 // for most applications.
 func NewDefaultTxHandler(options TxHandlerOptions) (tx.Handler, error) {
 	if options.AccountKeeper == nil {
-		return nil, sdkerrors.Wrap(sdkerrors.ErrLogic, "account keeper is required for compose middlewares")
+		return nil, sdkerrors.Wrap(sdkerrors.ErrLogic, "account keeper is required for middlewares")
 	}
 
 	if options.BankKeeper == nil {
-		return nil, sdkerrors.Wrap(sdkerrors.ErrLogic, "bank keeper is required for compose middlewares")
+		return nil, sdkerrors.Wrap(sdkerrors.ErrLogic, "bank keeper is required for middlewares")
 	}
 
 	if options.SignModeHandler == nil {
-		return nil, sdkerrors.Wrap(sdkerrors.ErrLogic, "sign mode handler is required for compose middlewares")
+		return nil, sdkerrors.Wrap(sdkerrors.ErrLogic, "sign mode handler is required for middlewares")
 	}
 
 	var sigGasConsumer = options.SigGasConsumer
@@ -89,7 +89,7 @@ func NewDefaultTxHandler(options TxHandlerOptions) (tx.Handler, error) {
 		ValidateMemoMiddleware(options.AccountKeeper),
 		ConsumeTxSizeGasMiddleware(options.AccountKeeper),
 		DeductFeeMiddleware(options.AccountKeeper, options.BankKeeper, options.FeegrantKeeper),
-		TxPriorityHandler,
+		TxPriorityMiddleware,
 		SetPubKeyMiddleware(options.AccountKeeper),
 		ValidateSigCountMiddleware(options.AccountKeeper),
 		SigGasConsumeMiddleware(options.AccountKeeper, sigGasConsumer),
diff --git a/x/auth/middleware/middleware_test.go b/x/auth/middleware/middleware_test.go
index d88e5cc6c1da..417ac8e7fcaa 100644
--- a/x/auth/middleware/middleware_test.go
+++ b/x/auth/middleware/middleware_test.go
@@ -14,6 +14,7 @@ import (
 	"github.com/cosmos/cosmos-sdk/testutil/testdata"
 	sdk "github.com/cosmos/cosmos-sdk/types"
 	sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
+	"github.com/cosmos/cosmos-sdk/types/tx"
 	"github.com/cosmos/cosmos-sdk/types/tx/signing"
 	"github.com/cosmos/cosmos-sdk/x/auth/middleware"
 	"github.com/cosmos/cosmos-sdk/x/auth/types"
@@ -853,14 +854,14 @@ func (s *MWTestSuite) TestTxHandlerSetPubKey() {
 				txBuilder.SetGasLimit(gasLimit)
 
 				// Manually create tx, and remove signature.
-				tx, _, err := s.createTestTx(txBuilder, privs, accNums, accSeqs, ctx.ChainID())
+				testTx, _, err := s.createTestTx(txBuilder, privs, accNums, accSeqs, ctx.ChainID())
 				s.Require().NoError(err)
-				txBuilder, err := s.clientCtx.TxConfig.WrapTxBuilder(tx)
+				txBuilder, err := s.clientCtx.TxConfig.WrapTxBuilder(testTx)
 				s.Require().NoError(err)
 				s.Require().NoError(txBuilder.SetSignatures())
 
 				// Run txHandler manually, expect ErrNoSignatures.
-				_, err = s.txHandler.CheckTx(sdk.WrapSDKContext(ctx), txBuilder.GetTx(), abci.RequestCheckTx{})
+				_, _, err = s.txHandler.CheckTx(sdk.WrapSDKContext(ctx), tx.Request{Tx: txBuilder.GetTx()}, tx.RequestCheckTx{})
 				s.Require().Error(err)
 				s.Require().True(errors.Is(err, sdkerrors.ErrNoSignatures))
 
@@ -1059,9 +1060,9 @@ func (s *MWTestSuite) TestCustomSignatureVerificationGasConsumer() {
 		s.Run(fmt.Sprintf("Case %s", tc.desc), func() {
 			tc.malleate()
 
-			tx, txBytes, err := s.createTestTx(txBuilder, privs, accNums, accSeqs, ctx.ChainID())
+			testTx, txBytes, err := s.createTestTx(txBuilder, privs, accNums, accSeqs, ctx.ChainID())
 			s.Require().NoError(err)
-			_, err = txHandler.DeliverTx(sdk.WrapSDKContext(ctx), tx, abci.RequestDeliverTx{Tx: txBytes})
+			_, err = txHandler.DeliverTx(sdk.WrapSDKContext(ctx), tx.Request{Tx: testTx, TxBytes: txBytes})
 			s.Require().Error(err)
 			s.Require().True(errors.Is(err, tc.expErr))
 		})
@@ -1090,21 +1091,21 @@ func (s *MWTestSuite) TestTxHandlerReCheck() {
 
 	// test that operations skipped on recheck do not run
 	privs, accNums, accSeqs := []cryptotypes.PrivKey{accounts[0].priv}, []uint64{0}, []uint64{0}
-	tx, _, err := s.createTestTx(txBuilder, privs, accNums, accSeqs, ctx.ChainID())
+	testTx, _, err := s.createTestTx(txBuilder, privs, accNums, accSeqs, ctx.ChainID())
 	s.Require().NoError(err)
 
 	// make signature array empty which would normally cause ValidateBasicMiddleware and SigVerificationMiddleware fail
 	// since these middlewares don't run on recheck, the tx should pass the middleware
-	txBuilder, err = s.clientCtx.TxConfig.WrapTxBuilder(tx)
+	txBuilder, err = s.clientCtx.TxConfig.WrapTxBuilder(testTx)
 	s.Require().NoError(err)
 	s.Require().NoError(txBuilder.SetSignatures())
 
-	_, err = s.txHandler.CheckTx(sdk.WrapSDKContext(ctx), txBuilder.GetTx(), abci.RequestCheckTx{Type: abci.CheckTxType_Recheck})
+	_, _, err = s.txHandler.CheckTx(sdk.WrapSDKContext(ctx), tx.Request{Tx: txBuilder.GetTx()}, tx.RequestCheckTx{Type: abci.CheckTxType_Recheck})
 	s.Require().Nil(err, "TxHandler errored on recheck unexpectedly: %v", err)
 
-	tx, _, err = s.createTestTx(txBuilder, privs, accNums, accSeqs, ctx.ChainID())
+	testTx, _, err = s.createTestTx(txBuilder, privs, accNums, accSeqs, ctx.ChainID())
 	s.Require().NoError(err)
-	txBytes, err := json.Marshal(tx)
+	txBytes, err := json.Marshal(testTx)
 	s.Require().Nil(err, "Error marshalling tx: %v", err)
 	ctx = ctx.WithTxBytes(txBytes)
 
@@ -1122,7 +1123,7 @@ func (s *MWTestSuite) TestTxHandlerReCheck() {
 		// set testcase parameters
 		s.app.AccountKeeper.SetParams(ctx, tc.params)
 
-		_, err = s.txHandler.CheckTx(sdk.WrapSDKContext(ctx), tx, abci.RequestCheckTx{Tx: txBytes, Type: abci.CheckTxType_Recheck})
+		_, _, err = s.txHandler.CheckTx(sdk.WrapSDKContext(ctx), tx.Request{Tx: testTx, TxBytes: txBytes}, tx.RequestCheckTx{Type: abci.CheckTxType_Recheck})
 
 		s.Require().NotNil(err, "tx does not fail on recheck with updated params in test case: %s", tc.name)
 
@@ -1136,7 +1137,7 @@ func (s *MWTestSuite) TestTxHandlerReCheck() {
 		Denom:  "dnecoin", // fee does not have this denom
 		Amount: sdk.NewDec(5),
 	}})
-	_, err = s.txHandler.CheckTx(sdk.WrapSDKContext(ctx), tx, abci.RequestCheckTx{})
+	_, _, err = s.txHandler.CheckTx(sdk.WrapSDKContext(ctx), tx.Request{Tx: testTx}, tx.RequestCheckTx{})
 
 	s.Require().NotNil(err, "txhandler on recheck did not fail when mingasPrice was changed")
 	// reset min gasprice
@@ -1148,6 +1149,6 @@ func (s *MWTestSuite) TestTxHandlerReCheck() {
 	err = s.app.BankKeeper.SendCoinsFromAccountToModule(ctx, accounts[0].acc.GetAddress(), minttypes.ModuleName, balances)
 	s.Require().NoError(err)
 
-	_, err = s.txHandler.CheckTx(sdk.WrapSDKContext(ctx), tx, abci.RequestCheckTx{})
+	_, _, err = s.txHandler.CheckTx(sdk.WrapSDKContext(ctx), tx.Request{Tx: testTx}, tx.RequestCheckTx{})
 	s.Require().NotNil(err, "txhandler on recheck did not fail once feePayer no longer has sufficient funds")
 }
diff --git a/x/auth/middleware/priority.go b/x/auth/middleware/priority.go
index fa6984b74201..a464fddd1e7d 100644
--- a/x/auth/middleware/priority.go
+++ b/x/auth/middleware/priority.go
@@ -3,8 +3,6 @@ package middleware
 import (
 	"context"
 
-	abci "github.com/tendermint/tendermint/abci/types"
-
 	sdk "github.com/cosmos/cosmos-sdk/types"
 	sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
 	"github.com/cosmos/cosmos-sdk/types/tx"
@@ -16,10 +14,10 @@ type txPriorityHandler struct {
 	next tx.Handler
 }
 
-// TxPriorityHandler implements tx handling middleware that determines a
+// TxPriorityMiddleware implements tx handling middleware that determines a
 // transaction's priority via a naive mechanism -- the total sum of fees provided.
 // It sets the Priority in ResponseCheckTx only.
-func TxPriorityHandler(txh tx.Handler) tx.Handler {
+func TxPriorityMiddleware(txh tx.Handler) tx.Handler {
 	return txPriorityHandler{next: txh}
 }
 
@@ -28,26 +26,26 @@ func TxPriorityHandler(txh tx.Handler) tx.Handler {
 // fees included. Applications that need more sophisticated mempool ordering
 // should look to implement their own fee handling middleware instead of using
 // TxPriorityHandler.
-func (h txPriorityHandler) CheckTx(ctx context.Context, tx sdk.Tx, req abci.RequestCheckTx) (abci.ResponseCheckTx, error) {
-	feeTx, ok := tx.(sdk.FeeTx)
+func (h txPriorityHandler) CheckTx(ctx context.Context, req tx.Request, checkReq tx.RequestCheckTx) (tx.Response, tx.ResponseCheckTx, error) {
+	feeTx, ok := req.Tx.(sdk.FeeTx)
 	if !ok {
-		return abci.ResponseCheckTx{}, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "Tx must be a FeeTx")
+		return tx.Response{}, tx.ResponseCheckTx{}, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "Tx must be a FeeTx")
 	}
 
 	feeCoins := feeTx.GetFee()
 
-	res, err := h.next.CheckTx(ctx, tx, req)
-	res.Priority = GetTxPriority(feeCoins)
+	res, checkRes, err := h.next.CheckTx(ctx, req, checkReq)
+	checkRes.Priority = GetTxPriority(feeCoins)
 
-	return res, err
+	return res, checkRes, err
 }
 
-func (h txPriorityHandler) DeliverTx(ctx context.Context, tx sdk.Tx, req abci.RequestDeliverTx) (abci.ResponseDeliverTx, error) {
-	return h.next.DeliverTx(ctx, tx, req)
+func (h txPriorityHandler) DeliverTx(ctx context.Context, req tx.Request) (tx.Response, error) {
+	return h.next.DeliverTx(ctx, req)
 }
 
-func (h txPriorityHandler) SimulateTx(ctx context.Context, sdkTx sdk.Tx, req tx.RequestSimulateTx) (tx.ResponseSimulateTx, error) {
-	return h.next.SimulateTx(ctx, sdkTx, req)
+func (h txPriorityHandler) SimulateTx(ctx context.Context, req tx.Request) (tx.Response, error) {
+	return h.next.SimulateTx(ctx, req)
 }
 
 // GetTxPriority returns a naive tx priority based on the amount of the smallest denomination of the fee
diff --git a/x/auth/middleware/priority_test.go b/x/auth/middleware/priority_test.go
index a06233f7e12b..a04e2065d971 100644
--- a/x/auth/middleware/priority_test.go
+++ b/x/auth/middleware/priority_test.go
@@ -4,15 +4,15 @@ import (
 	cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
 	"github.com/cosmos/cosmos-sdk/testutil/testdata"
 	sdk "github.com/cosmos/cosmos-sdk/types"
+	"github.com/cosmos/cosmos-sdk/types/tx"
 	"github.com/cosmos/cosmos-sdk/x/auth/middleware"
-	abci "github.com/tendermint/tendermint/abci/types"
 )
 
 func (s *MWTestSuite) TestPriority() {
 	ctx := s.SetupTest(true) // setup
 	txBuilder := s.clientCtx.TxConfig.NewTxBuilder()
 
-	txHandler := middleware.ComposeMiddlewares(noopTxHandler{}, middleware.TxPriorityHandler)
+	txHandler := middleware.ComposeMiddlewares(noopTxHandler{}, middleware.TxPriorityMiddleware)
 
 	// keys and addresses
 	priv1, _, addr1 := testdata.KeyTestPubAddr()
@@ -28,11 +28,11 @@ func (s *MWTestSuite) TestPriority() {
 	txBuilder.SetGasLimit(gasLimit)
 
 	privs, accNums, accSeqs := []cryptotypes.PrivKey{priv1}, []uint64{0}, []uint64{0}
-	tx, _, err := s.createTestTx(txBuilder, privs, accNums, accSeqs, ctx.ChainID())
+	testTx, _, err := s.createTestTx(txBuilder, privs, accNums, accSeqs, ctx.ChainID())
 	s.Require().NoError(err)
 
 	// txHandler errors with insufficient fees
-	res, err := txHandler.CheckTx(sdk.WrapSDKContext(ctx), tx, abci.RequestCheckTx{})
+	_, checkTxRes, err := txHandler.CheckTx(sdk.WrapSDKContext(ctx), tx.Request{Tx: testTx}, tx.RequestCheckTx{})
 	s.Require().NoError(err, "Middleware should not have errored on too low fee for local gasPrice")
-	s.Require().Equal(atomCoin.Amount.Int64(), res.Priority, "priority should be atom amount")
+	s.Require().Equal(atomCoin.Amount.Int64(), checkTxRes.Priority, "priority should be atom amount")
 }
diff --git a/x/auth/middleware/recovery.go b/x/auth/middleware/recovery.go
index 42091c354171..1d9cd4db7cdd 100644
--- a/x/auth/middleware/recovery.go
+++ b/x/auth/middleware/recovery.go
@@ -4,8 +4,6 @@ import (
 	"context"
 	"runtime/debug"
 
-	abci "github.com/tendermint/tendermint/abci/types"
-
 	sdk "github.com/cosmos/cosmos-sdk/types"
 	sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
 	"github.com/cosmos/cosmos-sdk/types/tx"
@@ -26,7 +24,7 @@ func RecoveryTxMiddleware(txh tx.Handler) tx.Handler {
 var _ tx.Handler = recoveryTxHandler{}
 
 // CheckTx implements tx.Handler.CheckTx method.
-func (txh recoveryTxHandler) CheckTx(ctx context.Context, tx sdk.Tx, req abci.RequestCheckTx) (res abci.ResponseCheckTx, err error) {
+func (txh recoveryTxHandler) CheckTx(ctx context.Context, req tx.Request, checkReq tx.RequestCheckTx) (res tx.Response, resCheckTx tx.ResponseCheckTx, err error) {
 	sdkCtx := sdk.UnwrapSDKContext(ctx)
 	// Panic recovery.
 	defer func() {
@@ -35,11 +33,11 @@ func (txh recoveryTxHandler) CheckTx(ctx context.Context, tx sdk.Tx, req abci.Re
 		}
 	}()
 
-	return txh.next.CheckTx(ctx, tx, req)
+	return txh.next.CheckTx(ctx, req, checkReq)
 }
 
 // DeliverTx implements tx.Handler.DeliverTx method.
-func (txh recoveryTxHandler) DeliverTx(ctx context.Context, tx sdk.Tx, req abci.RequestDeliverTx) (res abci.ResponseDeliverTx, err error) {
+func (txh recoveryTxHandler) DeliverTx(ctx context.Context, req tx.Request) (res tx.Response, err error) {
 	sdkCtx := sdk.UnwrapSDKContext(ctx)
 	// only run the tx if there is block gas remaining
 	if sdkCtx.BlockGasMeter().IsOutOfGas() {
@@ -71,11 +69,11 @@ func (txh recoveryTxHandler) DeliverTx(ctx context.Context, tx sdk.Tx, req abci.
 		}
 	}()
 
-	return txh.next.DeliverTx(ctx, tx, req)
+	return txh.next.DeliverTx(ctx, req)
 }
 
 // SimulateTx implements tx.Handler.SimulateTx method.
-func (txh recoveryTxHandler) SimulateTx(ctx context.Context, sdkTx sdk.Tx, req tx.RequestSimulateTx) (res tx.ResponseSimulateTx, err error) {
+func (txh recoveryTxHandler) SimulateTx(ctx context.Context, req tx.Request) (res tx.Response, err error) {
 	sdkCtx := sdk.UnwrapSDKContext(ctx)
 	// Panic recovery.
 	defer func() {
@@ -84,7 +82,7 @@ func (txh recoveryTxHandler) SimulateTx(ctx context.Context, sdkTx sdk.Tx, req t
 		}
 	}()
 
-	return txh.next.SimulateTx(ctx, sdkTx, req)
+	return txh.next.SimulateTx(ctx, req)
 }
 
 func handleRecovery(r interface{}, sdkCtx sdk.Context) error {
diff --git a/x/auth/middleware/run_msgs.go b/x/auth/middleware/run_msgs.go
index e9073b59a9af..c90d222a907b 100644
--- a/x/auth/middleware/run_msgs.go
+++ b/x/auth/middleware/run_msgs.go
@@ -5,10 +5,9 @@ import (
 	"fmt"
 	"strings"
 
-	"github.com/gogo/protobuf/proto"
-	abci "github.com/tendermint/tendermint/abci/types"
 	"github.com/tendermint/tendermint/crypto/tmhash"
 
+	codectypes "github.com/cosmos/cosmos-sdk/codec/types"
 	sdk "github.com/cosmos/cosmos-sdk/types"
 	sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
 	"github.com/cosmos/cosmos-sdk/types/tx"
@@ -30,37 +29,19 @@ func NewRunMsgsTxHandler(msr *MsgServiceRouter, legacyRouter sdk.Router) tx.Hand
 var _ tx.Handler = runMsgsTxHandler{}
 
 // CheckTx implements tx.Handler.CheckTx method.
-func (txh runMsgsTxHandler) CheckTx(ctx context.Context, tx sdk.Tx, req abci.RequestCheckTx) (abci.ResponseCheckTx, error) {
+func (txh runMsgsTxHandler) CheckTx(ctx context.Context, req tx.Request, checkReq tx.RequestCheckTx) (tx.Response, tx.ResponseCheckTx, error) {
 	// Don't run Msgs during CheckTx.
-	return abci.ResponseCheckTx{}, nil
+	return tx.Response{}, tx.ResponseCheckTx{}, nil
 }
 
 // DeliverTx implements tx.Handler.DeliverTx method.
-func (txh runMsgsTxHandler) DeliverTx(ctx context.Context, tx sdk.Tx, req abci.RequestDeliverTx) (abci.ResponseDeliverTx, error) {
-	res, err := txh.runMsgs(sdk.UnwrapSDKContext(ctx), tx.GetMsgs(), req.Tx)
-	if err != nil {
-		return abci.ResponseDeliverTx{}, err
-	}
-
-	return abci.ResponseDeliverTx{
-		// GasInfo will be populated by the Gas middleware.
-		Log:    res.Log,
-		Data:   res.Data,
-		Events: res.Events,
-	}, nil
+func (txh runMsgsTxHandler) DeliverTx(ctx context.Context, req tx.Request) (tx.Response, error) {
+	return txh.runMsgs(sdk.UnwrapSDKContext(ctx), req.Tx.GetMsgs(), req.TxBytes)
 }
 
 // SimulateTx implements tx.Handler.SimulateTx method.
-func (txh runMsgsTxHandler) SimulateTx(ctx context.Context, sdkTx sdk.Tx, req tx.RequestSimulateTx) (tx.ResponseSimulateTx, error) {
-	res, err := txh.runMsgs(sdk.UnwrapSDKContext(ctx), sdkTx.GetMsgs(), req.TxBytes)
-	if err != nil {
-		return tx.ResponseSimulateTx{}, err
-	}
-
-	return tx.ResponseSimulateTx{
-		// GasInfo will be populated by the Gas middleware.
-		Result: res,
-	}, nil
+func (txh runMsgsTxHandler) SimulateTx(ctx context.Context, req tx.Request) (tx.Response, error) {
+	return txh.runMsgs(sdk.UnwrapSDKContext(ctx), req.Tx.GetMsgs(), req.TxBytes)
 }
 
 // runMsgs iterates through a list of messages and executes them with the provided
@@ -68,7 +49,7 @@ func (txh runMsgsTxHandler) SimulateTx(ctx context.Context, sdkTx sdk.Tx, req tx
 // and DeliverTx. An error is returned if any single message fails or if a
 // Handler does not exist for a given message route. Otherwise, a reference to a
 // Result is returned. The caller must not commit state if an error is returned.
-func (txh runMsgsTxHandler) runMsgs(sdkCtx sdk.Context, msgs []sdk.Msg, txBytes []byte) (*sdk.Result, error) {
+func (txh runMsgsTxHandler) runMsgs(sdkCtx sdk.Context, msgs []sdk.Msg, txBytes []byte) (tx.Response, error) {
 	// Create a new Context based off of the existing Context with a MultiStore branch
 	// in case message processing fails. At this point, the MultiStore
 	// is a branch of a branch.
@@ -79,9 +60,7 @@ func (txh runMsgsTxHandler) runMsgs(sdkCtx sdk.Context, msgs []sdk.Msg, txBytes
 	// Result if any single message fails or does not have a registered Handler.
 	msgLogs := make(sdk.ABCIMessageLogs, 0, len(msgs))
 	events := sdkCtx.EventManager().Events()
-	txMsgData := &sdk.TxMsgData{
-		Data: make([]*sdk.MsgData, 0, len(msgs)),
-	}
+	msgResponses := make([]*codectypes.Any, len(msgs))
 
 	// NOTE: GasWanted is determined by the Gas TxHandler and GasUsed by the GasMeter.
 	for i, msg := range msgs {
@@ -105,16 +84,16 @@ func (txh runMsgsTxHandler) runMsgs(sdkCtx sdk.Context, msgs []sdk.Msg, txBytes
 			eventMsgName = legacyMsg.Type()
 			handler := txh.legacyRouter.Route(sdkCtx, msgRoute)
 			if handler == nil {
-				return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized message route: %s; message index: %d", msgRoute, i)
+				return tx.Response{}, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized message route: %s; message index: %d", msgRoute, i)
 			}
 
 			msgResult, err = handler(sdkCtx, msg)
 		} else {
-			return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "can't route message %+v", msg)
+			return tx.Response{}, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "can't route message %+v", msg)
 		}
 
 		if err != nil {
-			return nil, sdkerrors.Wrapf(err, "failed to execute message; message index: %d", i)
+			return tx.Response{}, sdkerrors.Wrapf(err, "failed to execute message; message index: %d", i)
 		}
 
 		msgEvents := sdk.Events{
@@ -128,20 +107,22 @@ func (txh runMsgsTxHandler) runMsgs(sdkCtx sdk.Context, msgs []sdk.Msg, txBytes
 		// separate each result.
 		events = events.AppendEvents(msgEvents)
 
-		txMsgData.Data = append(txMsgData.Data, &sdk.MsgData{MsgType: sdk.MsgTypeURL(msg), Data: msgResult.Data})
+		// Each individual sdk.Result has exactly one Msg response. We aggregate here.
+		msgResponse := msgResult.MsgResponses[0]
+		if msgResponse == nil {
+			return tx.Response{}, sdkerrors.ErrLogic.Wrapf("got nil Msg response at index %d for msg %s", i, sdk.MsgTypeURL(msg))
+		}
+		msgResponses[i] = msgResponse
 		msgLogs = append(msgLogs, sdk.NewABCIMessageLog(uint32(i), msgResult.Log, msgEvents))
 	}
 
 	msCache.Write()
-	data, err := proto.Marshal(txMsgData)
-	if err != nil {
-		return nil, sdkerrors.Wrap(err, "failed to marshal tx data")
-	}
 
-	return &sdk.Result{
-		Data:   data,
-		Log:    strings.TrimSpace(msgLogs.String()),
-		Events: events.ToABCIEvents(),
+	return tx.Response{
+		// GasInfo will be populated by the Gas middleware.
+		Log:          strings.TrimSpace(msgLogs.String()),
+		Events:       events.ToABCIEvents(),
+		MsgResponses: msgResponses,
 	}, nil
 }
 
diff --git a/x/auth/middleware/run_msgs_test.go b/x/auth/middleware/run_msgs_test.go
index 909de101d46d..6278d5c023d2 100644
--- a/x/auth/middleware/run_msgs_test.go
+++ b/x/auth/middleware/run_msgs_test.go
@@ -1,11 +1,14 @@
 package middleware_test
 
 import (
-	"github.com/tendermint/tendermint/abci/types"
+	"fmt"
+
+	"github.com/gogo/protobuf/proto"
 
 	cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
 	"github.com/cosmos/cosmos-sdk/testutil/testdata"
 	sdk "github.com/cosmos/cosmos-sdk/types"
+	"github.com/cosmos/cosmos-sdk/types/tx"
 	"github.com/cosmos/cosmos-sdk/x/auth/middleware"
 )
 
@@ -20,17 +23,13 @@ func (s *MWTestSuite) TestRunMsgs() {
 	txBuilder := s.clientCtx.TxConfig.NewTxBuilder()
 	txBuilder.SetMsgs(&testdata.MsgCreateDog{Dog: &testdata.Dog{Name: "Spot"}})
 	privs, accNums, accSeqs := []cryptotypes.PrivKey{priv}, []uint64{0}, []uint64{0}
-	tx, _, err := s.createTestTx(txBuilder, privs, accNums, accSeqs, ctx.ChainID())
+	testTx, _, err := s.createTestTx(txBuilder, privs, accNums, accSeqs, ctx.ChainID())
 	s.Require().NoError(err)
-	txBytes, err := s.clientCtx.TxConfig.TxEncoder()(tx)
+	txBytes, err := s.clientCtx.TxConfig.TxEncoder()(testTx)
 	s.Require().NoError(err)
 
-	res, err := txHandler.DeliverTx(sdk.WrapSDKContext(ctx), tx, types.RequestDeliverTx{Tx: txBytes})
-	s.Require().NoError(err)
-	s.Require().NotEmpty(res.Data)
-	var txMsgData sdk.TxMsgData
-	err = s.clientCtx.Codec.Unmarshal(res.Data, &txMsgData)
+	res, err := txHandler.DeliverTx(sdk.WrapSDKContext(ctx), tx.Request{Tx: testTx, TxBytes: txBytes})
 	s.Require().NoError(err)
-	s.Require().Len(txMsgData.Data, 1)
-	s.Require().Equal(sdk.MsgTypeURL(&testdata.MsgCreateDog{}), txMsgData.Data[0].MsgType)
+	s.Require().Len(res.MsgResponses, 1)
+	s.Require().Equal(fmt.Sprintf("/%s", proto.MessageName(&testdata.MsgCreateDogResponse{})), res.MsgResponses[0].TypeUrl)
 }
diff --git a/x/auth/middleware/sigverify.go b/x/auth/middleware/sigverify.go
index 504b7a27de46..0e31efa52877 100644
--- a/x/auth/middleware/sigverify.go
+++ b/x/auth/middleware/sigverify.go
@@ -52,9 +52,9 @@ func SetPubKeyMiddleware(ak AccountKeeper) tx.Middleware {
 	}
 }
 
-func (spkm setPubKeyTxHandler) setPubKey(ctx context.Context, tx sdk.Tx, simulate bool) error {
+func (spkm setPubKeyTxHandler) setPubKey(ctx context.Context, req tx.Request, simulate bool) error {
 	sdkCtx := sdk.UnwrapSDKContext(ctx)
-	sigTx, ok := tx.(authsigning.SigVerifiableTx)
+	sigTx, ok := req.Tx.(authsigning.SigVerifiableTx)
 	if !ok {
 		return sdkerrors.Wrap(sdkerrors.ErrTxDecode, "invalid tx type")
 	}
@@ -126,28 +126,28 @@ func (spkm setPubKeyTxHandler) setPubKey(ctx context.Context, tx sdk.Tx, simulat
 }
 
 // CheckTx implements tx.Handler.CheckTx.
-func (spkm setPubKeyTxHandler) CheckTx(ctx context.Context, tx sdk.Tx, req abci.RequestCheckTx) (abci.ResponseCheckTx, error) {
-	if err := spkm.setPubKey(ctx, tx, false); err != nil {
-		return abci.ResponseCheckTx{}, err
+func (spkm setPubKeyTxHandler) CheckTx(ctx context.Context, req tx.Request, checkReq tx.RequestCheckTx) (tx.Response, tx.ResponseCheckTx, error) {
+	if err := spkm.setPubKey(ctx, req, false); err != nil {
+		return tx.Response{}, tx.ResponseCheckTx{}, err
 	}
 
-	return spkm.next.CheckTx(ctx, tx, req)
+	return spkm.next.CheckTx(ctx, req, checkReq)
 }
 
 // DeliverTx implements tx.Handler.DeliverTx.
-func (spkm setPubKeyTxHandler) DeliverTx(ctx context.Context, tx sdk.Tx, req abci.RequestDeliverTx) (abci.ResponseDeliverTx, error) {
-	if err := spkm.setPubKey(ctx, tx, false); err != nil {
-		return abci.ResponseDeliverTx{}, err
+func (spkm setPubKeyTxHandler) DeliverTx(ctx context.Context, req tx.Request) (tx.Response, error) {
+	if err := spkm.setPubKey(ctx, req, false); err != nil {
+		return tx.Response{}, err
 	}
-	return spkm.next.DeliverTx(ctx, tx, req)
+	return spkm.next.DeliverTx(ctx, req)
 }
 
 // SimulateTx implements tx.Handler.SimulateTx.
-func (spkm setPubKeyTxHandler) SimulateTx(ctx context.Context, sdkTx sdk.Tx, req tx.RequestSimulateTx) (tx.ResponseSimulateTx, error) {
-	if err := spkm.setPubKey(ctx, sdkTx, true); err != nil {
-		return tx.ResponseSimulateTx{}, err
+func (spkm setPubKeyTxHandler) SimulateTx(ctx context.Context, req tx.Request) (tx.Response, error) {
+	if err := spkm.setPubKey(ctx, req, true); err != nil {
+		return tx.Response{}, err
 	}
-	return spkm.next.SimulateTx(ctx, sdkTx, req)
+	return spkm.next.SimulateTx(ctx, req)
 }
 
 var _ tx.Handler = validateSigCountTxHandler{}
@@ -170,10 +170,10 @@ func ValidateSigCountMiddleware(ak AccountKeeper) tx.Middleware {
 	}
 }
 
-func (vscd validateSigCountTxHandler) checkSigCount(ctx context.Context, tx sdk.Tx) error {
+func (vscd validateSigCountTxHandler) checkSigCount(ctx context.Context, req tx.Request) error {
 	sdkCtx := sdk.UnwrapSDKContext(ctx)
 
-	sigTx, ok := tx.(authsigning.SigVerifiableTx)
+	sigTx, ok := req.Tx.(authsigning.SigVerifiableTx)
 	if !ok {
 		return sdkerrors.Wrap(sdkerrors.ErrTxDecode, "Tx must be a sigTx")
 	}
@@ -196,30 +196,30 @@ func (vscd validateSigCountTxHandler) checkSigCount(ctx context.Context, tx sdk.
 }
 
 // CheckTx implements tx.Handler.CheckTx.
-func (vscd validateSigCountTxHandler) CheckTx(ctx context.Context, tx sdk.Tx, req abci.RequestCheckTx) (abci.ResponseCheckTx, error) {
-	if err := vscd.checkSigCount(ctx, tx); err != nil {
-		return abci.ResponseCheckTx{}, err
+func (vscd validateSigCountTxHandler) CheckTx(ctx context.Context, req tx.Request, checkReq tx.RequestCheckTx) (tx.Response, tx.ResponseCheckTx, error) {
+	if err := vscd.checkSigCount(ctx, req); err != nil {
+		return tx.Response{}, tx.ResponseCheckTx{}, err
 	}
 
-	return vscd.next.CheckTx(ctx, tx, req)
+	return vscd.next.CheckTx(ctx, req, checkReq)
 }
 
 // DeliverTx implements tx.Handler.DeliverTx.
-func (vscd validateSigCountTxHandler) SimulateTx(ctx context.Context, sdkTx sdk.Tx, req tx.RequestSimulateTx) (tx.ResponseSimulateTx, error) {
-	if err := vscd.checkSigCount(ctx, sdkTx); err != nil {
-		return tx.ResponseSimulateTx{}, err
+func (vscd validateSigCountTxHandler) DeliverTx(ctx context.Context, req tx.Request) (tx.Response, error) {
+	if err := vscd.checkSigCount(ctx, req); err != nil {
+		return tx.Response{}, err
 	}
 
-	return vscd.next.SimulateTx(ctx, sdkTx, req)
+	return vscd.next.DeliverTx(ctx, req)
 }
 
 // SimulateTx implements tx.Handler.SimulateTx.
-func (vscd validateSigCountTxHandler) DeliverTx(ctx context.Context, tx sdk.Tx, req abci.RequestDeliverTx) (abci.ResponseDeliverTx, error) {
-	if err := vscd.checkSigCount(ctx, tx); err != nil {
-		return abci.ResponseDeliverTx{}, err
+func (vscd validateSigCountTxHandler) SimulateTx(ctx context.Context, req tx.Request) (tx.Response, error) {
+	if err := vscd.checkSigCount(ctx, req); err != nil {
+		return tx.Response{}, err
 	}
 
-	return vscd.next.DeliverTx(ctx, tx, req)
+	return vscd.next.SimulateTx(ctx, req)
 }
 
 // DefaultSigVerificationGasConsumer is the default implementation of SignatureVerificationGasConsumer. It consumes gas
@@ -308,10 +308,10 @@ func SigGasConsumeMiddleware(ak AccountKeeper, sigGasConsumer SignatureVerificat
 	}
 }
 
-func (sgcm sigGasConsumeTxHandler) sigGasConsume(ctx context.Context, tx sdk.Tx, simulate bool) error {
+func (sgcm sigGasConsumeTxHandler) sigGasConsume(ctx context.Context, req tx.Request, simulate bool) error {
 	sdkCtx := sdk.UnwrapSDKContext(ctx)
 
-	sigTx, ok := tx.(authsigning.SigVerifiableTx)
+	sigTx, ok := req.Tx.(authsigning.SigVerifiableTx)
 	if !ok {
 		return sdkerrors.Wrap(sdkerrors.ErrTxDecode, "invalid transaction type")
 	}
@@ -359,30 +359,30 @@ func (sgcm sigGasConsumeTxHandler) sigGasConsume(ctx context.Context, tx sdk.Tx,
 }
 
 // CheckTx implements tx.Handler.CheckTx.
-func (sgcm sigGasConsumeTxHandler) CheckTx(ctx context.Context, tx sdk.Tx, req abci.RequestCheckTx) (abci.ResponseCheckTx, error) {
-	if err := sgcm.sigGasConsume(ctx, tx, false); err != nil {
-		return abci.ResponseCheckTx{}, err
+func (sgcm sigGasConsumeTxHandler) CheckTx(ctx context.Context, req tx.Request, checkReq tx.RequestCheckTx) (tx.Response, tx.ResponseCheckTx, error) {
+	if err := sgcm.sigGasConsume(ctx, req, false); err != nil {
+		return tx.Response{}, tx.ResponseCheckTx{}, err
 	}
 
-	return sgcm.next.CheckTx(ctx, tx, req)
+	return sgcm.next.CheckTx(ctx, req, checkReq)
 }
 
 // DeliverTx implements tx.Handler.DeliverTx.
-func (sgcm sigGasConsumeTxHandler) DeliverTx(ctx context.Context, tx sdk.Tx, req abci.RequestDeliverTx) (abci.ResponseDeliverTx, error) {
-	if err := sgcm.sigGasConsume(ctx, tx, false); err != nil {
-		return abci.ResponseDeliverTx{}, err
+func (sgcm sigGasConsumeTxHandler) DeliverTx(ctx context.Context, req tx.Request) (tx.Response, error) {
+	if err := sgcm.sigGasConsume(ctx, req, false); err != nil {
+		return tx.Response{}, err
 	}
 
-	return sgcm.next.DeliverTx(ctx, tx, req)
+	return sgcm.next.DeliverTx(ctx, req)
 }
 
 // SimulateTx implements tx.Handler.SimulateTx.
-func (sgcm sigGasConsumeTxHandler) SimulateTx(ctx context.Context, sdkTx sdk.Tx, req tx.RequestSimulateTx) (tx.ResponseSimulateTx, error) {
-	if err := sgcm.sigGasConsume(ctx, sdkTx, true); err != nil {
-		return tx.ResponseSimulateTx{}, err
+func (sgcm sigGasConsumeTxHandler) SimulateTx(ctx context.Context, req tx.Request) (tx.Response, error) {
+	if err := sgcm.sigGasConsume(ctx, req, true); err != nil {
+		return tx.Response{}, err
 	}
 
-	return sgcm.next.SimulateTx(ctx, sdkTx, req)
+	return sgcm.next.SimulateTx(ctx, req)
 }
 
 var _ tx.Handler = sigVerificationTxHandler{}
@@ -429,13 +429,13 @@ func OnlyLegacyAminoSigners(sigData signing.SignatureData) bool {
 	}
 }
 
-func (svd sigVerificationTxHandler) sigVerify(ctx context.Context, tx sdk.Tx, isReCheckTx, simulate bool) error {
+func (svd sigVerificationTxHandler) sigVerify(ctx context.Context, req tx.Request, isReCheckTx, simulate bool) error {
 	sdkCtx := sdk.UnwrapSDKContext(ctx)
 	// no need to verify signatures on recheck tx
 	if isReCheckTx {
 		return nil
 	}
-	sigTx, ok := tx.(authsigning.SigVerifiableTx)
+	sigTx, ok := req.Tx.(authsigning.SigVerifiableTx)
 	if !ok {
 		return sdkerrors.Wrap(sdkerrors.ErrTxDecode, "invalid transaction type")
 	}
@@ -491,7 +491,7 @@ func (svd sigVerificationTxHandler) sigVerify(ctx context.Context, tx sdk.Tx, is
 		}
 
 		if !simulate {
-			err := authsigning.VerifySignature(pubKey, signerData, sig.Data, svd.signModeHandler, tx)
+			err := authsigning.VerifySignature(pubKey, signerData, sig.Data, svd.signModeHandler, req.Tx)
 			if err != nil {
 				var errMsg string
 				if OnlyLegacyAminoSigners(sig.Data) {
@@ -511,30 +511,30 @@ func (svd sigVerificationTxHandler) sigVerify(ctx context.Context, tx sdk.Tx, is
 }
 
 // CheckTx implements tx.Handler.CheckTx.
-func (svd sigVerificationTxHandler) CheckTx(ctx context.Context, tx sdk.Tx, req abci.RequestCheckTx) (abci.ResponseCheckTx, error) {
-	if err := svd.sigVerify(ctx, tx, req.Type == abci.CheckTxType_Recheck, false); err != nil {
-		return abci.ResponseCheckTx{}, err
+func (svd sigVerificationTxHandler) CheckTx(ctx context.Context, req tx.Request, checkReq tx.RequestCheckTx) (tx.Response, tx.ResponseCheckTx, error) {
+	if err := svd.sigVerify(ctx, req, checkReq.Type == abci.CheckTxType_Recheck, false); err != nil {
+		return tx.Response{}, tx.ResponseCheckTx{}, err
 	}
 
-	return svd.next.CheckTx(ctx, tx, req)
+	return svd.next.CheckTx(ctx, req, checkReq)
 }
 
 // DeliverTx implements tx.Handler.DeliverTx.
-func (svd sigVerificationTxHandler) DeliverTx(ctx context.Context, tx sdk.Tx, req abci.RequestDeliverTx) (abci.ResponseDeliverTx, error) {
-	if err := svd.sigVerify(ctx, tx, false, false); err != nil {
-		return abci.ResponseDeliverTx{}, err
+func (svd sigVerificationTxHandler) DeliverTx(ctx context.Context, req tx.Request) (tx.Response, error) {
+	if err := svd.sigVerify(ctx, req, false, false); err != nil {
+		return tx.Response{}, err
 	}
 
-	return svd.next.DeliverTx(ctx, tx, req)
+	return svd.next.DeliverTx(ctx, req)
 }
 
 // SimulateTx implements tx.Handler.SimulateTx.
-func (svd sigVerificationTxHandler) SimulateTx(ctx context.Context, sdkTx sdk.Tx, req tx.RequestSimulateTx) (tx.ResponseSimulateTx, error) {
-	if err := svd.sigVerify(ctx, sdkTx, false, true); err != nil {
-		return tx.ResponseSimulateTx{}, err
+func (svd sigVerificationTxHandler) SimulateTx(ctx context.Context, req tx.Request) (tx.Response, error) {
+	if err := svd.sigVerify(ctx, req, false, true); err != nil {
+		return tx.Response{}, err
 	}
 
-	return svd.next.SimulateTx(ctx, sdkTx, req)
+	return svd.next.SimulateTx(ctx, req)
 }
 
 var _ tx.Handler = incrementSequenceTxHandler{}
@@ -562,9 +562,9 @@ func IncrementSequenceMiddleware(ak AccountKeeper) tx.Middleware {
 	}
 }
 
-func (isd incrementSequenceTxHandler) incrementSeq(ctx context.Context, tx sdk.Tx) error {
+func (isd incrementSequenceTxHandler) incrementSeq(ctx context.Context, req tx.Request) error {
 	sdkCtx := sdk.UnwrapSDKContext(ctx)
-	sigTx, ok := tx.(authsigning.SigVerifiableTx)
+	sigTx, ok := req.Tx.(authsigning.SigVerifiableTx)
 	if !ok {
 		return sdkerrors.Wrap(sdkerrors.ErrTxDecode, "invalid transaction type")
 	}
@@ -583,30 +583,30 @@ func (isd incrementSequenceTxHandler) incrementSeq(ctx context.Context, tx sdk.T
 }
 
 // CheckTx implements tx.Handler.CheckTx.
-func (isd incrementSequenceTxHandler) CheckTx(ctx context.Context, tx sdk.Tx, req abci.RequestCheckTx) (abci.ResponseCheckTx, error) {
-	if err := isd.incrementSeq(ctx, tx); err != nil {
-		return abci.ResponseCheckTx{}, err
+func (isd incrementSequenceTxHandler) CheckTx(ctx context.Context, req tx.Request, checkReq tx.RequestCheckTx) (tx.Response, tx.ResponseCheckTx, error) {
+	if err := isd.incrementSeq(ctx, req); err != nil {
+		return tx.Response{}, tx.ResponseCheckTx{}, err
 	}
 
-	return isd.next.CheckTx(ctx, tx, req)
+	return isd.next.CheckTx(ctx, req, checkReq)
 }
 
 // DeliverTx implements tx.Handler.DeliverTx.
-func (isd incrementSequenceTxHandler) DeliverTx(ctx context.Context, tx sdk.Tx, req abci.RequestDeliverTx) (abci.ResponseDeliverTx, error) {
-	if err := isd.incrementSeq(ctx, tx); err != nil {
-		return abci.ResponseDeliverTx{}, err
+func (isd incrementSequenceTxHandler) DeliverTx(ctx context.Context, req tx.Request) (tx.Response, error) {
+	if err := isd.incrementSeq(ctx, req); err != nil {
+		return tx.Response{}, err
 	}
 
-	return isd.next.DeliverTx(ctx, tx, req)
+	return isd.next.DeliverTx(ctx, req)
 }
 
 // SimulateTx implements tx.Handler.SimulateTx.
-func (isd incrementSequenceTxHandler) SimulateTx(ctx context.Context, sdkTx sdk.Tx, req tx.RequestSimulateTx) (tx.ResponseSimulateTx, error) {
-	if err := isd.incrementSeq(ctx, sdkTx); err != nil {
-		return tx.ResponseSimulateTx{}, err
+func (isd incrementSequenceTxHandler) SimulateTx(ctx context.Context, req tx.Request) (tx.Response, error) {
+	if err := isd.incrementSeq(ctx, req); err != nil {
+		return tx.Response{}, err
 	}
 
-	return isd.next.SimulateTx(ctx, sdkTx, req)
+	return isd.next.SimulateTx(ctx, req)
 }
 
 // GetSignerAcc returns an account for a given address that is expected to sign
diff --git a/x/auth/middleware/sigverify_test.go b/x/auth/middleware/sigverify_test.go
index 59c46938f619..b5f4d9c15966 100644
--- a/x/auth/middleware/sigverify_test.go
+++ b/x/auth/middleware/sigverify_test.go
@@ -55,7 +55,7 @@ func (s *MWTestSuite) TestSetPubKey() {
 	testTx, _, err := s.createTestTx(txBuilder, privs, accNums, accSeqs, ctx.ChainID())
 	require.NoError(err)
 
-	_, err = txHandler.DeliverTx(sdk.WrapSDKContext(ctx), testTx, abci.RequestDeliverTx{})
+	_, err = txHandler.DeliverTx(sdk.WrapSDKContext(ctx), tx.Request{Tx: testTx})
 	require.NoError(err)
 
 	// Require that all accounts have pubkey set after middleware runs
@@ -183,9 +183,9 @@ func (s *MWTestSuite) TestSigVerification() {
 		s.Require().NoError(err)
 
 		if tc.recheck {
-			_, err = txHandler.CheckTx(sdk.WrapSDKContext(ctx), testTx, abci.RequestCheckTx{Type: abci.CheckTxType_Recheck})
+			_, _, err = txHandler.CheckTx(sdk.WrapSDKContext(ctx), tx.Request{Tx: testTx}, tx.RequestCheckTx{Type: abci.CheckTxType_Recheck})
 		} else {
-			_, err = txHandler.CheckTx(sdk.WrapSDKContext(ctx), testTx, abci.RequestCheckTx{})
+			_, _, err = txHandler.CheckTx(sdk.WrapSDKContext(ctx), tx.Request{Tx: testTx}, tx.RequestCheckTx{})
 		}
 		if tc.shouldErr {
 			s.Require().NotNil(err, "TestCase %d: %s did not error as expected", i, tc.name)
@@ -278,9 +278,9 @@ func (s *MWTestSuite) TestSigVerification_ExplicitAmino() {
 		s.Require().NoError(err)
 
 		if tc.recheck {
-			_, err = txHandler.CheckTx(sdk.WrapSDKContext(ctx), testTx, abci.RequestCheckTx{Type: abci.CheckTxType_Recheck})
+			_, _, err = txHandler.CheckTx(sdk.WrapSDKContext(ctx), tx.Request{Tx: testTx}, tx.RequestCheckTx{Type: abci.CheckTxType_Recheck})
 		} else {
-			_, err = txHandler.CheckTx(sdk.WrapSDKContext(ctx), testTx, abci.RequestCheckTx{})
+			_, _, err = txHandler.CheckTx(sdk.WrapSDKContext(ctx), tx.Request{Tx: testTx}, tx.RequestCheckTx{})
 		}
 		if tc.shouldErr {
 			s.Require().NotNil(err, "TestCase %d: %s did not error as expected", i, tc.name)
@@ -353,7 +353,7 @@ func (s *MWTestSuite) runSigMiddlewares(params types.Params, _ bool, privs ...cr
 
 	// Determine gas consumption of txhandler with default params
 	before := ctx.GasMeter().GasConsumed()
-	_, err = txHandler.DeliverTx(sdk.WrapSDKContext(ctx), testTx, abci.RequestDeliverTx{})
+	_, err = txHandler.DeliverTx(sdk.WrapSDKContext(ctx), tx.Request{Tx: testTx})
 	after := ctx.GasMeter().GasConsumed()
 
 	return after - before, err
@@ -401,9 +401,9 @@ func (s *MWTestSuite) TestIncrementSequenceMiddleware() {
 	for i, tc := range testCases {
 		var err error
 		if tc.simulate {
-			_, err = txHandler.SimulateTx(sdk.WrapSDKContext(tc.ctx), testTx, tx.RequestSimulateTx{})
+			_, err = txHandler.SimulateTx(sdk.WrapSDKContext(tc.ctx), tx.Request{Tx: testTx})
 		} else {
-			_, err = txHandler.DeliverTx(sdk.WrapSDKContext(tc.ctx), testTx, abci.RequestDeliverTx{})
+			_, err = txHandler.DeliverTx(sdk.WrapSDKContext(tc.ctx), tx.Request{Tx: testTx})
 		}
 
 		s.Require().NoError(err, "unexpected error; tc #%d, %v", i, tc)
diff --git a/x/auth/middleware/testutil_test.go b/x/auth/middleware/testutil_test.go
index e5fd3043a7f3..9d804fa17ae2 100644
--- a/x/auth/middleware/testutil_test.go
+++ b/x/auth/middleware/testutil_test.go
@@ -6,12 +6,12 @@ import (
 	"testing"
 
 	"github.com/stretchr/testify/suite"
-	"github.com/tendermint/tendermint/abci/types"
 	tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
 
 	"github.com/cosmos/cosmos-sdk/client"
 	"github.com/cosmos/cosmos-sdk/client/tx"
 	"github.com/cosmos/cosmos-sdk/codec"
+	codectypes "github.com/cosmos/cosmos-sdk/codec/types"
 	cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
 	"github.com/cosmos/cosmos-sdk/simapp"
 	"github.com/cosmos/cosmos-sdk/testutil/testdata"
@@ -70,7 +70,16 @@ func (s *MWTestSuite) SetupTest(isCheckTx bool) sdk.Context {
 	msr := middleware.NewMsgServiceRouter(encodingConfig.InterfaceRegistry)
 	testdata.RegisterMsgServer(msr, testdata.MsgServerImpl{})
 	legacyRouter := middleware.NewLegacyRouter()
-	legacyRouter.AddRoute(sdk.NewRoute((&testdata.TestMsg{}).Route(), func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) { return &sdk.Result{}, nil }))
+	legacyRouter.AddRoute(sdk.NewRoute((&testdata.TestMsg{}).Route(), func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) {
+		any, err := codectypes.NewAnyWithValue(msg)
+		if err != nil {
+			return nil, err
+		}
+
+		return &sdk.Result{
+			MsgResponses: []*codectypes.Any{any},
+		}, nil
+	}))
 	txHandler, err := middleware.NewDefaultTxHandler(middleware.TxHandlerOptions{
 		Debug:            s.app.Trace(),
 		MsgServiceRouter: msr,
@@ -174,8 +183,8 @@ func (s *MWTestSuite) runTestCase(ctx sdk.Context, txBuilder client.TxBuilder, p
 		// Theoretically speaking, middleware unit tests should only test
 		// middlewares, but here we sometimes also test the tx creation
 		// process.
-		tx, _, txErr := s.createTestTx(txBuilder, privs, accNums, accSeqs, chainID)
-		newCtx, txHandlerErr := s.txHandler.DeliverTx(sdk.WrapSDKContext(ctx), tx, types.RequestDeliverTx{})
+		testTx, _, txErr := s.createTestTx(txBuilder, privs, accNums, accSeqs, chainID)
+		newCtx, txHandlerErr := s.txHandler.DeliverTx(sdk.WrapSDKContext(ctx), txtypes.Request{Tx: testTx})
 
 		if tc.expPass {
 			s.Require().NoError(txErr)
diff --git a/x/auth/middleware/tips.go b/x/auth/middleware/tips.go
index bcef9e62e0cd..68749b020647 100644
--- a/x/auth/middleware/tips.go
+++ b/x/auth/middleware/tips.go
@@ -3,8 +3,6 @@ package middleware
 import (
 	"context"
 
-	abci "github.com/tendermint/tendermint/abci/types"
-
 	sdk "github.com/cosmos/cosmos-sdk/types"
 	"github.com/cosmos/cosmos-sdk/types/tx"
 	"github.com/cosmos/cosmos-sdk/x/auth/types"
@@ -26,69 +24,46 @@ func NewTipMiddleware(bankKeeper types.BankKeeper) tx.Middleware {
 var _ tx.Handler = tipsTxHandler{}
 
 // CheckTx implements tx.Handler.CheckTx.
-func (txh tipsTxHandler) CheckTx(ctx context.Context, sdkTx sdk.Tx, req abci.RequestCheckTx) (abci.ResponseCheckTx, error) {
-	res, err := txh.next.CheckTx(ctx, sdkTx, req)
-	if err != nil {
-		return abci.ResponseCheckTx{}, err
-	}
-
-	tipTx, ok := sdkTx.(tx.TipTx)
-	if !ok || tipTx.GetTip() == nil {
-		return res, err
-	}
+func (txh tipsTxHandler) CheckTx(ctx context.Context, req tx.Request, checkTx tx.RequestCheckTx) (tx.Response, tx.ResponseCheckTx, error) {
+	res, resCheckTx, err := txh.next.CheckTx(ctx, req, checkTx)
+	res, err = txh.transferTip(ctx, req, res, err)
 
-	if err := txh.transferTip(ctx, tipTx); err != nil {
-		return abci.ResponseCheckTx{}, err
-	}
-
-	return res, err
+	return res, resCheckTx, err
 }
 
 // DeliverTx implements tx.Handler.DeliverTx.
-func (txh tipsTxHandler) DeliverTx(ctx context.Context, sdkTx sdk.Tx, req abci.RequestDeliverTx) (abci.ResponseDeliverTx, error) {
-	res, err := txh.next.DeliverTx(ctx, sdkTx, req)
-	if err != nil {
-		return abci.ResponseDeliverTx{}, err
-	}
+func (txh tipsTxHandler) DeliverTx(ctx context.Context, req tx.Request) (tx.Response, error) {
+	res, err := txh.next.DeliverTx(ctx, req)
 
-	tipTx, ok := sdkTx.(tx.TipTx)
-	if !ok || tipTx.GetTip() == nil {
-		return res, err
-	}
+	return txh.transferTip(ctx, req, res, err)
+}
 
-	if err := txh.transferTip(ctx, tipTx); err != nil {
-		return abci.ResponseDeliverTx{}, err
-	}
+// SimulateTx implements tx.Handler.SimulateTx method.
+func (txh tipsTxHandler) SimulateTx(ctx context.Context, req tx.Request) (tx.Response, error) {
+	res, err := txh.next.SimulateTx(ctx, req)
 
-	return res, err
+	return txh.transferTip(ctx, req, res, err)
 }
 
-// SimulateTx implements tx.Handler.SimulateTx method.
-func (txh tipsTxHandler) SimulateTx(ctx context.Context, sdkTx sdk.Tx, req tx.RequestSimulateTx) (tx.ResponseSimulateTx, error) {
-	res, err := txh.next.SimulateTx(ctx, sdkTx, req)
-	if err != nil {
-		return tx.ResponseSimulateTx{}, err
-	}
+// transferTip transfers the tip from the tipper to the fee payer.
+func (txh tipsTxHandler) transferTip(ctx context.Context, req tx.Request, res tx.Response, err error) (tx.Response, error) {
+	tipTx, ok := req.Tx.(tx.TipTx)
 
-	tipTx, ok := sdkTx.(tx.TipTx)
+	// No-op if the tx doesn't have tips.
 	if !ok || tipTx.GetTip() == nil {
 		return res, err
 	}
 
-	if err := txh.transferTip(ctx, tipTx); err != nil {
-		return tx.ResponseSimulateTx{}, err
-	}
-
-	return res, err
-}
-
-// transferTip transfers the tip from the tipper to the fee payer.
-func (txh tipsTxHandler) transferTip(ctx context.Context, tipTx tx.TipTx) error {
 	sdkCtx := sdk.UnwrapSDKContext(ctx)
 	tipper, err := sdk.AccAddressFromBech32(tipTx.GetTip().Tipper)
 	if err != nil {
-		return err
+		return tx.Response{}, err
+	}
+
+	err = txh.bankKeeper.SendCoins(sdkCtx, tipper, tipTx.FeePayer(), tipTx.GetTip().Amount)
+	if err != nil {
+		return tx.Response{}, err
 	}
 
-	return txh.bankKeeper.SendCoins(sdkCtx, tipper, tipTx.FeePayer(), tipTx.GetTip().Amount)
+	return res, nil
 }
diff --git a/x/auth/tx/service_test.go b/x/auth/tx/service_test.go
index 0424afba82e4..06242bd50eaa 100644
--- a/x/auth/tx/service_test.go
+++ b/x/auth/tx/service_test.go
@@ -129,6 +129,7 @@ func (s IntegrationTestSuite) TestSimulateTx_GRPC() {
 				// - Sending Amount to recipient: coin_spent, coin_received, transfer and message.sender=<val1>
 				// - Msg events: message.module=bank and message.action=/cosmos.bank.v1beta1.MsgSend
 				s.Require().Equal(len(res.GetResult().GetEvents()), 13)
+				s.Require().Len(res.GetResult().MsgResponses, 1)
 				// Check the result and gas used are correct.
 				s.Require().True(res.GetGasInfo().GetGasUsed() > 0) // Gas used sometimes change, just check it's not empty.
 			}
@@ -171,7 +172,8 @@ func (s IntegrationTestSuite) TestSimulateTx_GRPCGateway() {
 				s.Require().NoError(err)
 				// Check the result and gas used are correct.
 				s.Require().Equal(len(result.GetResult().GetEvents()), 13) // See TestSimulateTx_GRPC for the 13 events.
-				s.Require().True(result.GetGasInfo().GetGasUsed() > 0)     // Gas used sometimes change, just check it's not empty.
+				s.Require().Len(result.GetResult().MsgResponses, 1)
+				s.Require().True(result.GetGasInfo().GetGasUsed() > 0) // Gas used sometimes change, just check it's not empty.
 			}
 		})
 	}