diff --git a/app/app.go b/app/app.go
index b77c60b762..e6a40fb095 100644
--- a/app/app.go
+++ b/app/app.go
@@ -422,15 +422,21 @@ func New(
 	}
 
 	baseAppOptions = memiavlstore.SetupMemIAVL(logger, homePath, appOpts, false, false, baseAppOptions)
-	mempool := mempool.NoOpMempool{}
-
-	blockProposalHandler := NewProposalHandler(encodingConfig.TxConfig.TxDecoder(), identity, mempool)
+	blockProposalHandler := NewProposalHandler(encodingConfig.TxConfig.TxDecoder(), identity)
 
 	// NOTE we use custom transaction decoder that supports the sdk.Tx interface instead of sdk.StdTx
 	// Setup Mempool and Proposal Handlers
 	baseAppOptions = append(baseAppOptions, func(app *baseapp.BaseApp) {
+		mempool := mempool.NoOpMempool{}
 		app.SetMempool(mempool)
-		app.SetPrepareProposal(blockProposalHandler.PrepareProposalHandler(app))
+
+		// Re-use the default prepare proposal handler, extend the transaction validation logic
+		defaultProposalHandler := baseapp.NewDefaultProposalHandler(mempool, app)
+		defaultProposalHandler.SetTxSelector(NewExtTxSelector(baseapp.NewDefaultTxSelector(), blockProposalHandler.ValidateTransaction))
+		app.SetPrepareProposal(defaultProposalHandler.PrepareProposalHandler())
+
+		// The default process proposal handler do nothing when the mempool is noop,
+		// so we just implement a new one.
 		app.SetProcessProposal(blockProposalHandler.ProcessProposalHandler())
 	})
 	bApp := baseapp.NewBaseApp(Name, logger, db, encodingConfig.TxConfig.TxDecoder(), baseAppOptions...)
diff --git a/app/proposal.go b/app/proposal.go
index a5511bcd45..ce6d965bdb 100644
--- a/app/proposal.go
+++ b/app/proposal.go
@@ -11,7 +11,6 @@ import (
 	abci "github.com/cometbft/cometbft/abci/types"
 	"github.com/cosmos/cosmos-sdk/baseapp"
 	sdk "github.com/cosmos/cosmos-sdk/types"
-	"github.com/cosmos/cosmos-sdk/types/mempool"
 	"github.com/cosmos/cosmos-sdk/x/auth/signing"
 )
 
@@ -19,20 +18,34 @@ type BlockList struct {
 	Addresses []string `mapstructure:"addresses"`
 }
 
-type txSelector struct {
-	baseapp.TxSelector
-	handler *ProposalHandler
+var _ baseapp.TxSelector = &ExtTxSelector{}
+
+// ExtTxSelector extends a baseapp.TxSelector with extra tx validation method
+type ExtTxSelector struct {
+	Parent     baseapp.TxSelector
+	ValidateTx func(sdk.Tx) error
 }
 
-func (ts *txSelector) SelectTxForProposal(maxTxBytes, maxBlockGas uint64, memTx sdk.Tx, txBz []byte) bool {
-	tx, err := ts.handler.TxDecoder(txBz)
-	if err != nil {
-		return false
+func NewExtTxSelector(parent baseapp.TxSelector, validateTx func(sdk.Tx) error) *ExtTxSelector {
+	return &ExtTxSelector{
+		Parent:     parent,
+		ValidateTx: validateTx,
 	}
-	if err = ts.handler.ValidateTransaction(tx); err != nil {
+}
+
+func (ts *ExtTxSelector) SelectTxForProposal(maxTxBytes, maxBlockGas uint64, memTx sdk.Tx, txBz []byte) bool {
+	if err := ts.ValidateTx(memTx); err != nil {
 		return false
 	}
-	return ts.TxSelector.SelectTxForProposal(maxTxBytes, maxBlockGas, memTx, txBz)
+	return ts.Parent.SelectTxForProposal(maxTxBytes, maxBlockGas, memTx, txBz)
+}
+
+func (ts *ExtTxSelector) SelectedTxs() [][]byte {
+	return ts.Parent.SelectedTxs()
+}
+
+func (ts *ExtTxSelector) Clear() {
+	ts.Parent.Clear()
 }
 
 type ProposalHandler struct {
@@ -41,15 +54,13 @@ type ProposalHandler struct {
 
 	blocklist     map[string]struct{}
 	lastBlockList []byte
-	mempool       mempool.Mempool
 }
 
-func NewProposalHandler(txDecoder sdk.TxDecoder, identity age.Identity, mempool mempool.Mempool) *ProposalHandler {
+func NewProposalHandler(txDecoder sdk.TxDecoder, identity age.Identity) *ProposalHandler {
 	return &ProposalHandler{
 		TxDecoder: txDecoder,
 		Identity:  identity,
 		blocklist: make(map[string]struct{}),
-		mempool:   mempool,
 	}
 }
 
@@ -112,15 +123,6 @@ func (h *ProposalHandler) ValidateTransaction(tx sdk.Tx) error {
 	return nil
 }
 
-func (h *ProposalHandler) PrepareProposalHandler(txVerifier baseapp.ProposalTxVerifier) sdk.PrepareProposalHandler {
-	defaultHandler := baseapp.NewDefaultProposalHandler(h.mempool, txVerifier)
-	defaultHandler.SetTxSelector(&txSelector{
-		TxSelector: baseapp.NewDefaultTxSelector(),
-		handler:    h,
-	})
-	return defaultHandler.PrepareProposalHandler()
-}
-
 func (h *ProposalHandler) ProcessProposalHandler() sdk.ProcessProposalHandler {
 	return func(ctx sdk.Context, req abci.RequestProcessProposal) abci.ResponseProcessProposal {
 		for _, txBz := range req.Txs {