diff --git a/app/apptesting/test_suite.go b/app/apptesting/test_suite.go
index 71446fecf824cca9f77dd5e2ad1d9e1ccbed8070..13394a119b87c0e379ae0bd39e7f072840b61474 100644
--- a/app/apptesting/test_suite.go
+++ b/app/apptesting/test_suite.go
@@ -350,6 +350,14 @@ func (s *KeeperTestHelper) BuildTx(
 	return txBuilder.GetTx()
 }
 
+// StateNotAltered validates that app state is not altered. Fails if it is.
+func (s *KeeperTestHelper) StateNotAltered() {
+	oldState := s.App.ExportState(s.Ctx)
+	s.Commit()
+	newState := s.App.ExportState(s.Ctx)
+	s.Require().Equal(oldState, newState)
+}
+
 // CreateRandomAccounts is a function return a list of randomly generated AccAddresses
 func CreateRandomAccounts(numAccts int) []sdk.AccAddress {
 	testAddrs := make([]sdk.AccAddress, numAccts)
diff --git a/app/export.go b/app/export.go
index 12be00a2431b5071cc3d7a2286ebbb28c993bdd2..814a332df803fd66c6afce2af9a5bb2c7d980706 100644
--- a/app/export.go
+++ b/app/export.go
@@ -195,3 +195,7 @@ func (app *OsmosisApp) prepForZeroHeightGenesis(ctx sdk.Context, jailAllowedAddr
 		},
 	)
 }
+
+func (app *OsmosisApp) ExportState(ctx sdk.Context) map[string]json.RawMessage {
+	return app.mm.ExportGenesis(ctx, app.AppCodec())
+}
diff --git a/x/epochs/client/cli/query_test.go b/x/epochs/client/cli/query_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..7011acbbf9284c0f757c2d1a82f48fe8670a4527
--- /dev/null
+++ b/x/epochs/client/cli/query_test.go
@@ -0,0 +1,73 @@
+package cli_test
+
+import (
+	gocontext "context"
+	"testing"
+	"time"
+
+	"github.com/stretchr/testify/suite"
+
+	"github.com/osmosis-labs/osmosis/v12/app/apptesting"
+	"github.com/osmosis-labs/osmosis/v12/x/epochs/types"
+)
+
+type QueryTestSuite struct {
+	apptesting.KeeperTestHelper
+	queryClient types.QueryClient
+}
+
+func (s *QueryTestSuite) SetupSuite() {
+	s.Setup()
+	s.queryClient = types.NewQueryClient(s.QueryHelper)
+
+	// add new epoch
+	epoch := types.EpochInfo{
+		Identifier:              "weekly",
+		StartTime:               time.Time{},
+		Duration:                time.Hour,
+		CurrentEpoch:            0,
+		CurrentEpochStartHeight: 0,
+		CurrentEpochStartTime:   time.Time{},
+		EpochCountingStarted:    false,
+	}
+	s.App.EpochsKeeper.AddEpochInfo(s.Ctx, epoch)
+
+	s.Commit()
+}
+
+func (s *QueryTestSuite) TestQueriesNeverAlterState() {
+	testCases := []struct {
+		name   string
+		query  string
+		input  interface{}
+		output interface{}
+	}{
+		{
+			"Query current epoch",
+			"/osmosis.epochs.v1beta1.Query/CurrentEpoch",
+			&types.QueryCurrentEpochRequest{Identifier: "weekly"},
+			&types.QueryCurrentEpochResponse{},
+		},
+		{
+			"Query epochs info",
+			"/osmosis.epochs.v1beta1.Query/EpochInfos",
+			&types.QueryEpochsInfoRequest{},
+			&types.QueryEpochsInfoResponse{},
+		},
+	}
+
+	for _, tc := range testCases {
+		tc := tc
+
+		s.Run(tc.name, func() {
+			s.SetupSuite()
+			err := s.QueryHelper.Invoke(gocontext.Background(), tc.query, tc.input, tc.output)
+			s.Require().NoError(err)
+			s.StateNotAltered()
+		})
+	}
+}
+
+func TestQueryTestSuite(t *testing.T) {
+	suite.Run(t, new(QueryTestSuite))
+}
diff --git a/x/gamm/client/cli/query_test.go b/x/gamm/client/cli/query_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..649a849ca7f40f8c58bc1d01f56a03fe67b4e4dd
--- /dev/null
+++ b/x/gamm/client/cli/query_test.go
@@ -0,0 +1,102 @@
+package cli_test
+
+import (
+	gocontext "context"
+	"testing"
+
+	"github.com/stretchr/testify/suite"
+
+	"github.com/osmosis-labs/osmosis/v12/app/apptesting"
+	"github.com/osmosis-labs/osmosis/v12/x/gamm/types"
+)
+
+type QueryTestSuite struct {
+	apptesting.KeeperTestHelper
+	queryClient types.QueryClient
+}
+
+func (s *QueryTestSuite) SetupSuite() {
+	s.Setup()
+	s.queryClient = types.NewQueryClient(s.QueryHelper)
+	// create a new pool
+	s.PrepareBalancerPool()
+	s.Commit()
+}
+
+func (s *QueryTestSuite) TestQueriesNeverAlterState() {
+	testCases := []struct {
+		name   string
+		query  string
+		input  interface{}
+		output interface{}
+	}{
+		{
+			"Query pools",
+			"/osmosis.gamm.v1beta1.Query/Pools",
+			&types.QueryPoolsRequest{},
+			&types.QueryPoolsResponse{},
+		},
+		{
+			"Query single pool",
+			"/osmosis.gamm.v1beta1.Query/Pool",
+			&types.QueryPoolRequest{PoolId: 1},
+			&types.QueryPoolsResponse{},
+		},
+		{
+			"Query num pools",
+			"/osmosis.gamm.v1beta1.Query/NumPools",
+			&types.QueryNumPoolsRequest{},
+			&types.QueryNumPoolsResponse{},
+		},
+		{
+			"Query pool params",
+			"/osmosis.gamm.v1beta1.Query/PoolParams",
+			&types.QueryPoolParamsRequest{PoolId: 1},
+			&types.QueryPoolParamsResponse{},
+		},
+		{
+			"Query pool type",
+			"/osmosis.gamm.v1beta1.Query/PoolType",
+			&types.QueryPoolTypeRequest{PoolId: 1},
+			&types.QueryPoolTypeResponse{},
+		},
+		{
+			"Query spot price",
+			"/osmosis.gamm.v1beta1.Query/SpotPrice",
+			&types.QuerySpotPriceRequest{PoolId: 1, BaseAssetDenom: "foo", QuoteAssetDenom: "bar"},
+			&types.QuerySpotPriceResponse{},
+		},
+		{
+			"Query total liquidity",
+			"/osmosis.gamm.v1beta1.Query/TotalLiquidity",
+			&types.QueryTotalLiquidityRequest{},
+			&types.QueryTotalLiquidityResponse{},
+		},
+		{
+			"Query pool total liquidity",
+			"/osmosis.gamm.v1beta1.Query/TotalPoolLiquidity",
+			&types.QueryTotalPoolLiquidityRequest{PoolId: 1},
+			&types.QueryTotalPoolLiquidityResponse{},
+		},
+		{
+			"Query total shares",
+			"/osmosis.gamm.v1beta1.Query/TotalShares",
+			&types.QueryTotalSharesRequest{PoolId: 1},
+			&types.QueryTotalSharesResponse{},
+		},
+	}
+
+	for _, tc := range testCases {
+		tc := tc
+		s.Run(tc.name, func() {
+			s.SetupSuite()
+			err := s.QueryHelper.Invoke(gocontext.Background(), tc.query, tc.input, tc.output)
+			s.Require().NoError(err)
+			s.StateNotAltered()
+		})
+	}
+}
+
+func TestQueryTestSuite(t *testing.T) {
+	suite.Run(t, new(QueryTestSuite))
+}
diff --git a/x/incentives/client/cli/query_test.go b/x/incentives/client/cli/query_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..a88069544977a408bcecd7df8afca391b6144330
--- /dev/null
+++ b/x/incentives/client/cli/query_test.go
@@ -0,0 +1,110 @@
+package cli_test
+
+import (
+	gocontext "context"
+	"testing"
+	"time"
+
+	"github.com/stretchr/testify/suite"
+
+	"github.com/osmosis-labs/osmosis/v12/app/apptesting"
+	"github.com/osmosis-labs/osmosis/v12/x/incentives/types"
+
+	sdk "github.com/cosmos/cosmos-sdk/types"
+)
+
+type QueryTestSuite struct {
+	apptesting.KeeperTestHelper
+	queryClient types.QueryClient
+}
+
+func (s *QueryTestSuite) SetupSuite() {
+	s.Setup()
+	s.queryClient = types.NewQueryClient(s.QueryHelper)
+
+	// create a pool
+	s.PrepareBalancerPool()
+	// set up lock with id = 1
+	s.LockTokens(s.TestAccs[0], sdk.Coins{sdk.NewCoin("gamm/pool/1", sdk.NewInt(1000000))}, time.Hour*24)
+
+	s.Commit()
+}
+
+func (s *QueryTestSuite) TestQueriesNeverAlterState() {
+	testCases := []struct {
+		name   string
+		query  string
+		input  interface{}
+		output interface{}
+	}{
+		{
+			"Query active gauges",
+			"/osmosis.incentives.Query/ActiveGauges",
+			&types.ActiveGaugesRequest{},
+			&types.ActiveGaugesResponse{},
+		},
+		{
+			"Query active gauges per denom",
+			"/osmosis.incentives.Query/ActiveGaugesPerDenom",
+			&types.ActiveGaugesPerDenomRequest{Denom: "stake"},
+			&types.ActiveGaugesPerDenomResponse{},
+		},
+		{
+			"Query gauge by id",
+			"/osmosis.incentives.Query/GaugeByID",
+			&types.GaugeByIDRequest{Id: 1},
+			&types.GaugeByIDResponse{},
+		},
+		{
+			"Query all gauges",
+			"/osmosis.incentives.Query/Gauges",
+			&types.GaugesRequest{},
+			&types.GaugesResponse{},
+		},
+		{
+			"Query lockable durations",
+			"/osmosis.incentives.Query/LockableDurations",
+			&types.QueryLockableDurationsRequest{},
+			&types.QueryLockableDurationsResponse{},
+		},
+		{
+			"Query module to distibute coins",
+			"/osmosis.incentives.Query/ModuleToDistributeCoins",
+			&types.ModuleToDistributeCoinsRequest{},
+			&types.ModuleToDistributeCoinsResponse{},
+		},
+		{
+			"Query reward estimate",
+			"/osmosis.incentives.Query/RewardsEst",
+			&types.RewardsEstRequest{Owner: s.TestAccs[0].String()},
+			&types.RewardsEstResponse{},
+		},
+		{
+			"Query upcoming gauges",
+			"/osmosis.incentives.Query/UpcomingGauges",
+			&types.UpcomingGaugesRequest{},
+			&types.UpcomingGaugesResponse{},
+		},
+		{
+			"Query upcoming gauges",
+			"/osmosis.incentives.Query/UpcomingGaugesPerDenom",
+			&types.UpcomingGaugesPerDenomRequest{Denom: "stake"},
+			&types.UpcomingGaugesPerDenomResponse{},
+		},
+	}
+
+	for _, tc := range testCases {
+		tc := tc
+
+		s.Run(tc.name, func() {
+			s.SetupSuite()
+			err := s.QueryHelper.Invoke(gocontext.Background(), tc.query, tc.input, tc.output)
+			s.Require().NoError(err)
+			s.StateNotAltered()
+		})
+	}
+}
+
+func TestQueryTestSuite(t *testing.T) {
+	suite.Run(t, new(QueryTestSuite))
+}
diff --git a/x/lockup/client/cli/query_test.go b/x/lockup/client/cli/query_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..9532c5137d3353600407dbe7be95f38ecec6920b
--- /dev/null
+++ b/x/lockup/client/cli/query_test.go
@@ -0,0 +1,152 @@
+package cli_test
+
+import (
+	gocontext "context"
+	"testing"
+	"time"
+
+	"github.com/stretchr/testify/suite"
+
+	"github.com/osmosis-labs/osmosis/v12/app/apptesting"
+	"github.com/osmosis-labs/osmosis/v12/x/lockup/types"
+
+	sdk "github.com/cosmos/cosmos-sdk/types"
+)
+
+type QueryTestSuite struct {
+	apptesting.KeeperTestHelper
+	queryClient types.QueryClient
+}
+
+func (s *QueryTestSuite) SetupSuite() {
+	s.Setup()
+	s.queryClient = types.NewQueryClient(s.QueryHelper)
+
+	// create a pool
+	s.PrepareBalancerPool()
+	// set up lock with id = 1
+	s.LockTokens(s.TestAccs[0], sdk.Coins{sdk.NewCoin("gamm/pool/1", sdk.NewInt(1000000))}, time.Hour*24)
+
+	s.Commit()
+}
+
+func (s *QueryTestSuite) TestQueriesNeverAlterState() {
+	testCases := []struct {
+		name   string
+		query  string
+		input  interface{}
+		output interface{}
+	}{
+		{
+			"Query account locked coins",
+			"/osmosis.lockup.Query/AccountLockedCoins",
+			&types.AccountLockedCoinsRequest{Owner: s.TestAccs[0].String()},
+			&types.AccountLockedCoinsResponse{},
+		},
+		{
+			"Query account locked by duration",
+			"/osmosis.lockup.Query/AccountLockedDuration",
+			&types.AccountLockedDurationRequest{Owner: s.TestAccs[0].String(), Duration: time.Hour * 24},
+			&types.AccountLockedDurationResponse{},
+		},
+		{
+			"Query account locked longer than given duration",
+			"/osmosis.lockup.Query/AccountLockedLongerDuration",
+			&types.AccountLockedLongerDurationRequest{Owner: s.TestAccs[0].String(), Duration: time.Hour},
+			&types.AccountLockedLongerDurationResponse{},
+		},
+		{
+			"Query account locked by denom that longer than given duration",
+			"/osmosis.lockup.Query/AccountLockedLongerDurationDenom",
+			&types.AccountLockedLongerDurationDenomRequest{Owner: s.TestAccs[0].String(), Duration: time.Hour, Denom: "gamm/pool/1"},
+			&types.AccountLockedLongerDurationDenomResponse{},
+		},
+		{
+			"Query account locked longer than given duration not unlocking",
+			"/osmosis.lockup.Query/AccountLockedLongerDurationNotUnlockingOnly",
+			&types.AccountLockedLongerDurationNotUnlockingOnlyRequest{Owner: s.TestAccs[0].String(), Duration: time.Hour},
+			&types.AccountLockedLongerDurationNotUnlockingOnlyResponse{},
+		},
+		{
+			"Query account locked in past time",
+			"/osmosis.lockup.Query/AccountLockedPastTime",
+			&types.AccountLockedPastTimeRequest{Owner: s.TestAccs[0].String()},
+			&types.AccountLockedPastTimeResponse{},
+		},
+		{
+			"Query account locked in past time by denom",
+			"/osmosis.lockup.Query/AccountLockedPastTimeDenom",
+			&types.AccountLockedPastTimeDenomRequest{Owner: s.TestAccs[0].String(), Denom: "gamm/pool/1"},
+			&types.AccountLockedPastTimeDenomResponse{},
+		},
+		{
+			" Query account locked in past time that not unlocking",
+			"/osmosis.lockup.Query/AccountLockedPastTimeNotUnlockingOnly",
+			&types.AccountLockedPastTimeNotUnlockingOnlyRequest{Owner: s.TestAccs[0].String()},
+			&types.AccountLockedPastTimeNotUnlockingOnlyResponse{},
+		},
+		{
+			"Query account unlockable coins",
+			"/osmosis.lockup.Query/AccountUnlockableCoins",
+			&types.AccountUnlockableCoinsRequest{Owner: s.TestAccs[0].String()},
+			&types.AccountUnlockableCoinsResponse{},
+		},
+		{
+			"Query account unlocked before given time",
+			"/osmosis.lockup.Query/AccountUnlockedBeforeTime",
+			&types.AccountUnlockedBeforeTimeRequest{Owner: s.TestAccs[0].String()},
+			&types.AccountUnlockedBeforeTimeResponse{},
+		},
+		{
+			"Query account unlocking coins",
+			"/osmosis.lockup.Query/AccountUnlockingCoins",
+			&types.AccountUnlockingCoinsRequest{Owner: s.TestAccs[0].String()},
+			&types.AccountUnlockingCoinsResponse{},
+		},
+		{
+			"Query lock by id",
+			"/osmosis.lockup.Query/LockedByID",
+			&types.LockedRequest{LockId: 1},
+			&types.LockedResponse{},
+		},
+		{
+			"Query lock by denom",
+			"/osmosis.lockup.Query/LockedDenom",
+			&types.LockedDenomRequest{Duration: time.Hour * 24, Denom: "gamm/pool/1"},
+			&types.LockedDenomResponse{},
+		},
+		{
+			"Query module balances",
+			"/osmosis.lockup.Query/ModuleBalance",
+			&types.ModuleBalanceRequest{},
+			&types.ModuleBalanceResponse{},
+		},
+		{
+			"Query module locked amount",
+			"/osmosis.lockup.Query/ModuleLockedAmount",
+			&types.ModuleLockedAmountRequest{},
+			&types.ModuleLockedAmountResponse{},
+		},
+		{
+			"Query synthetic lock by id",
+			"/osmosis.lockup.Query/SyntheticLockupsByLockupID",
+			&types.SyntheticLockupsByLockupIDRequest{LockId: 1},
+			&types.SyntheticLockupsByLockupIDResponse{},
+		},
+	}
+
+	for _, tc := range testCases {
+		tc := tc
+
+		s.Run(tc.name, func() {
+			s.SetupSuite()
+			err := s.QueryHelper.Invoke(gocontext.Background(), tc.query, tc.input, tc.output)
+			s.Require().NoError(err)
+			s.StateNotAltered()
+		})
+	}
+}
+
+func TestQueryTestSuite(t *testing.T) {
+	suite.Run(t, new(QueryTestSuite))
+}
diff --git a/x/mint/client/cli/query_test.go b/x/mint/client/cli/query_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..84ba9dc66058204dccb805a786d9cbe4194563f1
--- /dev/null
+++ b/x/mint/client/cli/query_test.go
@@ -0,0 +1,60 @@
+package cli_test
+
+import (
+	gocontext "context"
+	"testing"
+
+	"github.com/stretchr/testify/suite"
+
+	"github.com/osmosis-labs/osmosis/v12/app/apptesting"
+	"github.com/osmosis-labs/osmosis/v12/x/mint/types"
+)
+
+type QueryTestSuite struct {
+	apptesting.KeeperTestHelper
+	queryClient types.QueryClient
+}
+
+func (s *QueryTestSuite) SetupSuite() {
+	s.Setup()
+	s.queryClient = types.NewQueryClient(s.QueryHelper)
+
+	s.Commit()
+}
+
+func (s *QueryTestSuite) TestQueriesNeverAlterState() {
+	testCases := []struct {
+		name   string
+		query  string
+		input  interface{}
+		output interface{}
+	}{
+		{
+			"Query epoch provisions",
+			"/osmosis.mint.v1beta1.Query/EpochProvisions",
+			&types.QueryEpochProvisionsRequest{},
+			&types.QueryEpochProvisionsResponse{},
+		},
+		{
+			"Query params",
+			"/osmosis.mint.v1beta1.Query/Params",
+			&types.QueryParamsRequest{},
+			&types.QueryParamsResponse{},
+		},
+	}
+
+	for _, tc := range testCases {
+		tc := tc
+
+		s.Run(tc.name, func() {
+			s.SetupSuite()
+			err := s.QueryHelper.Invoke(gocontext.Background(), tc.query, tc.input, tc.output)
+			s.Require().NoError(err)
+			s.StateNotAltered()
+		})
+	}
+}
+
+func TestQueryTestSuite(t *testing.T) {
+	suite.Run(t, new(QueryTestSuite))
+}
diff --git a/x/pool-incentives/client/cli/query_test.go b/x/pool-incentives/client/cli/query_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..565e3a7d31d311f0102b601ca72364cfed61b7bd
--- /dev/null
+++ b/x/pool-incentives/client/cli/query_test.go
@@ -0,0 +1,86 @@
+package cli_test
+
+import (
+	gocontext "context"
+	"testing"
+
+	"github.com/stretchr/testify/suite"
+
+	"github.com/osmosis-labs/osmosis/v12/app/apptesting"
+	"github.com/osmosis-labs/osmosis/v12/x/pool-incentives/types"
+)
+
+type QueryTestSuite struct {
+	apptesting.KeeperTestHelper
+	queryClient types.QueryClient
+}
+
+func (s *QueryTestSuite) SetupSuite() {
+	s.Setup()
+	s.queryClient = types.NewQueryClient(s.QueryHelper)
+
+	// set up pool
+	s.PrepareBalancerPool()
+	s.Commit()
+}
+
+func (s *QueryTestSuite) TestQueriesNeverAlterState() {
+	testCases := []struct {
+		name   string
+		query  string
+		input  interface{}
+		output interface{}
+	}{
+		{
+			"Query distribution info",
+			"/osmosis.poolincentives.v1beta1.Query/DistrInfo",
+			&types.QueryDistrInfoRequest{},
+			&types.QueryDistrInfoResponse{},
+		},
+		{
+			"Query external incentive gauges",
+			"/osmosis.poolincentives.v1beta1.Query/ExternalIncentiveGauges",
+			&types.QueryExternalIncentiveGaugesRequest{},
+			&types.QueryExternalIncentiveGaugesResponse{},
+		},
+		{
+			"Query all gauge ids",
+			"/osmosis.poolincentives.v1beta1.Query/GaugeIds",
+			&types.QueryGaugeIdsRequest{PoolId: 1},
+			&types.QueryGaugeIdsResponse{},
+		},
+		{
+			"Query all incentivized pools",
+			"/osmosis.poolincentives.v1beta1.Query/IncentivizedPools",
+			&types.QueryIncentivizedPoolsRequest{},
+			&types.QueryIncentivizedPoolsResponse{},
+		},
+		{
+			"Query lockable durations",
+			"/osmosis.poolincentives.v1beta1.Query/LockableDurations",
+			&types.QueryLockableDurationsRequest{},
+			&types.QueryLockableDurationsResponse{},
+		},
+		{
+			"Query params",
+			"/osmosis.poolincentives.v1beta1.Query/Params",
+			&types.QueryParamsRequest{},
+			&types.QueryParamsResponse{},
+		},
+	}
+
+	for _, tc := range testCases {
+		tc := tc
+
+		s.Run(tc.name, func() {
+			s.SetupSuite()
+			err := s.QueryHelper.Invoke(gocontext.Background(), tc.query, tc.input, tc.output)
+			s.Require().NoError(err)
+			s.StateNotAltered()
+		})
+	}
+}
+
+func TestQueryTestSuite(t *testing.T) {
+	suite.Run(t, new(QueryTestSuite))
+}
diff --git a/x/superfluid/client/cli/query_test.go b/x/superfluid/client/cli/query_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..a6f760cc521ce11993cc3b60ec6471cd9cb4902e
--- /dev/null
+++ b/x/superfluid/client/cli/query_test.go
@@ -0,0 +1,156 @@
+package cli_test
+
+import (
+	gocontext "context"
+	"testing"
+	"time"
+
+	"github.com/stretchr/testify/suite"
+
+	sdk "github.com/cosmos/cosmos-sdk/types"
+
+	stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
+
+	"github.com/osmosis-labs/osmosis/v12/app/apptesting"
+	"github.com/osmosis-labs/osmosis/v12/x/superfluid/types"
+)
+
+type QueryTestSuite struct {
+	apptesting.KeeperTestHelper
+	queryClient types.QueryClient
+	val         sdk.ValAddress
+}
+
+func (s *QueryTestSuite) SetupSuite() {
+	s.Setup()
+	s.queryClient = types.NewQueryClient(s.QueryHelper)
+
+	// set up durations
+	s.App.IncentivesKeeper.SetLockableDurations(s.Ctx, []time.Duration{
+		time.Hour * 24 * 14,
+		time.Hour,
+		time.Hour * 3,
+		time.Hour * 7,
+		time.Hour * 24 * 21,
+	})
+	// set up pool
+	s.SetupGammPoolsWithBondDenomMultiplier([]sdk.Dec{sdk.NewDec(20), sdk.NewDec(20)})
+	// set up lock with id = 1
+	s.LockTokens(s.TestAccs[0], sdk.Coins{sdk.NewCoin("gamm/pool/1", sdk.NewInt(1000000))}, time.Hour*24*21)
+	// set up validator
+	s.val = s.SetupValidator(stakingtypes.Bonded)
+	// set up sfs asset
+	err := s.App.SuperfluidKeeper.AddNewSuperfluidAsset(s.Ctx, types.SuperfluidAsset{
+		Denom:     "gamm/pool/1",
+		AssetType: types.SuperfluidAssetTypeLPShare,
+	})
+	s.Require().NoError(err)
+	// set up sfs delegation
+	err = s.App.SuperfluidKeeper.SuperfluidDelegate(s.Ctx, s.TestAccs[0].String(), 1, s.val.String())
+	s.Require().NoError(err)
+
+	s.Commit()
+}
+
+func (s *QueryTestSuite) TestQueriesNeverAlterState() {
+	s.SetupSuite()
+	testCases := []struct {
+		name   string
+		query  string
+		input  interface{}
+		output interface{}
+	}{
+		{
+			"Query all superfluild assets",
+			"/osmosis.superfluid.Query/AllAssets",
+			&types.AllAssetsRequest{},
+			&types.AllAssetsResponse{},
+		},
+		{
+			"Query all intermediary accounts",
+			"/osmosis.superfluid.Query/AllIntermediaryAccounts",
+			&types.AllIntermediaryAccountsRequest{},
+			&types.AllIntermediaryAccountsResponse{},
+		},
+		{
+			"Query osmo equivalent multiplier of an asset",
+			"/osmosis.superfluid.Query/AssetMultiplier",
+			&types.AssetMultiplierRequest{Denom: "gamm/pool/1"},
+			&types.AssetMultiplierResponse{},
+		},
+		{
+			"Query asset type",
+			"/osmosis.superfluid.Query/AssetType",
+			&types.AssetTypeRequest{Denom: "gamm/pool/1"},
+			&types.AssetTypeResponse{},
+		},
+		{
+			"Query connected intermediary account",
+			"/osmosis.superfluid.Query/ConnectedIntermediaryAccount",
+			&types.ConnectedIntermediaryAccountRequest{LockId: 1},
+			&types.ConnectedIntermediaryAccountResponse{},
+		},
+		{
+			"Query estimate sfs delegated amount by validator & denom",
+			"/osmosis.superfluid.Query/EstimateSuperfluidDelegatedAmountByValidatorDenom",
+			&types.EstimateSuperfluidDelegatedAmountByValidatorDenomRequest{ValidatorAddress: s.val.String(), Denom: "gamm/pool/1"},
+			&types.EstimateSuperfluidDelegatedAmountByValidatorDenomResponse{},
+		},
+		{
+			"Query params",
+			"/osmosis.superfluid.Query/Params",
+			&types.QueryParamsRequest{},
+			&types.QueryParamsResponse{},
+		},
+		{
+			"Query sfs delegation amount",
+			"/osmosis.superfluid.Query/SuperfluidDelegationAmount",
+			&types.SuperfluidDelegationAmountRequest{ValidatorAddress: s.val.String(), Denom: "gamm/pool/1", DelegatorAddress: s.TestAccs[0].String()},
+			&types.SuperfluidDelegationAmountResponse{},
+		},
+		{
+			"Query sfs delegation by delegator",
+			"/osmosis.superfluid.Query/SuperfluidDelegationsByDelegator",
+			&types.SuperfluidDelegationsByDelegatorRequest{DelegatorAddress: s.TestAccs[0].String()},
+			&types.SuperfluidDelegationsByDelegatorResponse{},
+		},
+		{
+			"Query sfs delegation by validator & denom",
+			"/osmosis.superfluid.Query/SuperfluidDelegationsByValidatorDenom",
+			&types.SuperfluidDelegationsByValidatorDenomRequest{ValidatorAddress: s.val.String(), Denom: "gamm/pool/1"},
+			&types.SuperfluidDelegationsByValidatorDenomResponse{},
+		},
+		{
+			"Query sfs undelegation by delegator",
+			"/osmosis.superfluid.Query/SuperfluidUndelegationsByDelegator",
+			&types.SuperfluidUndelegationsByDelegatorRequest{DelegatorAddress: s.TestAccs[0].String(), Denom: "gamm/pool/1"},
+			&types.SuperfluidUndelegationsByDelegatorResponse{},
+		},
+		{
+			"Query total sfs delegation by delegator",
+			"/osmosis.superfluid.Query/TotalDelegationByDelegator",
+			&types.QueryTotalDelegationByDelegatorRequest{DelegatorAddress: s.TestAccs[0].String()},
+			&types.QueryTotalDelegationByDelegatorResponse{},
+		},
+		{
+			"Query total sfs delegations",
+			"/osmosis.superfluid.Query/TotalSuperfluidDelegations",
+			&types.TotalSuperfluidDelegationsRequest{},
+			&types.TotalSuperfluidDelegationsResponse{},
+		},
+	}
+
+	for _, tc := range testCases {
+		tc := tc
+
+		s.Run(tc.name, func() {
+			err := s.QueryHelper.Invoke(gocontext.Background(), tc.query, tc.input, tc.output)
+			s.Require().NoError(err)
+			s.StateNotAltered()
+		})
+	}
+}
+
+func TestQueryTestSuite(t *testing.T) {
+	suite.Run(t, new(QueryTestSuite))
+}
diff --git a/x/tokenfactory/client/cli/query_test.go b/x/tokenfactory/client/cli/query_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..ea756feb9e9b79865e1fb5c52476d6b3620c2cad
--- /dev/null
+++ b/x/tokenfactory/client/cli/query_test.go
@@ -0,0 +1,75 @@
+package cli_test
+
+import (
+	gocontext "context"
+	"testing"
+
+	"github.com/stretchr/testify/suite"
+
+	sdk "github.com/cosmos/cosmos-sdk/types"
+
+	"github.com/osmosis-labs/osmosis/v12/app/apptesting"
+	"github.com/osmosis-labs/osmosis/v12/x/tokenfactory/types"
+)
+
+type QueryTestSuite struct {
+	apptesting.KeeperTestHelper
+	queryClient types.QueryClient
+}
+
+func (s *QueryTestSuite) SetupSuite() {
+	s.Setup()
+	s.queryClient = types.NewQueryClient(s.QueryHelper)
+
+	// fund acc
+	fundAccsAmount := sdk.NewCoins(sdk.NewCoin(types.DefaultParams().DenomCreationFee[0].Denom, types.DefaultParams().DenomCreationFee[0].Amount.MulRaw(100)), sdk.NewCoin(apptesting.SecondaryDenom, apptesting.SecondaryAmount))
+	s.FundAcc(s.TestAccs[0], fundAccsAmount)
+	// create new token
+	_, err := s.App.TokenFactoryKeeper.CreateDenom(s.Ctx, s.TestAccs[0].String(), "tokenfactory")
+	s.Require().NoError(err)
+
+	s.Commit()
+}
+
+func (s *QueryTestSuite) TestQueriesNeverAlterState() {
+	testCases := []struct {
+		name   string
+		query  string
+		input  interface{}
+		output interface{}
+	}{
+		{
+			"Query denom authority metadata",
+			"/osmosis.tokenfactory.v1beta1.Query/DenomAuthorityMetadata",
+			&types.QueryDenomAuthorityMetadataRequest{Denom: "tokenfactory"},
+			&types.QueryDenomAuthorityMetadataResponse{},
+		},
+		{
+			"Query denoms by creator",
+			"/osmosis.tokenfactory.v1beta1.Query/DenomsFromCreator",
+			&types.QueryDenomsFromCreatorRequest{Creator: s.TestAccs[0].String()},
+			&types.QueryDenomsFromCreatorResponse{},
+		},
+		{
+			"Query params",
+			"/osmosis.tokenfactory.v1beta1.Query/Params",
+			&types.QueryParamsRequest{},
+			&types.QueryParamsResponse{},
+		},
+	}
+
+	for _, tc := range testCases {
+		tc := tc
+
+		s.Run(tc.name, func() {
+			s.SetupSuite()
+			err := s.QueryHelper.Invoke(gocontext.Background(), tc.query, tc.input, tc.output)
+			s.Require().NoError(err)
+			s.StateNotAltered()
+		})
+	}
+}
+
+func TestQueryTestSuite(t *testing.T) {
+	suite.Run(t, new(QueryTestSuite))
+}
diff --git a/x/txfees/client/cli/query_test.go b/x/txfees/client/cli/query_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..7575d3eb902c060074bcdb4d0a3c667bceb240ce
--- /dev/null
+++ b/x/txfees/client/cli/query_test.go
@@ -0,0 +1,92 @@
+package cli_test
+
+import (
+	gocontext "context"
+	"testing"
+
+	"github.com/stretchr/testify/suite"
+
+	sdk "github.com/cosmos/cosmos-sdk/types"
+
+	"github.com/osmosis-labs/osmosis/v12/app/apptesting"
+	"github.com/osmosis-labs/osmosis/v12/x/txfees/types"
+)
+
+type QueryTestSuite struct {
+	apptesting.KeeperTestHelper
+	queryClient types.QueryClient
+}
+
+func (s *QueryTestSuite) SetupSuite() {
+	s.Setup()
+	s.queryClient = types.NewQueryClient(s.QueryHelper)
+
+	// set up pool
+	poolAssets := []sdk.Coin{
+		sdk.NewInt64Coin("uosmo", 1000000),
+		sdk.NewInt64Coin("stake", 120000000),
+	}
+	s.PrepareBalancerPoolWithCoins(poolAssets...)
+
+	// set up fee token
+	upgradeProp := types.NewUpdateFeeTokenProposal(
+		"Test Proposal",
+		"test",
+		types.FeeToken{
+			Denom:  "uosmo",
+			PoolID: 1,
+		},
+	)
+	err := s.App.TxFeesKeeper.HandleUpdateFeeTokenProposal(s.Ctx, &upgradeProp)
+	s.Require().NoError(err)
+
+	s.Commit()
+}
+
+func (s *QueryTestSuite) TestQueriesNeverAlterState() {
+	testCases := []struct {
+		name   string
+		query  string
+		input  interface{}
+		output interface{}
+	}{
+		{
+			"Query base denom",
+			"/osmosis.txfees.v1beta1.Query/BaseDenom",
+			&types.QueryBaseDenomRequest{},
+			&types.QueryBaseDenomResponse{},
+		},
+		{
+			"Query poolID by denom",
+			"/osmosis.txfees.v1beta1.Query/DenomPoolId",
+			&types.QueryDenomPoolIdRequest{Denom: "uosmo"},
+			&types.QueryDenomPoolIdResponse{},
+		},
+		{
+			"Query spot price by denom",
+			"/osmosis.txfees.v1beta1.Query/DenomSpotPrice",
+			&types.QueryDenomSpotPriceRequest{Denom: "uosmo"},
+			&types.QueryDenomSpotPriceResponse{},
+		},
+		{
+			"Query fee tokens",
+			"/osmosis.txfees.v1beta1.Query/FeeTokens",
+			&types.QueryFeeTokensRequest{},
+			&types.QueryFeeTokensResponse{},
+		},
+	}
+
+	for _, tc := range testCases {
+		tc := tc
+		s.Run(tc.name, func() {
+			s.SetupSuite()
+			err := s.QueryHelper.Invoke(gocontext.Background(), tc.query, tc.input, tc.output)
+			s.Require().NoError(err)
+			s.StateNotAltered()
+		})
+	}
+}
+
+func TestQueryTestSuite(t *testing.T) {
+	suite.Run(t, new(QueryTestSuite))
+}