> ## Documentation Index
> Fetch the complete documentation index at: https://cosmos-docs-sync-security-docs.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Module Simulation

<Note>
  **Prerequisite Readings**

  * [Cosmos Blockchain Simulator](/sdk/v0.53/learn/advanced/simulation)
</Note>

## Synopsis

This document guides developers on integrating their custom modules with the Cosmos SDK `Simulations`.
Simulations are useful for testing edge cases in module implementations.

* [Simulation Package](#simulation-package)
* [Simulation App Module](#simulation-app-module)
* [SimsX](#simsx)
  * [Example Implementations](#example-implementations)
* [Store decoders](#store-decoders)
* [Randomized genesis](#randomized-genesis)
* [Random weighted operations](#random-weighted-operations)
  * [Using Simsx](#using-simsx)
* [App Simulator manager](#app-simulator-manager)
* [Running Simulations](#running-simulations)

## Simulation Package

The Cosmos SDK suggests organizing your simulation related code in a `x/<module>/simulation` package.

## Simulation App Module

To integrate with the Cosmos SDK `SimulationManager`, app modules must implement the `AppModuleSimulation` interface.

```go expandable theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
package module

import (
    
	"encoding/json"
    "math/rand"
    "sort"
    "time"

	sdkmath "cosmossdk.io/math"
    "github.com/cosmos/cosmos-sdk/client"
    "github.com/cosmos/cosmos-sdk/codec"
    "github.com/cosmos/cosmos-sdk/types/simulation"
)

// AppModuleSimulation defines the standard functions that every module should expose
// for the SDK blockchain simulator
type AppModuleSimulation interface {
	// randomized genesis states
	GenerateGenesisState(input *SimulationState)

	// register a func to decode the each module's defined types from their corresponding store key
	RegisterStoreDecoder(simulation.StoreDecoderRegistry)

	// simulation operations (i.e msgs)

with their respective weight
	WeightedOperations(simState SimulationState) []simulation.WeightedOperation
}

// HasProposalMsgs defines the messages that can be used to simulate governance (v1)

proposals
type HasProposalMsgs interface {
	// msg functions used to simulate governance proposals
	ProposalMsgs(simState SimulationState) []simulation.WeightedProposalMsg
}

// HasProposalContents defines the contents that can be used to simulate legacy governance (v1beta1)

proposals
type HasProposalContents interface {
	// content functions used to simulate governance proposals
	ProposalContents(simState SimulationState) []simulation.WeightedProposalContent //nolint:staticcheck // legacy v1beta1 governance
}

// SimulationManager defines a simulation manager that provides the high level utility
// for managing and executing simulation functionalities for a group of modules
type SimulationManager struct {
    Modules       []AppModuleSimulation           // array of app modules; we use an array for deterministic simulation tests
	StoreDecoders simulation.StoreDecoderRegistry // functions to decode the key-value pairs from each module's store
}

// NewSimulationManager creates a new SimulationManager object
//
// CONTRACT: All the modules provided must be also registered on the module Manager
func NewSimulationManager(modules ...AppModuleSimulation) *SimulationManager {
    return &SimulationManager{
    Modules:       modules,
    StoreDecoders: make(simulation.StoreDecoderRegistry),
}
}

// NewSimulationManagerFromAppModules creates a new SimulationManager object.
//
// First it sets any SimulationModule provided by overrideModules, and ignores any AppModule
// with the same moduleName.
// Then it attempts to cast every provided AppModule into an AppModuleSimulation.
// If the cast succeeds, its included, otherwise it is excluded.
func NewSimulationManagerFromAppModules(modules map[string]any, overrideModules map[string]AppModuleSimulation) *SimulationManager {
    simModules := []AppModuleSimulation{
}
    appModuleNamesSorted := make([]string, 0, len(modules))
    for moduleName := range modules {
    appModuleNamesSorted = append(appModuleNamesSorted, moduleName)
}

sort.Strings(appModuleNamesSorted)
    for _, moduleName := range appModuleNamesSorted {
		// for every module, see if we override it. If so, use override.
		// Else, if we can cast the app module into a simulation module add it.
		// otherwise no simulation module.
    if simModule, ok := overrideModules[moduleName]; ok {
    simModules = append(simModules, simModule)
}

else {
    appModule := modules[moduleName]
    if simModule, ok := appModule.(AppModuleSimulation); ok {
    simModules = append(simModules, simModule)
}
			// cannot cast, so we continue
}
	
}

return NewSimulationManager(simModules...)
}

// Deprecated: Use GetProposalMsgs instead.
// GetProposalContents returns each module's proposal content generator function
// with their default operation weight and key.
func (sm *SimulationManager)

GetProposalContents(simState SimulationState) []simulation.WeightedProposalContent {
    wContents := make([]simulation.WeightedProposalContent, 0, len(sm.Modules))
    for _, module := range sm.Modules {
    if module, ok := module.(HasProposalContents); ok {
    wContents = append(wContents, module.ProposalContents(simState)...)
}
	
}

return wContents
}

// GetProposalMsgs returns each module's proposal msg generator function
// with their default operation weight and key.
func (sm *SimulationManager)

GetProposalMsgs(simState SimulationState) []simulation.WeightedProposalMsg {
    wContents := make([]simulation.WeightedProposalMsg, 0, len(sm.Modules))
    for _, module := range sm.Modules {
    if module, ok := module.(HasProposalMsgs); ok {
    wContents = append(wContents, module.ProposalMsgs(simState)...)
}
	
}

return wContents
}

// RegisterStoreDecoders registers each of the modules' store decoders into a map
func (sm *SimulationManager)

RegisterStoreDecoders() {
    for _, module := range sm.Modules {
    module.RegisterStoreDecoder(sm.StoreDecoders)
}
}

// GenerateGenesisStates generates a randomized GenesisState for each of the
// registered modules
func (sm *SimulationManager)

GenerateGenesisStates(simState *SimulationState) {
    for _, module := range sm.Modules {
    module.GenerateGenesisState(simState)
}
}

// WeightedOperations returns all the modules' weighted operations of an application
func (sm *SimulationManager)

WeightedOperations(simState SimulationState) []simulation.WeightedOperation {
    wOps := make([]simulation.WeightedOperation, 0, len(sm.Modules))
    for _, module := range sm.Modules {
    wOps = append(wOps, module.WeightedOperations(simState)...)
}

return wOps
}

// SimulationState is the input parameters used on each of the module's randomized
// GenesisState generator function
type SimulationState struct {
    AppParams         simulation.AppParams
	Cdc               codec.JSONCodec                // application codec
	TxConfig          client.TxConfig                // Shared TxConfig; this is expensive to create and stateless, so create it once up front.
	Rand              *rand.Rand                     // random number
	GenState          map[string]json.RawMessage     // genesis state
	Accounts          []simulation.Account           // simulation accounts
	InitialStake      sdkmath.Int                    // initial coins per account
	NumBonded         int64                          // number of initially bonded accounts
	BondDenom         string                         // denom to be used as default
	GenTimestamp      time.Time                      // genesis timestamp
	UnbondTime        time.Duration                  // staking unbond time stored to use it as the slashing maximum evidence duration
	LegacyParamChange []simulation.LegacyParamChange // simulated parameter changes from modules
	//nolint:staticcheck //	legacy used for testing
	LegacyProposalContents []simulation.WeightedProposalContent // proposal content generator functions with their default weight and app sim key
	ProposalMsgs           []simulation.WeightedProposalMsg     // proposal msg generator functions with their default weight and app sim key
}
```

See an example implementation of these methods from `x/distribution` [here](https://github.com/cosmos/cosmos-sdk/blob/b55b9e14fb792cc8075effb373be9d26327fddea/x/distribution/module.go#L170-L194).

## SimsX

Cosmos SDK v0.53.0 introduced a new package, `simsx`, providing improved DevX for writing simulation code.

It exposes the following extension interfaces that modules may implement to integrate with the new `simsx` runner.

```go expandable theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
package simsx

import (
    
	"encoding/json"
    "fmt"
    "io"
    "math"
    "os"
    "path/filepath"
    "strings"
    "testing"

	dbm "github.com/cosmos/cosmos-db"
    "github.com/stretchr/testify/require"
    "cosmossdk.io/log"
    "github.com/cosmos/cosmos-sdk/baseapp"
    "github.com/cosmos/cosmos-sdk/client"
    "github.com/cosmos/cosmos-sdk/client/flags"
    "github.com/cosmos/cosmos-sdk/codec"
    "github.com/cosmos/cosmos-sdk/runtime"
	servertypes "github.com/cosmos/cosmos-sdk/server/types"
	simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims"
	sdk "github.com/cosmos/cosmos-sdk/types"
    "github.com/cosmos/cosmos-sdk/types/module"
	simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
    "github.com/cosmos/cosmos-sdk/x/simulation"
    "github.com/cosmos/cosmos-sdk/x/simulation/client/cli"
)

const SimAppChainID = "simulation-app"

// this list of seeds was imported from the original simulation runner: https://github.com/cosmos/tools/blob/v1.0.0/cmd/runsim/main.go#L32
var defaultSeeds = []int64{
	1, 2, 4, 7,
	32, 123, 124, 582, 1893, 2989,
	3012, 4728, 37827, 981928, 87821, 891823782,
	989182, 89182391, 11, 22, 44, 77, 99, 2020,
	3232, 123123, 124124, 582582, 18931893,
	29892989, 30123012, 47284728, 7601778, 8090485,
	977367484, 491163361, 424254581, 673398983,
}

// SimStateFactory is a factory type that provides a convenient way to create a simulation state for testing.
// It contains the following fields:
// - Codec: a codec used for serializing other objects
// - AppStateFn: a function that returns the app state JSON bytes and the genesis accounts
// - BlockedAddr: a map of blocked addresses
// - AccountSource: an interface for retrieving accounts
// - BalanceSource: an interface for retrieving balance-related information
type SimStateFactory struct {
    Codec         codec.Codec
	AppStateFn    simtypes.AppStateFn
	BlockedAddr   map[string]bool
	AccountSource AccountSourceX
	BalanceSource BalanceSource
}

// SimulationApp abstract app that is used by sims
type SimulationApp interface {
    runtime.AppI
	SetNotSigverifyTx()

GetBaseApp() *baseapp.BaseApp
	TxConfig()

client.TxConfig
	Close()

error
}

// Run is a helper function that runs a simulation test with the given parameters.
// It calls the RunWithSeeds function with the default seeds and parameters.
//
// This is the entrypoint to run simulation tests that used to run with the runsim binary.
func Run[T SimulationApp](
	t *testing.T,
	appFactory func(
		logger log.Logger,
		db dbm.DB,
		traceStore io.Writer,
		loadLatest bool,
		appOpts servertypes.AppOptions,
		baseAppOptions ...func(*baseapp.BaseApp),
	)

T,
	setupStateFactory func(app T)

SimStateFactory,
	postRunActions ...func(t testing.TB, app TestInstance[T], accs []simtypes.Account),
) {
    t.Helper()

RunWithSeeds(t, appFactory, setupStateFactory, defaultSeeds, nil, postRunActions...)
}

// RunWithSeeds is a helper function that runs a simulation test with the given parameters.
// It iterates over the provided seeds and runs the simulation test for each seed in parallel.
//
// It sets up the environment, creates an instance of the simulation app,
// calls the simulation.SimulateFromSeed function to run the simulation, and performs post-run actions for each seed.
// The execution is deterministic and can be used for fuzz tests as well.
//
// The system under test is isolated for each run but unlike the old runsim command, there is no Process separation.
// This means, global caches may be reused for example. This implementation build upon the vanilla Go stdlib test framework.
func RunWithSeeds[T SimulationApp](
	t *testing.T,
	appFactory func(
		logger log.Logger,
		db dbm.DB,
		traceStore io.Writer,
		loadLatest bool,
		appOpts servertypes.AppOptions,
		baseAppOptions ...func(*baseapp.BaseApp),
	)

T,
	setupStateFactory func(app T)

SimStateFactory,
	seeds []int64,
	fuzzSeed []byte,
	postRunActions ...func(t testing.TB, app TestInstance[T], accs []simtypes.Account),
) {
    t.Helper()

RunWithSeedsAndRandAcc(t, appFactory, setupStateFactory, seeds, fuzzSeed, simtypes.RandomAccounts, postRunActions...)
}

// RunWithSeedsAndRandAcc calls RunWithSeeds with randAccFn
func RunWithSeedsAndRandAcc[T SimulationApp](
	t *testing.T,
	appFactory func(
		logger log.Logger,
		db dbm.DB,
		traceStore io.Writer,
		loadLatest bool,
		appOpts servertypes.AppOptions,
		baseAppOptions ...func(*baseapp.BaseApp),
	)

T,
	setupStateFactory func(app T)

SimStateFactory,
	seeds []int64,
	fuzzSeed []byte,
	randAccFn simtypes.RandomAccountFn,
	postRunActions ...func(t testing.TB, app TestInstance[T], accs []simtypes.Account),
) {
    t.Helper()
    if deprecatedParams := cli.GetDeprecatedFlagUsed(); len(deprecatedParams) != 0 {
    fmt.Printf("Warning: Deprecated flag are used: %s", strings.Join(deprecatedParams, ","))
}
    cfg := cli.NewConfigFromFlags()

cfg.ChainID = SimAppChainID
    for i := range seeds {
    seed := seeds[i]
		t.Run(fmt.Sprintf("seed: %d", seed), func(t *testing.T) {
    t.Parallel()

RunWithSeed(t, cfg, appFactory, setupStateFactory, seed, fuzzSeed, postRunActions...)
})
}
}

// RunWithSeed is a helper function that runs a simulation test with the given parameters.
// It iterates over the provided seeds and runs the simulation test for each seed in parallel.
//
// It sets up the environment, creates an instance of the simulation app,
// calls the simulation.SimulateFromSeed function to run the simulation, and performs post-run actions for the seed.
// The execution is deterministic and can be used for fuzz tests as well.
func RunWithSeed[T SimulationApp](
	tb testing.TB,
	cfg simtypes.Config,
	appFactory func(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest bool, appOpts servertypes.AppOptions, baseAppOptions ...func(*baseapp.BaseApp))

T,
	setupStateFactory func(app T)

SimStateFactory,
	seed int64,
	fuzzSeed []byte,
	postRunActions ...func(t testing.TB, app TestInstance[T], accs []simtypes.Account),
) {
    tb.Helper()

RunWithSeedAndRandAcc(tb, cfg, appFactory, setupStateFactory, seed, fuzzSeed, simtypes.RandomAccounts, postRunActions...)
}

// RunWithSeedAndRandAcc calls RunWithSeed with randAccFn
func RunWithSeedAndRandAcc[T SimulationApp](
	tb testing.TB,
	cfg simtypes.Config,
	appFactory func(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest bool, appOpts servertypes.AppOptions, baseAppOptions ...func(*baseapp.BaseApp))

T,
	setupStateFactory func(app T)

SimStateFactory,
	seed int64,
	fuzzSeed []byte,
	randAccFn simtypes.RandomAccountFn,
	postRunActions ...func(t testing.TB, app TestInstance[T], accs []simtypes.Account),
) {
    tb.Helper()
	// setup environment
    tCfg := cfg.With(tb, seed, fuzzSeed)
    testInstance := NewSimulationAppInstance(tb, tCfg, appFactory)

var runLogger log.Logger
    if cli.FlagVerboseValue {
    runLogger = log.NewTestLogger(tb)
}

else {
    runLogger = log.NewTestLoggerInfo(tb)
}

runLogger = runLogger.With("seed", tCfg.Seed)
    app := testInstance.App
    stateFactory := setupStateFactory(app)

ops, reporter := prepareWeightedOps(app.SimulationManager(), stateFactory, tCfg, testInstance.App.TxConfig(), runLogger)

simParams, accs, err := simulation.SimulateFromSeedX(
		tb,
		runLogger,
		WriteToDebugLog(runLogger),
		app.GetBaseApp(),
		stateFactory.AppStateFn,
		randAccFn,
		ops,
		stateFactory.BlockedAddr,
		tCfg,
		stateFactory.Codec,
		testInstance.ExecLogWriter,
	)

require.NoError(tb, err)

err = simtestutil.CheckExportSimulation(app, tCfg, simParams)

require.NoError(tb, err)
    if tCfg.Commit {
    simtestutil.PrintStats(testInstance.DB)
}
	// not using tb.Log to always print the summary
	fmt.Printf("+++ DONE (seed: %d): \n%s\n", seed, reporter.Summary().String())
    for _, step := range postRunActions {
    step(tb, testInstance, accs)
}

require.NoError(tb, app.Close())
}

type (
	HasWeightedOperationsX interface {
    WeightedOperationsX(weight WeightSource, reg Registry)
}

HasWeightedOperationsXWithProposals interface {
    WeightedOperationsX(weights WeightSource, reg Registry, proposals WeightedProposalMsgIter,
			legacyProposals []simtypes.WeightedProposalContent) //nolint: staticcheck // used for legacy proposal types
}

HasProposalMsgsX interface {
    ProposalMsgsX(weights WeightSource, reg Registry)
}
)

type (
	HasLegacyWeightedOperations interface {
		// WeightedOperations simulation operations (i.e msgs)

with their respective weight
		WeightedOperations(simState module.SimulationState) []simtypes.WeightedOperation
}
	// HasLegacyProposalMsgs defines the messages that can be used to simulate governance (v1)

proposals
	// Deprecated replaced by HasProposalMsgsX
	HasLegacyProposalMsgs interface {
		// ProposalMsgs msg fu	nctions used to simulate governance proposals
		ProposalMsgs(simState module.SimulationState) []simtypes.WeightedProposalMsg
}

	// HasLegacyProposalContents defines the contents that can be used to simulate legacy governance (v1beta1)

proposals
	// Deprecated replaced by HasProposalMsgsX
	HasLegacyProposalContents interface {
		// ProposalContents content functions used to simulate governance proposals
		ProposalContents(simState module.SimulationState) []simtypes.WeightedProposalContent //nolint:staticcheck // legacy v1beta1 governance
}
)

// TestInstance is a generic type that represents an instance of a SimulationApp used for testing simulations.
// It contains the following fields:
//   - App: The instance of the SimulationApp under test.
//   - DB: The LevelDB database for the simulation app.
//   - WorkDir: The temporary working directory for the simulation app.
//   - Cfg: The configuration flags for the simulator.
//   - AppLogger: The logger used for logging in the app during the simulation, with seed value attached.
//   - ExecLogWriter: Captures block and operation data coming from the simulation
type TestInstance[T SimulationApp] struct {
    App           T
	DB            dbm.DB
	WorkDir       string
	Cfg           simtypes.Config
	AppLogger     log.Logger
	ExecLogWriter simulation.LogWriter
}

// included to avoid cyclic dependency in testutils/sims
func prepareWeightedOps(
	sm *module.SimulationManager,
	stateFact SimStateFactory,
	config simtypes.Config,
	txConfig client.TxConfig,
	logger log.Logger,
) (simulation.WeightedOperations, *BasicSimulationReporter) {
    cdc := stateFact.Codec
    simState := module.SimulationState{
    AppParams: make(simtypes.AppParams),
    Cdc:       cdc,
    TxConfig:  txConfig,
    BondDenom: sdk.DefaultBondDenom,
}
    if config.ParamsFile != "" {
    bz, err := os.ReadFile(config.ParamsFile)
    if err != nil {
    panic(err)
}

err = json.Unmarshal(bz, &simState.AppParams)
    if err != nil {
    panic(err)
}
	
}
    weights := ParamWeightSource(simState.AppParams)
    reporter := NewBasicSimulationReporter()
    pReg := make(UniqueTypeRegistry)
    wContent := make([]simtypes.WeightedProposalContent, 0) //nolint:staticcheck // required for legacy type
    legacyPReg := NewWeightedFactoryMethods()
	// add gov proposals types
    for _, m := range sm.Modules {
    switch xm := m.(type) {
    case HasProposalMsgsX:
			xm.ProposalMsgsX(weights, pReg)
    case HasLegacyProposalMsgs:
    for _, p := range xm.ProposalMsgs(simState) {
    weight := weights.Get(p.AppParamsKey(), safeUint(p.DefaultWeight()))

legacyPReg.Add(weight, legacyToMsgFactoryAdapter(p.MsgSimulatorFn()))
}
    case HasLegacyProposalContents:
			wContent = append(wContent, xm.ProposalContents(simState)...)
}
	
}
    oReg := NewSimsMsgRegistryAdapter(
		reporter,
		stateFact.AccountSource,
		stateFact.BalanceSource,
		txConfig,
		logger,
	)
    wOps := make([]simtypes.WeightedOperation, 0, len(sm.Modules))
    for _, m := range sm.Modules {
		// add operations
    switch xm := m.(type) {
    case HasWeightedOperationsX:
			xm.WeightedOperationsX(weights, oReg)
    case HasWeightedOperationsXWithProposals:
			xm.WeightedOperationsX(weights, oReg, AppendIterators(legacyPReg.Iterator(), pReg.Iterator()), wContent)
    case HasLegacyWeightedOperations:
			wOps = append(wOps, xm.WeightedOperations(simState)...)
}
	
}

return append(wOps, Collect(oReg.items, func(a weightedOperation)

simtypes.WeightedOperation {
    return a
})...), reporter
}

func safeUint(p int)

uint32 {
    if p < 0 || p > math.MaxUint32 {
    panic(fmt.Sprintf("can not cast to uint32: %d", p))
}

return uint32(p)
}

// NewSimulationAppInstance initializes and returns a TestInstance of a SimulationApp.
// The function takes a testing.T instance, a simtypes.Config instance, and an appFactory function as parameters.
// It creates a temporary working directory and a LevelDB database for the simulation app.
// The function then initializes a logger based on the verbosity flag and sets the logger's seed to the test configuration's seed.
// The database is closed and cleaned up on test completion.
func NewSimulationAppInstance[T SimulationApp](
	tb testing.TB,
	tCfg simtypes.Config,
	appFactory func(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest bool, appOpts servertypes.AppOptions, baseAppOptions ...func(*baseapp.BaseApp))

T,
)

TestInstance[T] {
    tb.Helper()
    workDir := tb.TempDir()

require.NoError(tb, os.Mkdir(filepath.Join(workDir, "data"), 0o750))
    dbDir := filepath.Join(workDir, "leveldb-app-sim")

var logger log.Logger
    if cli.FlagVerboseValue {
    logger = log.NewTestLogger(tb)
}

else {
    logger = log.NewTestLoggerError(tb)
}

logger = logger.With("seed", tCfg.Seed)

db, err := dbm.NewDB("Simulation", dbm.BackendType(tCfg.DBBackend), dbDir)

require.NoError(tb, err)

tb.Cleanup(func() {
		_ = db.Close() // ensure db is closed
})
    appOptions := make(simtestutil.AppOptionsMap)

appOptions[flags.FlagHome] = workDir
    opts := []func(*baseapp.BaseApp) {
    baseapp.SetChainID(tCfg.ChainID)
}
    if tCfg.FauxMerkle {
    opts = append(opts, FauxMerkleModeOpt)
}
    app := appFactory(logger, db, nil, true, appOptions, opts...)
    if !cli.FlagSigverifyTxValue {
    app.SetNotSigverifyTx()
}

return TestInstance[T]{
    App:           app,
    DB:            db,
    WorkDir:       workDir,
    Cfg:           tCfg,
    AppLogger:     logger,
    ExecLogWriter: &simulation.StandardLogWriter{
    Seed: tCfg.Seed
},
}
}

var _ io.Writer = writerFn(nil)

type writerFn func(p []byte) (n int, err error)

func (w writerFn)

Write(p []byte) (n int, err error) {
    return w(p)
}

// WriteToDebugLog is an adapter to io.Writer interface
func WriteToDebugLog(logger log.Logger)

io.Writer {
    return writerFn(func(p []byte) (n int, err error) {
    logger.Debug(string(p))

return len(p), nil
})
}

// FauxMerkleModeOpt returns a BaseApp option to use a dbStoreAdapter instead of
// an IAVLStore for faster simulation speed.
func FauxMerkleModeOpt(bapp *baseapp.BaseApp) {
    bapp.SetFauxMerkleMode()
}
```

These methods allow constructing randomized messages and/or proposal messages.

<Tip>
  Note that modules should **not** implement both `HasWeightedOperationsX` and `HasWeightedOperationsXWithProposals`.
  See the runner code [here](https://github.com/cosmos/cosmos-sdk/blob/main/testutil/simsx/runner.go#L330-L339) for details

  If the module does **not** have message handlers or governance proposal handlers, these interface methods do **not** need to be implemented.
</Tip>

### Example Implementations

* `HasWeightedOperationsXWithProposals`: [x/gov](https://github.com/cosmos/cosmos-sdk/blob/main/x/gov/module.go#L242-L261)
* `HasWeightedOperationsX`: [x/bank](https://github.com/cosmos/cosmos-sdk/blob/main/x/bank/module.go#L199-L203)
* `HasProposalMsgsX`: [x/bank](https://github.com/cosmos/cosmos-sdk/blob/main/x/bank/module.go#L194-L197)

## Store decoders

Registering the store decoders is required for the `AppImportExport` simulation. This allows
for the key-value pairs from the stores to be decoded to their corresponding types.
In particular, it matches the key to a concrete type and then unmarshalls the value from the `KVPair` to the type provided.

Modules using [collections](https://github.com/cosmos/cosmos-sdk/blob/main/collections/README.md) can use the `NewStoreDecoderFuncFromCollectionsSchema` function that builds the decoder for you:

```go expandable theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
package bank

import (
    
	"context"
    "encoding/json"
    "fmt"
    "maps"
    "slices"
    "sort"

	gwruntime "github.com/grpc-ecosystem/grpc-gateway/runtime"
    "github.com/spf13/cobra"

	modulev1 "cosmossdk.io/api/cosmos/bank/module/v1"
    "cosmossdk.io/core/address"
    "cosmossdk.io/core/appmodule"
	corestore "cosmossdk.io/core/store"
    "cosmossdk.io/depinject"
    "cosmossdk.io/log"
    "github.com/cosmos/cosmos-sdk/client"
    "github.com/cosmos/cosmos-sdk/codec"
	codectypes "github.com/cosmos/cosmos-sdk/codec/types"
    "github.com/cosmos/cosmos-sdk/testutil/simsx"
	sdk "github.com/cosmos/cosmos-sdk/types"
    "github.com/cosmos/cosmos-sdk/types/module"
	simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
	authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
    "github.com/cosmos/cosmos-sdk/x/bank/client/cli"
    "github.com/cosmos/cosmos-sdk/x/bank/exported"
    "github.com/cosmos/cosmos-sdk/x/bank/keeper"
	v1bank "github.com/cosmos/cosmos-sdk/x/bank/migrations/v1"
    "github.com/cosmos/cosmos-sdk/x/bank/simulation"
    "github.com/cosmos/cosmos-sdk/x/bank/types"
	govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
)

// ConsensusVersion defines the current x/bank module consensus version.
const ConsensusVersion = 4

var (
	_ module.AppModuleBasic      = AppModule{
}
	_ module.AppModuleSimulation = AppModule{
}
	_ module.HasGenesis          = AppModule{
}
	_ module.HasServices         = AppModule{
}

	_ appmodule.AppModule = AppModule{
}
)

// AppModuleBasic defines the basic application module used by the bank module.
type AppModuleBasic struct {
    cdc codec.Codec
	ac  address.Codec
}

// Name returns the bank module's name.
func (AppModuleBasic)

Name()

string {
    return types.ModuleName
}

// RegisterLegacyAminoCodec registers the bank module's types on the LegacyAmino codec.
func (AppModuleBasic)

RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) {
    types.RegisterLegacyAminoCodec(cdc)
}

// DefaultGenesis returns default genesis state as raw bytes for the bank
// module.
func (AppModuleBasic)

DefaultGenesis(cdc codec.JSONCodec)

json.RawMessage {
    return cdc.MustMarshalJSON(types.DefaultGenesisState())
}

// ValidateGenesis performs genesis state validation for the bank module.
func (AppModuleBasic)

ValidateGenesis(cdc codec.JSONCodec, _ client.TxEncodingConfig, bz json.RawMessage)

error {
    var data types.GenesisState
    if err := cdc.UnmarshalJSON(bz, &data); err != nil {
    return fmt.Errorf("failed to unmarshal %s genesis state: %w", types.ModuleName, err)
}

return data.Validate()
}

// RegisterGRPCGatewayRoutes registers the gRPC Gateway routes for the bank module.
func (AppModuleBasic)

RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *gwruntime.ServeMux) {
    if err := types.RegisterQueryHandlerClient(context.Background(), mux, types.NewQueryClient(clientCtx)); err != nil {
    panic(err)
}
}

// GetTxCmd returns the root tx command for the bank module.
func (ab AppModuleBasic)

GetTxCmd() *cobra.Command {
    return cli.NewTxCmd(ab.ac)
}

// RegisterInterfaces registers interfaces and implementations of the bank module.
func (AppModuleBasic)

RegisterInterfaces(registry codectypes.InterfaceRegistry) {
    types.RegisterInterfaces(registry)

	// Register legacy interfaces for migration scripts.
	v1bank.RegisterInterfaces(registry)
}

// AppModule implements an application module for the bank module.
type AppModule struct {
    AppModuleBasic

	keeper        keeper.Keeper
	accountKeeper types.AccountKeeper

	// legacySubspace is used solely for migration of x/params managed parameters
	legacySubspace exported.Subspace
}

// IsOnePerModuleType implements the depinject.OnePerModuleType interface.
func (am AppModule)

IsOnePerModuleType() {
}

// IsAppModule implements the appmodule.AppModule interface.
func (am AppModule)

IsAppModule() {
}

// RegisterServices registers module services.
func (am AppModule)

RegisterServices(cfg module.Configurator) {
    types.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(am.keeper))

types.RegisterQueryServer(cfg.QueryServer(), am.keeper)
    m := keeper.NewMigrator(am.keeper.(keeper.BaseKeeper), am.legacySubspace)
    if err := cfg.RegisterMigration(types.ModuleName, 1, m.Migrate1to2); err != nil {
    panic(fmt.Sprintf("failed to migrate x/bank from version 1 to 2: %v", err))
}
    if err := cfg.RegisterMigration(types.ModuleName, 2, m.Migrate2to3); err != nil {
    panic(fmt.Sprintf("failed to migrate x/bank from version 2 to 3: %v", err))
}
    if err := cfg.RegisterMigration(types.ModuleName, 3, m.Migrate3to4); err != nil {
    panic(fmt.Sprintf("failed to migrate x/bank from version 3 to 4: %v", err))
}
}

// NewAppModule creates a new AppModule object
func NewAppModule(cdc codec.Codec, keeper keeper.Keeper, accountKeeper types.AccountKeeper, ss exported.Subspace)

AppModule {
    return AppModule{
    AppModuleBasic: AppModuleBasic{
    cdc: cdc, ac: accountKeeper.AddressCodec()
},
		keeper:         keeper,
		accountKeeper:  accountKeeper,
		legacySubspace: ss,
}
}

// QuerierRoute returns the bank module's querier route name.
func (AppModule)

QuerierRoute()

string {
    return types.RouterKey
}

// InitGenesis performs genesis initialization for the bank module. It returns
// no validator updates.
func (am AppModule)

InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, data json.RawMessage) {
    var genesisState types.GenesisState
	cdc.MustUnmarshalJSON(data, &genesisState)

am.keeper.InitGenesis(ctx, &genesisState)
}

// ExportGenesis returns the exported genesis state as raw bytes for the bank
// module.
func (am AppModule)

ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec)

json.RawMessage {
    gs := am.keeper.ExportGenesis(ctx)

return cdc.MustMarshalJSON(gs)
}

// ConsensusVersion implements AppModule/ConsensusVersion.
func (AppModule)

ConsensusVersion()

uint64 {
    return ConsensusVersion
}

// AppModuleSimulation functions

// GenerateGenesisState creates a randomized GenState of the bank module.
func (AppModule)

GenerateGenesisState(simState *module.SimulationState) {
    simulation.RandomizedGenState(simState)
}

// ProposalMsgs returns msgs used for governance proposals for simulations.
// migrate to ProposalMsgsX. This method is ignored when ProposalMsgsX exists and will be removed in the future.
func (AppModule)

ProposalMsgs(simState module.SimulationState) []simtypes.WeightedProposalMsg {
    return simulation.ProposalMsgs()
}

// RegisterStoreDecoder registers a decoder for supply module's types
func (am AppModule)

RegisterStoreDecoder(sdr simtypes.StoreDecoderRegistry) {
    sdr[types.StoreKey] = simtypes.NewStoreDecoderFuncFromCollectionsSchema(am.keeper.(keeper.BaseKeeper).Schema)
}

// WeightedOperations returns the all the bank module operations with their respective weights.
// migrate to WeightedOperationsX. This method is ignored when WeightedOperationsX exists and will be removed in the future
func (am AppModule)

WeightedOperations(simState module.SimulationState) []simtypes.WeightedOperation {
    return simulation.WeightedOperations(
		simState.AppParams, simState.Cdc, simState.TxConfig, am.accountKeeper, am.keeper,
	)
}

// ProposalMsgsX registers governance proposal messages in the simulation registry.
func (AppModule)

ProposalMsgsX(weights simsx.WeightSource, reg simsx.Registry) {
    reg.Add(weights.Get("msg_update_params", 100), simulation.MsgUpdateParamsFactory())
}

// WeightedOperationsX registers weighted bank module operations for simulation.
func (am AppModule)

WeightedOperationsX(weights simsx.WeightSource, reg simsx.Registry) {
    reg.Add(weights.Get("msg_send", 100), simulation.MsgSendFactory())

reg.Add(weights.Get("msg_multisend", 10), simulation.MsgMultiSendFactory())
}

// App Wiring Setup

func init() {
    appmodule.Register(
		&modulev1.Module{
},
		appmodule.Provide(ProvideModule),
		appmodule.Invoke(InvokeSetSendRestrictions),
	)
}

type ModuleInputs struct {
    depinject.In

	Config       *modulev1.Module
	Cdc          codec.Codec
	StoreService corestore.KVStoreService
	Logger       log.Logger

	AccountKeeper types.AccountKeeper

	// LegacySubspace is used solely for migration of x/params managed parameters
	LegacySubspace exported.Subspace `optional:"true"`
}

type ModuleOutputs struct {
    depinject.Out

	BankKeeper keeper.BaseKeeper
	Module     appmodule.AppModule
}

func ProvideModule(in ModuleInputs)

ModuleOutputs {
	// Configure blocked module accounts.
	//
	// Default behavior for blockedAddresses is to regard any module mentioned in
	// AccountKeeper's module account permissions as blocked.
    blockedAddresses := make(map[string]bool)
    if len(in.Config.BlockedModuleAccountsOverride) > 0 {
    for _, moduleName := range in.Config.BlockedModuleAccountsOverride {
    blockedAddresses[authtypes.NewModuleAddress(moduleName).String()] = true
}
	
}

else {
    for _, permission := range in.AccountKeeper.GetModulePermissions() {
    blockedAddresses[permission.GetAddress().String()] = true
}
	
}

	// default to governance authority if not provided
    authority := authtypes.NewModuleAddress(govtypes.ModuleName)
    if in.Config.Authority != "" {
    authority = authtypes.NewModuleAddressOrBech32Address(in.Config.Authority)
}
    bankKeeper := keeper.NewBaseKeeper(
		in.Cdc,
		in.StoreService,
		in.AccountKeeper,
		blockedAddresses,
		authority.String(),
		in.Logger,
	)
    m := NewAppModule(in.Cdc, bankKeeper, in.AccountKeeper, in.LegacySubspace)

return ModuleOutputs{
    BankKeeper: bankKeeper,
    Module: m
}
}

func InvokeSetSendRestrictions(
	config *modulev1.Module,
	keeper keeper.BaseKeeper,
	restrictions map[string]types.SendRestrictionFn,
)

error {
    if config == nil {
    return nil
}
    modules := slices.Collect(maps.Keys(restrictions))
    order := config.RestrictionsOrder
    if len(order) == 0 {
    order = modules
		sort.Strings(order)
}
    if len(order) != len(modules) {
    return fmt.Errorf("len(restrictions order: %v) != len(restriction modules: %v)", order, modules)
}
    if len(modules) == 0 {
    return nil
}
    for _, module := range order {
    restriction, ok := restrictions[module]
    if !ok {
    return fmt.Errorf("can't find send restriction for module %s", module)
}

keeper.AppendSendRestriction(restriction)
}

return nil
}
```

Modules not using collections must manually build the store decoder.
See the implementation [here](https://github.com/cosmos/cosmos-sdk/blob/main/x/distribution/simulation/decoder.go) from the distribution module for an example.

## Randomized genesis

The simulator tests different scenarios and values for genesis parameters.
App modules must implement a `GenerateGenesisState` method to generate the initial random `GenesisState` from a given seed.

```go expandable theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
package module

import (
    
	"encoding/json"
    "math/rand"
    "sort"
    "time"

	sdkmath "cosmossdk.io/math"
    "github.com/cosmos/cosmos-sdk/client"
    "github.com/cosmos/cosmos-sdk/codec"
    "github.com/cosmos/cosmos-sdk/types/simulation"
)

// AppModuleSimulation defines the standard functions that every module should expose
// for the SDK blockchain simulator
type AppModuleSimulation interface {
	// randomized genesis states
	GenerateGenesisState(input *SimulationState)

	// register a func to decode the each module's defined types from their corresponding store key
	RegisterStoreDecoder(simulation.StoreDecoderRegistry)

	// simulation operations (i.e msgs)

with their respective weight
	WeightedOperations(simState SimulationState) []simulation.WeightedOperation
}

// HasProposalMsgs defines the messages that can be used to simulate governance (v1)

proposals
type HasProposalMsgs interface {
	// msg functions used to simulate governance proposals
	ProposalMsgs(simState SimulationState) []simulation.WeightedProposalMsg
}

// HasProposalContents defines the contents that can be used to simulate legacy governance (v1beta1)

proposals
type HasProposalContents interface {
	// content functions used to simulate governance proposals
	ProposalContents(simState SimulationState) []simulation.WeightedProposalContent //nolint:staticcheck // legacy v1beta1 governance
}

// SimulationManager defines a simulation manager that provides the high level utility
// for managing and executing simulation functionalities for a group of modules
type SimulationManager struct {
    Modules       []AppModuleSimulation           // array of app modules; we use an array for deterministic simulation tests
	StoreDecoders simulation.StoreDecoderRegistry // functions to decode the key-value pairs from each module's store
}

// NewSimulationManager creates a new SimulationManager object
//
// CONTRACT: All the modules provided must be also registered on the module Manager
func NewSimulationManager(modules ...AppModuleSimulation) *SimulationManager {
    return &SimulationManager{
    Modules:       modules,
    StoreDecoders: make(simulation.StoreDecoderRegistry),
}
}

// NewSimulationManagerFromAppModules creates a new SimulationManager object.
//
// First it sets any SimulationModule provided by overrideModules, and ignores any AppModule
// with the same moduleName.
// Then it attempts to cast every provided AppModule into an AppModuleSimulation.
// If the cast succeeds, its included, otherwise it is excluded.
func NewSimulationManagerFromAppModules(modules map[string]any, overrideModules map[string]AppModuleSimulation) *SimulationManager {
    simModules := []AppModuleSimulation{
}
    appModuleNamesSorted := make([]string, 0, len(modules))
    for moduleName := range modules {
    appModuleNamesSorted = append(appModuleNamesSorted, moduleName)
}

sort.Strings(appModuleNamesSorted)
    for _, moduleName := range appModuleNamesSorted {
		// for every module, see if we override it. If so, use override.
		// Else, if we can cast the app module into a simulation module add it.
		// otherwise no simulation module.
    if simModule, ok := overrideModules[moduleName]; ok {
    simModules = append(simModules, simModule)
}

else {
    appModule := modules[moduleName]
    if simModule, ok := appModule.(AppModuleSimulation); ok {
    simModules = append(simModules, simModule)
}
			// cannot cast, so we continue
}
	
}

return NewSimulationManager(simModules...)
}

// Deprecated: Use GetProposalMsgs instead.
// GetProposalContents returns each module's proposal content generator function
// with their default operation weight and key.
func (sm *SimulationManager)

GetProposalContents(simState SimulationState) []simulation.WeightedProposalContent {
    wContents := make([]simulation.WeightedProposalContent, 0, len(sm.Modules))
    for _, module := range sm.Modules {
    if module, ok := module.(HasProposalContents); ok {
    wContents = append(wContents, module.ProposalContents(simState)...)
}
	
}

return wContents
}

// GetProposalMsgs returns each module's proposal msg generator function
// with their default operation weight and key.
func (sm *SimulationManager)

GetProposalMsgs(simState SimulationState) []simulation.WeightedProposalMsg {
    wContents := make([]simulation.WeightedProposalMsg, 0, len(sm.Modules))
    for _, module := range sm.Modules {
    if module, ok := module.(HasProposalMsgs); ok {
    wContents = append(wContents, module.ProposalMsgs(simState)...)
}
	
}

return wContents
}

// RegisterStoreDecoders registers each of the modules' store decoders into a map
func (sm *SimulationManager)

RegisterStoreDecoders() {
    for _, module := range sm.Modules {
    module.RegisterStoreDecoder(sm.StoreDecoders)
}
}

// GenerateGenesisStates generates a randomized GenesisState for each of the
// registered modules
func (sm *SimulationManager)

GenerateGenesisStates(simState *SimulationState) {
    for _, module := range sm.Modules {
    module.GenerateGenesisState(simState)
}
}

// WeightedOperations returns all the modules' weighted operations of an application
func (sm *SimulationManager)

WeightedOperations(simState SimulationState) []simulation.WeightedOperation {
    wOps := make([]simulation.WeightedOperation, 0, len(sm.Modules))
    for _, module := range sm.Modules {
    wOps = append(wOps, module.WeightedOperations(simState)...)
}

return wOps
}

// SimulationState is the input parameters used on each of the module's randomized
// GenesisState generator function
type SimulationState struct {
    AppParams         simulation.AppParams
	Cdc               codec.JSONCodec                // application codec
	TxConfig          client.TxConfig                // Shared TxConfig; this is expensive to create and stateless, so create it once up front.
	Rand              *rand.Rand                     // random number
	GenState          map[string]json.RawMessage     // genesis state
	Accounts          []simulation.Account           // simulation accounts
	InitialStake      sdkmath.Int                    // initial coins per account
	NumBonded         int64                          // number of initially bonded accounts
	BondDenom         string                         // denom to be used as default
	GenTimestamp      time.Time                      // genesis timestamp
	UnbondTime        time.Duration                  // staking unbond time stored to use it as the slashing maximum evidence duration
	LegacyParamChange []simulation.LegacyParamChange // simulated parameter changes from modules
	//nolint:staticcheck //	legacy used for testing
	LegacyProposalContents []simulation.WeightedProposalContent // proposal content generator functions with their default weight and app sim key
	ProposalMsgs           []simulation.WeightedProposalMsg     // proposal msg generator functions with their default weight and app sim key
}
```

See an example from `x/auth` [here](https://github.com/cosmos/cosmos-sdk/blob/main/x/auth/module.go#L169-L172).

Once the module's genesis parameters are generated randomly (or with the key and
values defined in a `params` file), they are marshaled to JSON format and added
to the app genesis JSON for the simulation.

## Random weighted operations

Operations are one of the crucial parts of the Cosmos SDK simulation. They are the transactions
(`Msg`) that are simulated with random field values. The sender of the operation
is also assigned randomly.

Operations on the simulation are simulated using the full [transaction cycle](/sdk/v0.53/learn/advanced/transactions) of a
`ABCI` application that exposes the `BaseApp`.

### Using Simsx

Simsx introduces the ability to define a `MsgFactory` for each of a module's messages.

These factories are registered in `WeightedOperationsX` and/or `ProposalMsgsX`.

```go expandable theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
package distribution

import (
    
	"context"
    "encoding/json"
    "fmt"

	gwruntime "github.com/grpc-ecosystem/grpc-gateway/runtime"
    "github.com/spf13/cobra"

	modulev1 "cosmossdk.io/api/cosmos/distribution/module/v1"
    "cosmossdk.io/core/address"
    "cosmossdk.io/core/appmodule"
    "cosmossdk.io/core/store"
    "cosmossdk.io/depinject"

	sdkclient "github.com/cosmos/cosmos-sdk/client"
    "github.com/cosmos/cosmos-sdk/codec"
	cdctypes "github.com/cosmos/cosmos-sdk/codec/types"
    "github.com/cosmos/cosmos-sdk/testutil/simsx"
	sdk "github.com/cosmos/cosmos-sdk/types"
    "github.com/cosmos/cosmos-sdk/types/module"
	simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
	authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
    "github.com/cosmos/cosmos-sdk/x/distribution/client/cli"
    "github.com/cosmos/cosmos-sdk/x/distribution/exported"
    "github.com/cosmos/cosmos-sdk/x/distribution/keeper"
    "github.com/cosmos/cosmos-sdk/x/distribution/simulation"
    "github.com/cosmos/cosmos-sdk/x/distribution/types"
	govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
	staking "github.com/cosmos/cosmos-sdk/x/staking/types"
)

// ConsensusVersion defines the current x/distribution module consensus version.
const ConsensusVersion = 3

var (
	_ module.AppModuleBasic      = AppModule{
}
	_ module.AppModuleSimulation = AppModule{
}
	_ module.HasGenesis          = AppModule{
}
	_ module.HasServices         = AppModule{
}

	_ appmodule.AppModule       = AppModule{
}
	_ appmodule.HasBeginBlocker = AppModule{
}
)

// AppModuleBasic defines the basic application module used by the distribution module.
type AppModuleBasic struct {
    cdc codec.Codec
	ac  address.Codec
}

// Name returns the distribution module's name.
func (AppModuleBasic)

Name()

string {
    return types.ModuleName
}

// RegisterLegacyAminoCodec registers the distribution module's types for the given codec.
func (AppModuleBasic)

RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) {
    types.RegisterLegacyAminoCodec(cdc)
}

// DefaultGenesis returns default genesis state as raw bytes for the distribution
// module.
func (AppModuleBasic)

DefaultGenesis(cdc codec.JSONCodec)

json.RawMessage {
    return cdc.MustMarshalJSON(types.DefaultGenesisState())
}

// ValidateGenesis performs genesis state validation for the distribution module.
func (AppModuleBasic)

ValidateGenesis(cdc codec.JSONCodec, _ sdkclient.TxEncodingConfig, bz json.RawMessage)

error {
    var data types.GenesisState
    if err := cdc.UnmarshalJSON(bz, &data); err != nil {
    return fmt.Errorf("failed to unmarshal %s genesis state: %w", types.ModuleName, err)
}

return types.ValidateGenesis(&data)
}

// RegisterGRPCGatewayRoutes registers the gRPC Gateway routes for the distribution module.
func (AppModuleBasic)

RegisterGRPCGatewayRoutes(clientCtx sdkclient.Context, mux *gwruntime.ServeMux) {
    if err := types.RegisterQueryHandlerClient(context.Background(), mux, types.NewQueryClient(clientCtx)); err != nil {
    panic(err)
}
}

// GetTxCmd returns the root tx command for the distribution module.
func (ab AppModuleBasic)

GetTxCmd() *cobra.Command {
    return cli.NewTxCmd(ab.cdc.InterfaceRegistry().SigningContext().ValidatorAddressCodec(), ab.cdc.InterfaceRegistry().SigningContext().AddressCodec())
}

// RegisterInterfaces implements InterfaceModule
func (AppModuleBasic)

RegisterInterfaces(registry cdctypes.InterfaceRegistry) {
    types.RegisterInterfaces(registry)
}

// AppModule implements an application module for the distribution module.
type AppModule struct {
    AppModuleBasic

	keeper        keeper.Keeper
	accountKeeper types.AccountKeeper
	bankKeeper    types.BankKeeper
	stakingKeeper types.StakingKeeper

	// legacySubspace is used solely for migration of x/params managed parameters
	legacySubspace exported.Subspace
}

// NewAppModule creates a new AppModule object
func NewAppModule(
	cdc codec.Codec, keeper keeper.Keeper, accountKeeper types.AccountKeeper,
	bankKeeper types.BankKeeper, stakingKeeper types.StakingKeeper, ss exported.Subspace,
)

AppModule {
    return AppModule{
    AppModuleBasic: AppModuleBasic{
    cdc: cdc, ac: accountKeeper.AddressCodec()
},
		keeper:         keeper,
		accountKeeper:  accountKeeper,
		bankKeeper:     bankKeeper,
		stakingKeeper:  stakingKeeper,
		legacySubspace: ss,
}
}

// IsOnePerModuleType implements the depinject.OnePerModuleType interface.
func (am AppModule)

IsOnePerModuleType() {
}

// IsAppModule implements the appmodule.AppModule interface.
func (am AppModule)

IsAppModule() {
}

// RegisterServices registers module services.
func (am AppModule)

RegisterServices(cfg module.Configurator) {
    types.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(am.keeper))

types.RegisterQueryServer(cfg.QueryServer(), keeper.NewQuerier(am.keeper))
    m := keeper.NewMigrator(am.keeper, am.legacySubspace)
    if err := cfg.RegisterMigration(types.ModuleName, 1, m.Migrate1to2); err != nil {
    panic(fmt.Sprintf("failed to migrate x/%s from version 1 to 2: %v", types.ModuleName, err))
}
    if err := cfg.RegisterMigration(types.ModuleName, 2, m.Migrate2to3); err != nil {
    panic(fmt.Sprintf("failed to migrate x/%s from version 2 to 3: %v", types.ModuleName, err))
}
}

// InitGenesis performs genesis initialization for the distribution module. It returns
// no validator updates.
func (am AppModule)

InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, data json.RawMessage) {
    var genesisState types.GenesisState
	cdc.MustUnmarshalJSON(data, &genesisState)

am.keeper.InitGenesis(ctx, genesisState)
}

// ExportGenesis returns the exported genesis state as raw bytes for the distribution
// module.
func (am AppModule)

ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec)

json.RawMessage {
    gs := am.keeper.ExportGenesis(ctx)

return cdc.MustMarshalJSON(gs)
}

// ConsensusVersion implements AppModule/ConsensusVersion.
func (AppModule)

ConsensusVersion()

uint64 {
    return ConsensusVersion
}

// BeginBlock returns the begin blocker for the distribution module.
func (am AppModule)

BeginBlock(ctx context.Context)

error {
    c := sdk.UnwrapSDKContext(ctx)

return BeginBlocker(c, am.keeper)
}

// AppModuleSimulation functions

// GenerateGenesisState creates a randomized GenState of the distribution module.
func (AppModule)

GenerateGenesisState(simState *module.SimulationState) {
    simulation.RandomizedGenState(simState)
}

// ProposalMsgs returns msgs used for governance proposals for simulations.
// migrate to ProposalMsgsX. This method is ignored when ProposalMsgsX exists and will be removed in the future.
func (AppModule)

ProposalMsgs(_ module.SimulationState) []simtypes.WeightedProposalMsg {
    return simulation.ProposalMsgs()
}

// RegisterStoreDecoder registers a decoder for distribution module's types
func (am AppModule)

RegisterStoreDecoder(sdr simtypes.StoreDecoderRegistry) {
    sdr[types.StoreKey] = simulation.NewDecodeStore(am.cdc)
}

// WeightedOperations returns the all the gov module operations with their respective weights.
// migrate to WeightedOperationsX. This method is ignored when WeightedOperationsX exists and will be removed in the future
func (am AppModule)

WeightedOperations(simState module.SimulationState) []simtypes.WeightedOperation {
    return simulation.WeightedOperations(
		simState.AppParams, simState.Cdc, simState.TxConfig,
		am.accountKeeper, am.bankKeeper, am.keeper, am.stakingKeeper,
	)
}

// ProposalMsgsX registers governance proposal messages in the simulation registry.
func (AppModule)

ProposalMsgsX(weights simsx.WeightSource, reg simsx.Registry) {
    reg.Add(weights.Get("msg_update_params", 100), simulation.MsgUpdateParamsFactory())
}

// WeightedOperationsX registers weighted distribution module operations for simulation.
func (am AppModule)

WeightedOperationsX(weights simsx.WeightSource, reg simsx.Registry) {
    reg.Add(weights.Get("msg_set_withdraw_address", 50), simulation.MsgSetWithdrawAddressFactory(am.keeper))

reg.Add(weights.Get("msg_withdraw_delegation_reward", 50), simulation.MsgWithdrawDelegatorRewardFactory(am.keeper, am.stakingKeeper))

reg.Add(weights.Get("msg_withdraw_validator_commission", 50), simulation.MsgWithdrawValidatorCommissionFactory(am.keeper, am.stakingKeeper))
}

//
// App Wiring Setup
//

func init() {
    appmodule.Register(&modulev1.Module{
},
		appmodule.Provide(ProvideModule),
	)
}

type ModuleInputs struct {
    depinject.In

	Config       *modulev1.Module
	StoreService store.KVStoreService
	Cdc          codec.Codec

	AccountKeeper      types.AccountKeeper
	BankKeeper         types.BankKeeper
	StakingKeeper      types.StakingKeeper
	ExternalPoolKeeper types.ExternalCommunityPoolKeeper `optional:"true"`

	// LegacySubspace is used solely for migration of x/params managed parameters
	LegacySubspace exported.Subspace `optional:"true"`
}

type ModuleOutputs struct {
    depinject.Out

	DistrKeeper keeper.Keeper
	Module      appmodule.AppModule
	Hooks       staking.StakingHooksWrapper
}

func ProvideModule(in ModuleInputs)

ModuleOutputs {
    feeCollectorName := in.Config.FeeCollectorName
    if feeCollectorName == "" {
    feeCollectorName = authtypes.FeeCollectorName
}

	// default to governance authority if not provided
    authority := authtypes.NewModuleAddress(govtypes.ModuleName)
    if in.Config.Authority != "" {
    authority = authtypes.NewModuleAddressOrBech32Address(in.Config.Authority)
}

var opts []keeper.InitOption
    if in.ExternalPoolKeeper != nil {
    opts = append(opts, keeper.WithExternalCommunityPool(in.ExternalPoolKeeper))
}
    k := keeper.NewKeeper(
		in.Cdc,
		in.StoreService,
		in.AccountKeeper,
		in.BankKeeper,
		in.StakingKeeper,
		feeCollectorName,
		authority.String(),
		opts...,
	)
    m := NewAppModule(in.Cdc, k, in.AccountKeeper, in.BankKeeper, in.StakingKeeper, in.LegacySubspace)

return ModuleOutputs{
    DistrKeeper: k,
    Module:      m,
    Hooks:       staking.StakingHooksWrapper{
    StakingHooks: k.Hooks()
},
}
}
```

Note that the name passed in to `weights.Get` must match the name of the operation set in the `WeightedOperations`.

For example, if the module contains an operation `op_weight_msg_set_withdraw_address`, the name passed to `weights.Get` should be `msg_set_withdraw_address`.

See the `x/distribution` for an example of implementing message factories [here](https://github.com/cosmos/cosmos-sdk/blob/main/x/distribution/simulation/msg_factory.go)

## App Simulator manager

The following step is setting up the `SimulatorManager` at the app level. This
is required for the simulation test files in the next step.

```go theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
type CoolApp struct {
...
sm *module.SimulationManager
}
```

Within the constructor of the application, construct the simulation manager using the modules from `ModuleManager` and call the `RegisterStoreDecoders` method.

```go expandable theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
//go:build app_v1

package simapp

import (
    
	"encoding/json"
    "fmt"
    "io"
    "maps"

	abci "github.com/cometbft/cometbft/abci/types"
	dbm "github.com/cosmos/cosmos-db"
    "github.com/cosmos/gogoproto/proto"
    "github.com/spf13/cast"

	autocliv1 "cosmossdk.io/api/cosmos/autocli/v1"
	reflectionv1 "cosmossdk.io/api/cosmos/reflection/v1"
    "cosmossdk.io/client/v2/autocli"
	clienthelpers "cosmossdk.io/client/v2/helpers"
    "cosmossdk.io/core/appmodule"
    "cosmossdk.io/log"
	storetypes "cosmossdk.io/store/types"
    "cosmossdk.io/x/tx/signing"
    "github.com/cosmos/cosmos-sdk/baseapp"
    "github.com/cosmos/cosmos-sdk/client"
    "github.com/cosmos/cosmos-sdk/client/flags"
    "github.com/cosmos/cosmos-sdk/client/grpc/cmtservice"
	nodeservice "github.com/cosmos/cosmos-sdk/client/grpc/node"
    "github.com/cosmos/cosmos-sdk/codec"
    "github.com/cosmos/cosmos-sdk/codec/address"
    "github.com/cosmos/cosmos-sdk/codec/types"
    "github.com/cosmos/cosmos-sdk/runtime"
	runtimeservices "github.com/cosmos/cosmos-sdk/runtime/services"
    "github.com/cosmos/cosmos-sdk/server"
    "github.com/cosmos/cosmos-sdk/server/api"
    "github.com/cosmos/cosmos-sdk/server/config"
	servertypes "github.com/cosmos/cosmos-sdk/server/types"
    "github.com/cosmos/cosmos-sdk/std"
	testdata_pulsar "github.com/cosmos/cosmos-sdk/testutil/testdata/testpb"
	sdk "github.com/cosmos/cosmos-sdk/types"
    "github.com/cosmos/cosmos-sdk/types/module"
	sigtypes "github.com/cosmos/cosmos-sdk/types/tx/signing"
    "github.com/cosmos/cosmos-sdk/version"
    "github.com/cosmos/cosmos-sdk/x/auth"
    "github.com/cosmos/cosmos-sdk/x/auth/ante"
	authcodec "github.com/cosmos/cosmos-sdk/x/auth/codec"
	authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
    "github.com/cosmos/cosmos-sdk/x/auth/posthandler"
	authsims "github.com/cosmos/cosmos-sdk/x/auth/simulation"
    "github.com/cosmos/cosmos-sdk/x/auth/tx"
	authtx "github.com/cosmos/cosmos-sdk/x/auth/tx"
	txmodule "github.com/cosmos/cosmos-sdk/x/auth/tx/config"
	authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
    "github.com/cosmos/cosmos-sdk/x/auth/vesting"
	vestingtypes "github.com/cosmos/cosmos-sdk/x/auth/vesting/types"
    "github.com/cosmos/cosmos-sdk/x/authz"
	authzkeeper "github.com/cosmos/cosmos-sdk/x/authz/keeper"
	authzmodule "github.com/cosmos/cosmos-sdk/x/authz/module"
    "github.com/cosmos/cosmos-sdk/x/bank"
	bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper"
	banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
	consensus "github.com/cosmos/cosmos-sdk/x/consensus"
	consensusparamkeeper "github.com/cosmos/cosmos-sdk/x/consensus/keeper"
	consensusparamtypes "github.com/cosmos/cosmos-sdk/x/consensus/types"
	distr "github.com/cosmos/cosmos-sdk/x/distribution"
	distrkeeper "github.com/cosmos/cosmos-sdk/x/distribution/keeper"
	distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types"
    "github.com/cosmos/cosmos-sdk/x/epochs"
	epochskeeper "github.com/cosmos/cosmos-sdk/x/epochs/keeper"
	epochstypes "github.com/cosmos/cosmos-sdk/x/epochs/types"
    "github.com/cosmos/cosmos-sdk/x/evidence"
	evidencekeeper "github.com/cosmos/cosmos-sdk/x/evidence/keeper"
	evidencetypes "github.com/cosmos/cosmos-sdk/x/evidence/types"
    "github.com/cosmos/cosmos-sdk/x/feegrant"
	feegrantkeeper "github.com/cosmos/cosmos-sdk/x/feegrant/keeper"
	feegrantmodule "github.com/cosmos/cosmos-sdk/x/feegrant/module"
    "github.com/cosmos/cosmos-sdk/x/genutil"
	genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types"
    "github.com/cosmos/cosmos-sdk/x/gov"
	govclient "github.com/cosmos/cosmos-sdk/x/gov/client"
	govkeeper "github.com/cosmos/cosmos-sdk/x/gov/keeper"
	govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
	govv1beta1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1"
    "github.com/cosmos/cosmos-sdk/x/mint"
	mintkeeper "github.com/cosmos/cosmos-sdk/x/mint/keeper"
	minttypes "github.com/cosmos/cosmos-sdk/x/mint/types"
    "github.com/cosmos/cosmos-sdk/x/protocolpool"
	protocolpoolkeeper "github.com/cosmos/cosmos-sdk/x/protocolpool/keeper"
	protocolpooltypes "github.com/cosmos/cosmos-sdk/x/protocolpool/types"
    "github.com/cosmos/cosmos-sdk/x/slashing"
	slashingkeeper "github.com/cosmos/cosmos-sdk/x/slashing/keeper"
	slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types"
    "github.com/cosmos/cosmos-sdk/x/staking"
	stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper"
	stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
    "github.com/cosmos/cosmos-sdk/x/upgrade"
	upgradekeeper "github.com/cosmos/cosmos-sdk/x/upgrade/keeper"
	upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types"
)

const appName = "SimApp"

var (
	// DefaultNodeHome default home directories for the application daemon
	DefaultNodeHome string

	// module account permissions
	maccPerms = map[string][]string{
    authtypes.FeeCollectorName:                  nil,
		distrtypes.ModuleName:                       nil,
		minttypes.ModuleName:                        {
    authtypes.Minter
},
		stakingtypes.BondedPoolName:                 {
    authtypes.Burner, authtypes.Staking
},
		stakingtypes.NotBondedPoolName:              {
    authtypes.Burner, authtypes.Staking
},
		govtypes.ModuleName:                         {
    authtypes.Burner
},
		protocolpooltypes.ModuleName:                nil,
		protocolpooltypes.ProtocolPoolEscrowAccount: nil
}
)

var (
	_ runtime.AppI            = (*SimApp)(nil)
	_ servertypes.Application = (*SimApp)(nil)
)

// SimApp extends an ABCI application, but with most of its parameters exported.
// They are exported for convenience in creating helper functions, as object
// capabilities aren't needed for testing.
type SimApp struct {
	*baseapp.BaseApp
	legacyAmino       *codec.LegacyAmino
	appCodec          codec.Codec
	txConfig          client.TxConfig
	interfaceRegistry types.InterfaceRegistry

	// keys to access the substores
	keys map[string]*storetypes.KVStoreKey

	// essential keepers
	AccountKeeper         authkeeper.AccountKeeper
	BankKeeper            bankkeeper.BaseKeeper
	StakingKeeper         *stakingkeeper.Keeper
	SlashingKeeper        slashingkeeper.Keeper
	MintKeeper            mintkeeper.Keeper
	DistrKeeper           distrkeeper.Keeper
	GovKeeper             govkeeper.Keeper
	UpgradeKeeper         *upgradekeeper.Keeper
	EvidenceKeeper        evidencekeeper.Keeper
	ConsensusParamsKeeper consensusparamkeeper.Keeper

	// supplementary keepers
	FeeGrantKeeper     feegrantkeeper.Keeper
	AuthzKeeper        authzkeeper.Keeper
	EpochsKeeper       epochskeeper.Keeper
	ProtocolPoolKeeper protocolpoolkeeper.Keeper

	// the module manager
	ModuleManager      *module.Manager
	BasicModuleManager module.BasicManager

	// simulation manager
	sm *module.SimulationManager

	// module configurator
	configurator module.Configurator
}

func init() {
    var err error
	DefaultNodeHome, err = clienthelpers.GetNodeHomeDirectory(".simapp")
    if err != nil {
    panic(err)
}
}

// NewSimApp returns a reference to an initialized SimApp.
func NewSimApp(
	logger log.Logger,
	db dbm.DB,
	traceStore io.Writer,
	loadLatest bool,
	appOpts servertypes.AppOptions,
	baseAppOptions ...func(*baseapp.BaseApp),
) *SimApp {
    interfaceRegistry, _ := types.NewInterfaceRegistryWithOptions(types.InterfaceRegistryOptions{
    ProtoFiles: proto.HybridResolver,
    SigningOptions: signing.Options{
    AddressCodec: address.Bech32Codec{
    Bech32Prefix: sdk.GetConfig().GetBech32AccountAddrPrefix(),
},
    ValidatorAddressCodec: address.Bech32Codec{
    Bech32Prefix: sdk.GetConfig().GetBech32ValidatorAddrPrefix(),
},
},
})
    appCodec := codec.NewProtoCodec(interfaceRegistry)
    legacyAmino := codec.NewLegacyAmino()
    txConfig := tx.NewTxConfig(appCodec, tx.DefaultSignModes)
    if err := interfaceRegistry.SigningContext().Validate(); err != nil {
    panic(err)
}

std.RegisterLegacyAminoCodec(legacyAmino)

std.RegisterInterfaces(interfaceRegistry)

	// Below we could construct and set an application specific mempool and
	// ABCI 1.0 PrepareProposal and ProcessProposal handlers. These defaults are
	// already set in the SDK's BaseApp, this shows an example of how to override
	// them.
	//
	// Example:
	//
	// bApp := baseapp.NewBaseApp(...)
	// nonceMempool := mempool.NewSenderNonceMempool()
	// abciPropHandler := NewDefaultProposalHandler(nonceMempool, bApp)
	//
	// bApp.SetMempool(nonceMempool)
	// bApp.SetPrepareProposal(abciPropHandler.PrepareProposalHandler())
	// bApp.SetProcessProposal(abciPropHandler.ProcessProposalHandler())
	//
	// Alternatively, you can construct BaseApp options, append those to
	// baseAppOptions and pass them to NewBaseApp.
	//
	// Example:
	//
	// prepareOpt = func(app *baseapp.BaseApp) {
	// 	abciPropHandler := baseapp.NewDefaultProposalHandler(nonceMempool, app)
	// 	app.SetPrepareProposal(abciPropHandler.PrepareProposalHandler())
	//
}
	// baseAppOptions = append(baseAppOptions, prepareOpt)

	// create and set dummy vote extension handler
    voteExtOp := func(bApp *baseapp.BaseApp) {
    voteExtHandler := NewVoteExtensionHandler()

voteExtHandler.SetHandlers(bApp)
}

baseAppOptions = append(baseAppOptions, voteExtOp, baseapp.SetOptimisticExecution())
    bApp := baseapp.NewBaseApp(appName, logger, db, txConfig.TxDecoder(), baseAppOptions...)

bApp.SetCommitMultiStoreTracer(traceStore)

bApp.SetVersion(version.Version)

bApp.SetInterfaceRegistry(interfaceRegistry)

bApp.SetTxEncoder(txConfig.TxEncoder())
    keys := storetypes.NewKVStoreKeys(
		authtypes.StoreKey,
		banktypes.StoreKey,
		stakingtypes.StoreKey,
		minttypes.StoreKey,
		distrtypes.StoreKey,
		slashingtypes.StoreKey,
		govtypes.StoreKey,
		consensusparamtypes.StoreKey,
		upgradetypes.StoreKey,
		feegrant.StoreKey,
		evidencetypes.StoreKey,
		authzkeeper.StoreKey,
		epochstypes.StoreKey,
		protocolpooltypes.StoreKey,
	)

	// register streaming services
    if err := bApp.RegisterStreamingServices(appOpts, keys); err != nil {
    panic(err)
}
    app := &SimApp{
    BaseApp:           bApp,
		legacyAmino:       legacyAmino,
		appCodec:          appCodec,
		txConfig:          txConfig,
		interfaceRegistry: interfaceRegistry,
		keys:              keys,
}

	// set the BaseApp's parameter store
	app.ConsensusParamsKeeper = consensusparamkeeper.NewKeeper(
		appCodec,
		runtime.NewKVStoreService(keys[consensusparamtypes.StoreKey]),
		authtypes.NewModuleAddress(govtypes.ModuleName).String(),
		runtime.EventService{
},
	)

bApp.SetParamStore(app.ConsensusParamsKeeper.ParamsStore)

	// add keepers
	app.AccountKeeper = authkeeper.NewAccountKeeper(
		appCodec,
		runtime.NewKVStoreService(keys[authtypes.StoreKey]),
		authtypes.ProtoBaseAccount,
		maccPerms,
		authcodec.NewBech32Codec(sdk.Bech32MainPrefix),
		sdk.Bech32MainPrefix,
		authtypes.NewModuleAddress(govtypes.ModuleName).String(),
		authkeeper.WithUnorderedTransactions(true),
	)

app.BankKeeper = bankkeeper.NewBaseKeeper(
		appCodec,
		runtime.NewKVStoreService(keys[banktypes.StoreKey]),
		app.AccountKeeper,
		BlockedAddresses(),
		authtypes.NewModuleAddress(govtypes.ModuleName).String(),
		logger,
	)

	// optional: enable sign mode textual by overwriting the default tx config (after setting the bank keeper)
    enabledSignModes := append(tx.DefaultSignModes, sigtypes.SignMode_SIGN_MODE_TEXTUAL)
    txConfigOpts := tx.ConfigOptions{
    EnabledSignModes:           enabledSignModes,
    TextualCoinMetadataQueryFn: txmodule.NewBankKeeperCoinMetadataQueryFn(app.BankKeeper),
}

txConfig, err := tx.NewTxConfigWithOptions(
		appCodec,
		txConfigOpts,
	)
    if err != nil {
    panic(err)
}

app.txConfig = txConfig

	app.StakingKeeper = stakingkeeper.NewKeeper(
		appCodec,
		runtime.NewKVStoreService(keys[stakingtypes.StoreKey]),
		app.AccountKeeper,
		app.BankKeeper,
		authtypes.NewModuleAddress(govtypes.ModuleName).String(),
		authcodec.NewBech32Codec(sdk.Bech32PrefixValAddr),
		authcodec.NewBech32Codec(sdk.Bech32PrefixConsAddr),
	)

app.MintKeeper = mintkeeper.NewKeeper(
		appCodec,
		runtime.NewKVStoreService(keys[minttypes.StoreKey]),
		app.StakingKeeper,
		app.AccountKeeper,
		app.BankKeeper,
		authtypes.FeeCollectorName,
		authtypes.NewModuleAddress(govtypes.ModuleName).String(),
		// mintkeeper.WithMintFn(mintkeeper.DefaultMintFn(minttypes.DefaultInflationCalculationFn)), custom mintFn can be added here
	)

app.ProtocolPoolKeeper = protocolpoolkeeper.NewKeeper(
		appCodec,
		runtime.NewKVStoreService(keys[protocolpooltypes.StoreKey]),
		app.AccountKeeper,
		app.BankKeeper,
		authtypes.NewModuleAddress(govtypes.ModuleName).String(),
	)

app.DistrKeeper = distrkeeper.NewKeeper(
		appCodec,
		runtime.NewKVStoreService(keys[distrtypes.StoreKey]),
		app.AccountKeeper,
		app.BankKeeper,
		app.StakingKeeper,
		authtypes.FeeCollectorName,
		authtypes.NewModuleAddress(govtypes.ModuleName).String(),
		distrkeeper.WithExternalCommunityPool(app.ProtocolPoolKeeper),
	)

app.SlashingKeeper = slashingkeeper.NewKeeper(
		appCodec,
		legacyAmino,
		runtime.NewKVStoreService(keys[slashingtypes.StoreKey]),
		app.StakingKeeper,
		authtypes.NewModuleAddress(govtypes.ModuleName).String(),
	)

app.FeeGrantKeeper = feegrantkeeper.NewKeeper(
		appCodec,
		runtime.NewKVStoreService(keys[feegrant.StoreKey]),
		app.AccountKeeper,
	)

	// register the staking hooks
	// NOTE: stakingKeeper above is passed by reference, so that it will contain these hooks
	app.StakingKeeper.SetHooks(
		stakingtypes.NewMultiStakingHooks(
			app.DistrKeeper.Hooks(),
			app.SlashingKeeper.Hooks(),
		),
	)

app.AuthzKeeper = authzkeeper.NewKeeper(
		runtime.NewKVStoreService(keys[authzkeeper.StoreKey]),
		appCodec,
		app.MsgServiceRouter(),
		app.AccountKeeper,
	)

	// get skipUpgradeHeights from the app options
    skipUpgradeHeights := map[int64]bool{
}
    for _, h := range cast.ToIntSlice(appOpts.Get(server.FlagUnsafeSkipUpgrades)) {
    skipUpgradeHeights[int64(h)] = true
}
    homePath := cast.ToString(appOpts.Get(flags.FlagHome))
	// set the governance module account as the authority for conducting upgrades
	app.UpgradeKeeper = upgradekeeper.NewKeeper(
		skipUpgradeHeights,
		runtime.NewKVStoreService(keys[upgradetypes.StoreKey]),
		appCodec,
		homePath,
		app.BaseApp,
		authtypes.NewModuleAddress(govtypes.ModuleName).String(),
	)

	// Register the proposal types
	// Deprecated: Avoid adding new handlers, instead use the new proposal flow
	// by granting the governance module the right to execute the message.
	// See: /sdk/v0.53/build/modules/gov#proposal-messages
    govRouter := govv1beta1.NewRouter()

govRouter.AddRoute(govtypes.RouterKey, govv1beta1.ProposalHandler)
    govConfig := govtypes.DefaultConfig()
	/*
		Example of setting gov params:
		govConfig.MaxMetadataLen = 10000
	*/
    govKeeper := govkeeper.NewKeeper(
		appCodec,
		runtime.NewKVStoreService(keys[govtypes.StoreKey]),
		app.AccountKeeper,
		app.BankKeeper,
		app.StakingKeeper,
		app.DistrKeeper,
		app.MsgServiceRouter(),
		govConfig,
		authtypes.NewModuleAddress(govtypes.ModuleName).String(),
		// govkeeper.WithCustomCalculateVoteResultsAndVotingPowerFn(...), // Add if you want to use a custom vote calculation function.
	)

	// Set legacy router for backwards compatibility with gov v1beta1
	govKeeper.SetLegacyRouter(govRouter)

app.GovKeeper = *govKeeper.SetHooks(
		govtypes.NewMultiGovHooks(
		// register the governance hooks
		),
	)

	// create evidence keeper with router
    evidenceKeeper := evidencekeeper.NewKeeper(
		appCodec,
		runtime.NewKVStoreService(keys[evidencetypes.StoreKey]),
		app.StakingKeeper,
		app.SlashingKeeper,
		app.AccountKeeper.AddressCodec(),
		runtime.ProvideCometInfoService(),
	)
	// If evidence needs to be handled for the app, set routes in router here and seal
	app.EvidenceKeeper = *evidenceKeeper

	app.EpochsKeeper = epochskeeper.NewKeeper(
		runtime.NewKVStoreService(keys[epochstypes.StoreKey]),
		appCodec,
	)

app.EpochsKeeper.SetHooks(
		epochstypes.NewMultiEpochHooks(
		// insert epoch hooks receivers here
		),
	)

	/****  Module Options ****/

	// NOTE: Any module instantiated in the module manager that is later modified
	// must be passed by reference here.
	app.ModuleManager = module.NewManager(
		genutil.NewAppModule(
			app.AccountKeeper, app.StakingKeeper, app,
			txConfig,
		),
		auth.NewAppModule(appCodec, app.AccountKeeper, authsims.RandomGenesisAccounts, nil),
		vesting.NewAppModule(app.AccountKeeper, app.BankKeeper),
		bank.NewAppModule(appCodec, app.BankKeeper, app.AccountKeeper, nil),
		feegrantmodule.NewAppModule(appCodec, app.AccountKeeper, app.BankKeeper, app.FeeGrantKeeper, app.interfaceRegistry),
		gov.NewAppModule(appCodec, &app.GovKeeper, app.AccountKeeper, app.BankKeeper, nil),
		mint.NewAppModule(appCodec, app.MintKeeper, app.AccountKeeper, nil, nil),
		slashing.NewAppModule(appCodec, app.SlashingKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper, nil, app.interfaceRegistry),
		distr.NewAppModule(appCodec, app.DistrKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper, nil),
		staking.NewAppModule(appCodec, app.StakingKeeper, app.AccountKeeper, app.BankKeeper, nil),
		upgrade.NewAppModule(app.UpgradeKeeper, app.AccountKeeper.AddressCodec()),
		evidence.NewAppModule(app.EvidenceKeeper),
		authzmodule.NewAppModule(appCodec, app.AuthzKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry),
		consensus.NewAppModule(appCodec, app.ConsensusParamsKeeper),
		epochs.NewAppModule(app.EpochsKeeper),
		protocolpool.NewAppModule(app.ProtocolPoolKeeper, app.AccountKeeper, app.BankKeeper),
	)

	// BasicModuleManager defines the module BasicManager is in charge of setting up basic,
	// non-dependent module elements, such as codec registration and genesis verification.
	// By default it is composed of all the module from the module manager.
	// Additionally, app module basics can be overwritten by passing them as argument.
	app.BasicModuleManager = module.NewBasicManagerFromManager(
		app.ModuleManager,
		map[string]module.AppModuleBasic{
    genutiltypes.ModuleName: genutil.NewAppModuleBasic(genutiltypes.DefaultMessageValidator),
			govtypes.ModuleName: gov.NewAppModuleBasic(
				[]govclient.ProposalHandler{
},
			),
})

app.BasicModuleManager.RegisterLegacyAminoCodec(legacyAmino)

app.BasicModuleManager.RegisterInterfaces(interfaceRegistry)

	// NOTE: upgrade module is required to be prioritized
	app.ModuleManager.SetOrderPreBlockers(
		upgradetypes.ModuleName,
		authtypes.ModuleName,
	)
	// During begin block slashing happens after distr.BeginBlocker so that
	// there is nothing left over in the validator fee pool, so as to keep the
	// CanWithdrawInvariant invariant.
	// NOTE: staking module is required if HistoricalEntries param > 0
	app.ModuleManager.SetOrderBeginBlockers(
		minttypes.ModuleName,
		distrtypes.ModuleName,
		protocolpooltypes.ModuleName,
		slashingtypes.ModuleName,
		evidencetypes.ModuleName,
		stakingtypes.ModuleName,
		genutiltypes.ModuleName,
		authz.ModuleName,
		epochstypes.ModuleName,
	)

app.ModuleManager.SetOrderEndBlockers(
		govtypes.ModuleName,
		stakingtypes.ModuleName,
		genutiltypes.ModuleName,
		feegrant.ModuleName,
		protocolpooltypes.ModuleName,
	)

	// NOTE: The genutils module must occur after staking so that pools are
	// properly initialized with tokens from genesis accounts.
	// NOTE: The genutils module must also occur after auth so that it can access the params from auth.
    genesisModuleOrder := []string{
    authtypes.ModuleName,
		banktypes.ModuleName,
		distrtypes.ModuleName,
		stakingtypes.ModuleName,
		slashingtypes.ModuleName,
		govtypes.ModuleName,
		minttypes.ModuleName,
		genutiltypes.ModuleName,
		evidencetypes.ModuleName,
		authz.ModuleName,
		feegrant.ModuleName,
		upgradetypes.ModuleName,
		vestingtypes.ModuleName,
		consensusparamtypes.ModuleName,
		epochstypes.ModuleName,
		protocolpooltypes.ModuleName,
}
    exportModuleOrder := []string{
    consensusparamtypes.ModuleName,
		authtypes.ModuleName,
		protocolpooltypes.ModuleName, // Must be exported before bank
		banktypes.ModuleName,
		distrtypes.ModuleName,
		stakingtypes.ModuleName,
		slashingtypes.ModuleName,
		govtypes.ModuleName,
		minttypes.ModuleName,
		genutiltypes.ModuleName,
		evidencetypes.ModuleName,
		authz.ModuleName,
		feegrant.ModuleName,
		upgradetypes.ModuleName,
		vestingtypes.ModuleName,
		epochstypes.ModuleName,
}

app.ModuleManager.SetOrderInitGenesis(genesisModuleOrder...)

app.ModuleManager.SetOrderExportGenesis(exportModuleOrder...)

	// Uncomment if you want to set a custom migration order here.
	// app.ModuleManager.SetOrderMigrations(custom order)

app.configurator = module.NewConfigurator(app.appCodec, app.MsgServiceRouter(), app.GRPCQueryRouter())

err = app.ModuleManager.RegisterServices(app.configurator)
    if err != nil {
    panic(err)
}

	// RegisterUpgradeHandlers is used for registering any on-chain upgrades.
	// Make sure it's called after `app.ModuleManager` and `app.configurator` are set.
	app.RegisterUpgradeHandlers()

autocliv1.RegisterQueryServer(app.GRPCQueryRouter(), runtimeservices.NewAutoCLIQueryService(app.ModuleManager.Modules))

reflectionSvc, err := runtimeservices.NewReflectionService()
    if err != nil {
    panic(err)
}

reflectionv1.RegisterReflectionServiceServer(app.GRPCQueryRouter(), reflectionSvc)

	// add test gRPC service for testing gRPC queries in isolation
	testdata_pulsar.RegisterQueryServer(app.GRPCQueryRouter(), testdata_pulsar.QueryImpl{
})

	// create the simulation manager and define the order of the modules for deterministic simulations
	//
	// NOTE: this is not required apps that don't use the simulator for fuzz testing
	// transactions
    overrideModules := map[string]module.AppModuleSimulation{
    authtypes.ModuleName: auth.NewAppModule(app.appCodec, app.AccountKeeper, authsims.RandomGenesisAccounts, nil),
}

app.sm = module.NewSimulationManagerFromAppModules(app.ModuleManager.Modules, overrideModules)

app.sm.RegisterStoreDecoders()

	// initialize stores
	app.MountKVStores(keys)

	// initialize BaseApp
	app.SetInitChainer(app.InitChainer)

app.SetPreBlocker(app.PreBlocker)

app.SetBeginBlocker(app.BeginBlocker)

app.SetEndBlocker(app.EndBlocker)

app.setAnteHandler(txConfig)

	// In v0.46, the SDK introduces _postHandlers_. PostHandlers are like
	// antehandlers, but are run _after_ the `runMsgs` execution. They are also
	// defined as a chain, and have the same signature as antehandlers.
	//
	// In baseapp, postHandlers are run in the same store branch as `runMsgs`,
	// meaning that both `runMsgs` and `postHandler` state will be committed if
	// both are successful, and both will be reverted if any of the two fails.
	//
	// The SDK exposes a default postHandlers chain
	//
	// Please note that changing any of the anteHandler or postHandler chain is
	// likely to be a state-machine breaking change, which needs a coordinated
	// upgrade.
	app.setPostHandler()
    if loadLatest {
    if err := app.LoadLatestVersion(); err != nil {
    panic(fmt.Errorf("error loading last version: %w", err))
}
	
}

return app
}

func (app *SimApp)

setAnteHandler(txConfig client.TxConfig) {
    anteHandler, err := ante.NewAnteHandler(
		ante.HandlerOptions{
    AccountKeeper:   app.AccountKeeper,
    BankKeeper:      app.BankKeeper,
    SignModeHandler: txConfig.SignModeHandler(),
    FeegrantKeeper:  app.FeeGrantKeeper,
    SigGasConsumer:  ante.DefaultSigVerificationGasConsumer,
    SigVerifyOptions: []ante.SigVerificationDecoratorOption{
				// change below as needed.
				ante.WithUnorderedTxGasCost(ante.DefaultUnorderedTxGasCost),
				ante.WithMaxUnorderedTxTimeoutDuration(ante.DefaultMaxTimeoutDuration),
},
},
	)
    if err != nil {
    panic(err)
}

	// Set the AnteHandler for the app
	app.SetAnteHandler(anteHandler)
}

func (app *SimApp)

setPostHandler() {
    postHandler, err := posthandler.NewPostHandler(
		posthandler.HandlerOptions{
},
	)
    if err != nil {
    panic(err)
}

app.SetPostHandler(postHandler)
}

// Name returns the name of the App
func (app *SimApp)

Name()

string {
    return app.BaseApp.Name()
}

// PreBlocker application updates every pre block
func (app *SimApp)

PreBlocker(ctx sdk.Context, _ *abci.RequestFinalizeBlock) (*sdk.ResponsePreBlock, error) {
    return app.ModuleManager.PreBlock(ctx)
}

// BeginBlocker application updates every begin block
func (app *SimApp)

BeginBlocker(ctx sdk.Context) (sdk.BeginBlock, error) {
    return app.ModuleManager.BeginBlock(ctx)
}

// EndBlocker application updates every end block
func (app *SimApp)

EndBlocker(ctx sdk.Context) (sdk.EndBlock, error) {
    return app.ModuleManager.EndBlock(ctx)
}

func (a *SimApp)

Configurator()

module.Configurator {
    return a.configurator
}

// InitChainer application update at chain initialization
func (app *SimApp)

InitChainer(ctx sdk.Context, req *abci.RequestInitChain) (*abci.ResponseInitChain, error) {
    var genesisState GenesisState
    if err := json.Unmarshal(req.AppStateBytes, &genesisState); err != nil {
    panic(err)
}

app.UpgradeKeeper.SetModuleVersionMap(ctx, app.ModuleManager.GetVersionMap())

return app.ModuleManager.InitGenesis(ctx, app.appCodec, genesisState)
}

// LoadHeight loads a particular height
func (app *SimApp)

LoadHeight(height int64)

error {
    return app.LoadVersion(height)
}

// LegacyAmino returns SimApp's amino codec.
//
// NOTE: This is solely to be used for testing purposes as it may be desirable
// for modules to register their own custom testing types.
func (app *SimApp)

LegacyAmino() *codec.LegacyAmino {
    return app.legacyAmino
}

// AppCodec returns SimApp's app codec.
//
// NOTE: This is solely to be used for testing purposes as it may be desirable
// for modules to register their own custom testing types.
func (app *SimApp)

AppCodec()

codec.Codec {
    return app.appCodec
}

// InterfaceRegistry returns SimApp's InterfaceRegistry
func (app *SimApp)

InterfaceRegistry()

types.InterfaceRegistry {
    return app.interfaceRegistry
}

// TxConfig returns SimApp's TxConfig
func (app *SimApp)

TxConfig()

client.TxConfig {
    return app.txConfig
}

// AutoCliOpts returns the autocli options for the app.
func (app *SimApp)

AutoCliOpts()

autocli.AppOptions {
    modules := make(map[string]appmodule.AppModule, 0)
    for _, m := range app.ModuleManager.Modules {
    if moduleWithName, ok := m.(module.HasName); ok {
    moduleName := moduleWithName.Name()
    if appModule, ok := moduleWithName.(appmodule.AppModule); ok {
    modules[moduleName] = appModule
}
	
}
	
}

return autocli.AppOptions{
    Modules:               modules,
    ModuleOptions:         runtimeservices.ExtractAutoCLIOptions(app.ModuleManager.Modules),
    AddressCodec:          authcodec.NewBech32Codec(sdk.GetConfig().GetBech32AccountAddrPrefix()),
    ValidatorAddressCodec: authcodec.NewBech32Codec(sdk.GetConfig().GetBech32ValidatorAddrPrefix()),
    ConsensusAddressCodec: authcodec.NewBech32Codec(sdk.GetConfig().GetBech32ConsensusAddrPrefix()),
}
}

// DefaultGenesis returns a default genesis from the registered AppModuleBasic's.
func (a *SimApp)

DefaultGenesis()

map[string]json.RawMessage {
    return a.BasicModuleManager.DefaultGenesis(a.appCodec)
}

// GetKey returns the KVStoreKey for the provided store key.
//
// NOTE: This is solely to be used for testing purposes.
func (app *SimApp)

GetKey(storeKey string) *storetypes.KVStoreKey {
    return app.keys[storeKey]
}

// GetStoreKeys returns all the stored store keys.
func (app *SimApp)

GetStoreKeys() []storetypes.StoreKey {
    keys := make([]storetypes.StoreKey, 0, len(app.keys))
    for _, key := range app.keys {
    keys = append(keys, key)
}

return keys
}

// SimulationManager implements the SimulationApp interface
func (app *SimApp)

SimulationManager() *module.SimulationManager {
    return app.sm
}

// RegisterAPIRoutes registers all application module routes with the provided
// API server.
func (app *SimApp)

RegisterAPIRoutes(apiSvr *api.Server, apiConfig config.APIConfig) {
    clientCtx := apiSvr.ClientCtx
	// Register new tx routes from grpc-gateway.
	authtx.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)

	// Register new CometBFT queries routes from grpc-gateway.
	cmtservice.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)

	// Register node gRPC service for grpc-gateway.
	nodeservice.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)

	// Register grpc-gateway routes for all modules.
	app.BasicModuleManager.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)

	// register swagger API from root so that other applications can override easily
    if err := server.RegisterSwaggerAPI(apiSvr.ClientCtx, apiSvr.Router, apiConfig.Swagger); err != nil {
    panic(err)
}
}

// RegisterTxService implements the Application.RegisterTxService method.
func (app *SimApp)

RegisterTxService(clientCtx client.Context) {
    authtx.RegisterTxService(app.BaseApp.GRPCQueryRouter(), clientCtx, app.BaseApp.Simulate, app.interfaceRegistry)
}

// RegisterTendermintService implements the Application.RegisterTendermintService method.
func (app *SimApp)

RegisterTendermintService(clientCtx client.Context) {
    cmtApp := server.NewCometABCIWrapper(app)

cmtservice.RegisterTendermintService(
		clientCtx,
		app.BaseApp.GRPCQueryRouter(),
		app.interfaceRegistry,
		cmtApp.Query,
	)
}

func (app *SimApp)

RegisterNodeService(clientCtx client.Context, cfg config.Config) {
    nodeservice.RegisterNodeService(clientCtx, app.GRPCQueryRouter(), cfg)
}

// GetMaccPerms returns a copy of the module account permissions
//
// NOTE: This is solely to be used for testing purposes.
func GetMaccPerms()

map[string][]string {
    return maps.Clone(maccPerms)
}

// BlockedAddresses returns all the app's blocked account addresses.
func BlockedAddresses()

map[string]bool {
    modAccAddrs := make(map[string]bool)
    for acc := range GetMaccPerms() {
    modAccAddrs[authtypes.NewModuleAddress(acc).String()] = true
}

	// allow the following addresses to receive funds
	delete(modAccAddrs, authtypes.NewModuleAddress(govtypes.ModuleName).String())

return modAccAddrs
}
```

Note that you may override some modules.
This is useful if the existing module configuration in the `ModuleManager` should be different in the `SimulationManager`.

Finally, the application should expose the `SimulationManager` via the following method defined in the `Runtime` interface:

```go theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
// SimulationManager implements the SimulationApp interface
func (app *SimApp)

SimulationManager() *module.SimulationManager {
    return app.sm
}
```

## Running Simulations

To run the simulation, use the `simsx` runner.

Call the following function from the `simsx` package to begin simulating with a default seed:

```go expandable theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
package simsx

import (
    
	"encoding/json"
    "fmt"
    "io"
    "math"
    "os"
    "path/filepath"
    "strings"
    "testing"

	dbm "github.com/cosmos/cosmos-db"
    "github.com/stretchr/testify/require"
    "cosmossdk.io/log"
    "github.com/cosmos/cosmos-sdk/baseapp"
    "github.com/cosmos/cosmos-sdk/client"
    "github.com/cosmos/cosmos-sdk/client/flags"
    "github.com/cosmos/cosmos-sdk/codec"
    "github.com/cosmos/cosmos-sdk/runtime"
	servertypes "github.com/cosmos/cosmos-sdk/server/types"
	simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims"
	sdk "github.com/cosmos/cosmos-sdk/types"
    "github.com/cosmos/cosmos-sdk/types/module"
	simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
    "github.com/cosmos/cosmos-sdk/x/simulation"
    "github.com/cosmos/cosmos-sdk/x/simulation/client/cli"
)

const SimAppChainID = "simulation-app"

// this list of seeds was imported from the original simulation runner: https://github.com/cosmos/tools/blob/v1.0.0/cmd/runsim/main.go#L32
var defaultSeeds = []int64{
	1, 2, 4, 7,
	32, 123, 124, 582, 1893, 2989,
	3012, 4728, 37827, 981928, 87821, 891823782,
	989182, 89182391, 11, 22, 44, 77, 99, 2020,
	3232, 123123, 124124, 582582, 18931893,
	29892989, 30123012, 47284728, 7601778, 8090485,
	977367484, 491163361, 424254581, 673398983,
}

// SimStateFactory is a factory type that provides a convenient way to create a simulation state for testing.
// It contains the following fields:
// - Codec: a codec used for serializing other objects
// - AppStateFn: a function that returns the app state JSON bytes and the genesis accounts
// - BlockedAddr: a map of blocked addresses
// - AccountSource: an interface for retrieving accounts
// - BalanceSource: an interface for retrieving balance-related information
type SimStateFactory struct {
    Codec         codec.Codec
	AppStateFn    simtypes.AppStateFn
	BlockedAddr   map[string]bool
	AccountSource AccountSourceX
	BalanceSource BalanceSource
}

// SimulationApp abstract app that is used by sims
type SimulationApp interface {
    runtime.AppI
	SetNotSigverifyTx()

GetBaseApp() *baseapp.BaseApp
	TxConfig()

client.TxConfig
	Close()

error
}

// Run is a helper function that runs a simulation test with the given parameters.
// It calls the RunWithSeeds function with the default seeds and parameters.
//
// This is the entrypoint to run simulation tests that used to run with the runsim binary.
func Run[T SimulationApp](
	t *testing.T,
	appFactory func(
		logger log.Logger,
		db dbm.DB,
		traceStore io.Writer,
		loadLatest bool,
		appOpts servertypes.AppOptions,
		baseAppOptions ...func(*baseapp.BaseApp),
	)

T,
	setupStateFactory func(app T)

SimStateFactory,
	postRunActions ...func(t testing.TB, app TestInstance[T], accs []simtypes.Account),
) {
    t.Helper()

RunWithSeeds(t, appFactory, setupStateFactory, defaultSeeds, nil, postRunActions...)
}

// RunWithSeeds is a helper function that runs a simulation test with the given parameters.
// It iterates over the provided seeds and runs the simulation test for each seed in parallel.
//
// It sets up the environment, creates an instance of the simulation app,
// calls the simulation.SimulateFromSeed function to run the simulation, and performs post-run actions for each seed.
// The execution is deterministic and can be used for fuzz tests as well.
//
// The system under test is isolated for each run but unlike the old runsim command, there is no Process separation.
// This means, global caches may be reused for example. This implementation build upon the vanilla Go stdlib test framework.
func RunWithSeeds[T SimulationApp](
	t *testing.T,
	appFactory func(
		logger log.Logger,
		db dbm.DB,
		traceStore io.Writer,
		loadLatest bool,
		appOpts servertypes.AppOptions,
		baseAppOptions ...func(*baseapp.BaseApp),
	)

T,
	setupStateFactory func(app T)

SimStateFactory,
	seeds []int64,
	fuzzSeed []byte,
	postRunActions ...func(t testing.TB, app TestInstance[T], accs []simtypes.Account),
) {
    t.Helper()

RunWithSeedsAndRandAcc(t, appFactory, setupStateFactory, seeds, fuzzSeed, simtypes.RandomAccounts, postRunActions...)
}

// RunWithSeedsAndRandAcc calls RunWithSeeds with randAccFn
func RunWithSeedsAndRandAcc[T SimulationApp](
	t *testing.T,
	appFactory func(
		logger log.Logger,
		db dbm.DB,
		traceStore io.Writer,
		loadLatest bool,
		appOpts servertypes.AppOptions,
		baseAppOptions ...func(*baseapp.BaseApp),
	)

T,
	setupStateFactory func(app T)

SimStateFactory,
	seeds []int64,
	fuzzSeed []byte,
	randAccFn simtypes.RandomAccountFn,
	postRunActions ...func(t testing.TB, app TestInstance[T], accs []simtypes.Account),
) {
    t.Helper()
    if deprecatedParams := cli.GetDeprecatedFlagUsed(); len(deprecatedParams) != 0 {
    fmt.Printf("Warning: Deprecated flag are used: %s", strings.Join(deprecatedParams, ","))
}
    cfg := cli.NewConfigFromFlags()

cfg.ChainID = SimAppChainID
    for i := range seeds {
    seed := seeds[i]
		t.Run(fmt.Sprintf("seed: %d", seed), func(t *testing.T) {
    t.Parallel()

RunWithSeed(t, cfg, appFactory, setupStateFactory, seed, fuzzSeed, postRunActions...)
})
}
}

// RunWithSeed is a helper function that runs a simulation test with the given parameters.
// It iterates over the provided seeds and runs the simulation test for each seed in parallel.
//
// It sets up the environment, creates an instance of the simulation app,
// calls the simulation.SimulateFromSeed function to run the simulation, and performs post-run actions for the seed.
// The execution is deterministic and can be used for fuzz tests as well.
func RunWithSeed[T SimulationApp](
	tb testing.TB,
	cfg simtypes.Config,
	appFactory func(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest bool, appOpts servertypes.AppOptions, baseAppOptions ...func(*baseapp.BaseApp))

T,
	setupStateFactory func(app T)

SimStateFactory,
	seed int64,
	fuzzSeed []byte,
	postRunActions ...func(t testing.TB, app TestInstance[T], accs []simtypes.Account),
) {
    tb.Helper()

RunWithSeedAndRandAcc(tb, cfg, appFactory, setupStateFactory, seed, fuzzSeed, simtypes.RandomAccounts, postRunActions...)
}

// RunWithSeedAndRandAcc calls RunWithSeed with randAccFn
func RunWithSeedAndRandAcc[T SimulationApp](
	tb testing.TB,
	cfg simtypes.Config,
	appFactory func(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest bool, appOpts servertypes.AppOptions, baseAppOptions ...func(*baseapp.BaseApp))

T,
	setupStateFactory func(app T)

SimStateFactory,
	seed int64,
	fuzzSeed []byte,
	randAccFn simtypes.RandomAccountFn,
	postRunActions ...func(t testing.TB, app TestInstance[T], accs []simtypes.Account),
) {
    tb.Helper()
	// setup environment
    tCfg := cfg.With(tb, seed, fuzzSeed)
    testInstance := NewSimulationAppInstance(tb, tCfg, appFactory)

var runLogger log.Logger
    if cli.FlagVerboseValue {
    runLogger = log.NewTestLogger(tb)
}

else {
    runLogger = log.NewTestLoggerInfo(tb)
}

runLogger = runLogger.With("seed", tCfg.Seed)
    app := testInstance.App
    stateFactory := setupStateFactory(app)

ops, reporter := prepareWeightedOps(app.SimulationManager(), stateFactory, tCfg, testInstance.App.TxConfig(), runLogger)

simParams, accs, err := simulation.SimulateFromSeedX(
		tb,
		runLogger,
		WriteToDebugLog(runLogger),
		app.GetBaseApp(),
		stateFactory.AppStateFn,
		randAccFn,
		ops,
		stateFactory.BlockedAddr,
		tCfg,
		stateFactory.Codec,
		testInstance.ExecLogWriter,
	)

require.NoError(tb, err)

err = simtestutil.CheckExportSimulation(app, tCfg, simParams)

require.NoError(tb, err)
    if tCfg.Commit {
    simtestutil.PrintStats(testInstance.DB)
}
	// not using tb.Log to always print the summary
	fmt.Printf("+++ DONE (seed: %d): \n%s\n", seed, reporter.Summary().String())
    for _, step := range postRunActions {
    step(tb, testInstance, accs)
}

require.NoError(tb, app.Close())
}

type (
	HasWeightedOperationsX interface {
    WeightedOperationsX(weight WeightSource, reg Registry)
}

HasWeightedOperationsXWithProposals interface {
    WeightedOperationsX(weights WeightSource, reg Registry, proposals WeightedProposalMsgIter,
			legacyProposals []simtypes.WeightedProposalContent) //nolint: staticcheck // used for legacy proposal types
}

HasProposalMsgsX interface {
    ProposalMsgsX(weights WeightSource, reg Registry)
}
)

type (
	HasLegacyWeightedOperations interface {
		// WeightedOperations simulation operations (i.e msgs)

with their respective weight
		WeightedOperations(simState module.SimulationState) []simtypes.WeightedOperation
}
	// HasLegacyProposalMsgs defines the messages that can be used to simulate governance (v1)

proposals
	// Deprecated replaced by HasProposalMsgsX
	HasLegacyProposalMsgs interface {
		// ProposalMsgs msg fu	nctions used to simulate governance proposals
		ProposalMsgs(simState module.SimulationState) []simtypes.WeightedProposalMsg
}

	// HasLegacyProposalContents defines the contents that can be used to simulate legacy governance (v1beta1)

proposals
	// Deprecated replaced by HasProposalMsgsX
	HasLegacyProposalContents interface {
		// ProposalContents content functions used to simulate governance proposals
		ProposalContents(simState module.SimulationState) []simtypes.WeightedProposalContent //nolint:staticcheck // legacy v1beta1 governance
}
)

// TestInstance is a generic type that represents an instance of a SimulationApp used for testing simulations.
// It contains the following fields:
//   - App: The instance of the SimulationApp under test.
//   - DB: The LevelDB database for the simulation app.
//   - WorkDir: The temporary working directory for the simulation app.
//   - Cfg: The configuration flags for the simulator.
//   - AppLogger: The logger used for logging in the app during the simulation, with seed value attached.
//   - ExecLogWriter: Captures block and operation data coming from the simulation
type TestInstance[T SimulationApp] struct {
    App           T
	DB            dbm.DB
	WorkDir       string
	Cfg           simtypes.Config
	AppLogger     log.Logger
	ExecLogWriter simulation.LogWriter
}

// included to avoid cyclic dependency in testutils/sims
func prepareWeightedOps(
	sm *module.SimulationManager,
	stateFact SimStateFactory,
	config simtypes.Config,
	txConfig client.TxConfig,
	logger log.Logger,
) (simulation.WeightedOperations, *BasicSimulationReporter) {
    cdc := stateFact.Codec
    simState := module.SimulationState{
    AppParams: make(simtypes.AppParams),
    Cdc:       cdc,
    TxConfig:  txConfig,
    BondDenom: sdk.DefaultBondDenom,
}
    if config.ParamsFile != "" {
    bz, err := os.ReadFile(config.ParamsFile)
    if err != nil {
    panic(err)
}

err = json.Unmarshal(bz, &simState.AppParams)
    if err != nil {
    panic(err)
}
	
}
    weights := ParamWeightSource(simState.AppParams)
    reporter := NewBasicSimulationReporter()
    pReg := make(UniqueTypeRegistry)
    wContent := make([]simtypes.WeightedProposalContent, 0) //nolint:staticcheck // required for legacy type
    legacyPReg := NewWeightedFactoryMethods()
	// add gov proposals types
    for _, m := range sm.Modules {
    switch xm := m.(type) {
    case HasProposalMsgsX:
			xm.ProposalMsgsX(weights, pReg)
    case HasLegacyProposalMsgs:
    for _, p := range xm.ProposalMsgs(simState) {
    weight := weights.Get(p.AppParamsKey(), safeUint(p.DefaultWeight()))

legacyPReg.Add(weight, legacyToMsgFactoryAdapter(p.MsgSimulatorFn()))
}
    case HasLegacyProposalContents:
			wContent = append(wContent, xm.ProposalContents(simState)...)
}
	
}
    oReg := NewSimsMsgRegistryAdapter(
		reporter,
		stateFact.AccountSource,
		stateFact.BalanceSource,
		txConfig,
		logger,
	)
    wOps := make([]simtypes.WeightedOperation, 0, len(sm.Modules))
    for _, m := range sm.Modules {
		// add operations
    switch xm := m.(type) {
    case HasWeightedOperationsX:
			xm.WeightedOperationsX(weights, oReg)
    case HasWeightedOperationsXWithProposals:
			xm.WeightedOperationsX(weights, oReg, AppendIterators(legacyPReg.Iterator(), pReg.Iterator()), wContent)
    case HasLegacyWeightedOperations:
			wOps = append(wOps, xm.WeightedOperations(simState)...)
}
	
}

return append(wOps, Collect(oReg.items, func(a weightedOperation)

simtypes.WeightedOperation {
    return a
})...), reporter
}

func safeUint(p int)

uint32 {
    if p < 0 || p > math.MaxUint32 {
    panic(fmt.Sprintf("can not cast to uint32: %d", p))
}

return uint32(p)
}

// NewSimulationAppInstance initializes and returns a TestInstance of a SimulationApp.
// The function takes a testing.T instance, a simtypes.Config instance, and an appFactory function as parameters.
// It creates a temporary working directory and a LevelDB database for the simulation app.
// The function then initializes a logger based on the verbosity flag and sets the logger's seed to the test configuration's seed.
// The database is closed and cleaned up on test completion.
func NewSimulationAppInstance[T SimulationApp](
	tb testing.TB,
	tCfg simtypes.Config,
	appFactory func(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest bool, appOpts servertypes.AppOptions, baseAppOptions ...func(*baseapp.BaseApp))

T,
)

TestInstance[T] {
    tb.Helper()
    workDir := tb.TempDir()

require.NoError(tb, os.Mkdir(filepath.Join(workDir, "data"), 0o750))
    dbDir := filepath.Join(workDir, "leveldb-app-sim")

var logger log.Logger
    if cli.FlagVerboseValue {
    logger = log.NewTestLogger(tb)
}

else {
    logger = log.NewTestLoggerError(tb)
}

logger = logger.With("seed", tCfg.Seed)

db, err := dbm.NewDB("Simulation", dbm.BackendType(tCfg.DBBackend), dbDir)

require.NoError(tb, err)

tb.Cleanup(func() {
		_ = db.Close() // ensure db is closed
})
    appOptions := make(simtestutil.AppOptionsMap)

appOptions[flags.FlagHome] = workDir
    opts := []func(*baseapp.BaseApp) {
    baseapp.SetChainID(tCfg.ChainID)
}
    if tCfg.FauxMerkle {
    opts = append(opts, FauxMerkleModeOpt)
}
    app := appFactory(logger, db, nil, true, appOptions, opts...)
    if !cli.FlagSigverifyTxValue {
    app.SetNotSigverifyTx()
}

return TestInstance[T]{
    App:           app,
    DB:            db,
    WorkDir:       workDir,
    Cfg:           tCfg,
    AppLogger:     logger,
    ExecLogWriter: &simulation.StandardLogWriter{
    Seed: tCfg.Seed
},
}
}

var _ io.Writer = writerFn(nil)

type writerFn func(p []byte) (n int, err error)

func (w writerFn)

Write(p []byte) (n int, err error) {
    return w(p)
}

// WriteToDebugLog is an adapter to io.Writer interface
func WriteToDebugLog(logger log.Logger)

io.Writer {
    return writerFn(func(p []byte) (n int, err error) {
    logger.Debug(string(p))

return len(p), nil
})
}

// FauxMerkleModeOpt returns a BaseApp option to use a dbStoreAdapter instead of
// an IAVLStore for faster simulation speed.
func FauxMerkleModeOpt(bapp *baseapp.BaseApp) {
    bapp.SetFauxMerkleMode()
}
```

If a custom seed is desired, tests should use `RunWithSeed`:

```go expandable theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
package simsx

import (
    
	"encoding/json"
    "fmt"
    "io"
    "math"
    "os"
    "path/filepath"
    "strings"
    "testing"

	dbm "github.com/cosmos/cosmos-db"
    "github.com/stretchr/testify/require"
    "cosmossdk.io/log"
    "github.com/cosmos/cosmos-sdk/baseapp"
    "github.com/cosmos/cosmos-sdk/client"
    "github.com/cosmos/cosmos-sdk/client/flags"
    "github.com/cosmos/cosmos-sdk/codec"
    "github.com/cosmos/cosmos-sdk/runtime"
	servertypes "github.com/cosmos/cosmos-sdk/server/types"
	simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims"
	sdk "github.com/cosmos/cosmos-sdk/types"
    "github.com/cosmos/cosmos-sdk/types/module"
	simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
    "github.com/cosmos/cosmos-sdk/x/simulation"
    "github.com/cosmos/cosmos-sdk/x/simulation/client/cli"
)

const SimAppChainID = "simulation-app"

// this list of seeds was imported from the original simulation runner: https://github.com/cosmos/tools/blob/v1.0.0/cmd/runsim/main.go#L32
var defaultSeeds = []int64{
	1, 2, 4, 7,
	32, 123, 124, 582, 1893, 2989,
	3012, 4728, 37827, 981928, 87821, 891823782,
	989182, 89182391, 11, 22, 44, 77, 99, 2020,
	3232, 123123, 124124, 582582, 18931893,
	29892989, 30123012, 47284728, 7601778, 8090485,
	977367484, 491163361, 424254581, 673398983,
}

// SimStateFactory is a factory type that provides a convenient way to create a simulation state for testing.
// It contains the following fields:
// - Codec: a codec used for serializing other objects
// - AppStateFn: a function that returns the app state JSON bytes and the genesis accounts
// - BlockedAddr: a map of blocked addresses
// - AccountSource: an interface for retrieving accounts
// - BalanceSource: an interface for retrieving balance-related information
type SimStateFactory struct {
    Codec         codec.Codec
	AppStateFn    simtypes.AppStateFn
	BlockedAddr   map[string]bool
	AccountSource AccountSourceX
	BalanceSource BalanceSource
}

// SimulationApp abstract app that is used by sims
type SimulationApp interface {
    runtime.AppI
	SetNotSigverifyTx()

GetBaseApp() *baseapp.BaseApp
	TxConfig()

client.TxConfig
	Close()

error
}

// Run is a helper function that runs a simulation test with the given parameters.
// It calls the RunWithSeeds function with the default seeds and parameters.
//
// This is the entrypoint to run simulation tests that used to run with the runsim binary.
func Run[T SimulationApp](
	t *testing.T,
	appFactory func(
		logger log.Logger,
		db dbm.DB,
		traceStore io.Writer,
		loadLatest bool,
		appOpts servertypes.AppOptions,
		baseAppOptions ...func(*baseapp.BaseApp),
	)

T,
	setupStateFactory func(app T)

SimStateFactory,
	postRunActions ...func(t testing.TB, app TestInstance[T], accs []simtypes.Account),
) {
    t.Helper()

RunWithSeeds(t, appFactory, setupStateFactory, defaultSeeds, nil, postRunActions...)
}

// RunWithSeeds is a helper function that runs a simulation test with the given parameters.
// It iterates over the provided seeds and runs the simulation test for each seed in parallel.
//
// It sets up the environment, creates an instance of the simulation app,
// calls the simulation.SimulateFromSeed function to run the simulation, and performs post-run actions for each seed.
// The execution is deterministic and can be used for fuzz tests as well.
//
// The system under test is isolated for each run but unlike the old runsim command, there is no Process separation.
// This means, global caches may be reused for example. This implementation build upon the vanilla Go stdlib test framework.
func RunWithSeeds[T SimulationApp](
	t *testing.T,
	appFactory func(
		logger log.Logger,
		db dbm.DB,
		traceStore io.Writer,
		loadLatest bool,
		appOpts servertypes.AppOptions,
		baseAppOptions ...func(*baseapp.BaseApp),
	)

T,
	setupStateFactory func(app T)

SimStateFactory,
	seeds []int64,
	fuzzSeed []byte,
	postRunActions ...func(t testing.TB, app TestInstance[T], accs []simtypes.Account),
) {
    t.Helper()

RunWithSeedsAndRandAcc(t, appFactory, setupStateFactory, seeds, fuzzSeed, simtypes.RandomAccounts, postRunActions...)
}

// RunWithSeedsAndRandAcc calls RunWithSeeds with randAccFn
func RunWithSeedsAndRandAcc[T SimulationApp](
	t *testing.T,
	appFactory func(
		logger log.Logger,
		db dbm.DB,
		traceStore io.Writer,
		loadLatest bool,
		appOpts servertypes.AppOptions,
		baseAppOptions ...func(*baseapp.BaseApp),
	)

T,
	setupStateFactory func(app T)

SimStateFactory,
	seeds []int64,
	fuzzSeed []byte,
	randAccFn simtypes.RandomAccountFn,
	postRunActions ...func(t testing.TB, app TestInstance[T], accs []simtypes.Account),
) {
    t.Helper()
    if deprecatedParams := cli.GetDeprecatedFlagUsed(); len(deprecatedParams) != 0 {
    fmt.Printf("Warning: Deprecated flag are used: %s", strings.Join(deprecatedParams, ","))
}
    cfg := cli.NewConfigFromFlags()

cfg.ChainID = SimAppChainID
    for i := range seeds {
    seed := seeds[i]
		t.Run(fmt.Sprintf("seed: %d", seed), func(t *testing.T) {
    t.Parallel()

RunWithSeed(t, cfg, appFactory, setupStateFactory, seed, fuzzSeed, postRunActions...)
})
}
}

// RunWithSeed is a helper function that runs a simulation test with the given parameters.
// It iterates over the provided seeds and runs the simulation test for each seed in parallel.
//
// It sets up the environment, creates an instance of the simulation app,
// calls the simulation.SimulateFromSeed function to run the simulation, and performs post-run actions for the seed.
// The execution is deterministic and can be used for fuzz tests as well.
func RunWithSeed[T SimulationApp](
	tb testing.TB,
	cfg simtypes.Config,
	appFactory func(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest bool, appOpts servertypes.AppOptions, baseAppOptions ...func(*baseapp.BaseApp))

T,
	setupStateFactory func(app T)

SimStateFactory,
	seed int64,
	fuzzSeed []byte,
	postRunActions ...func(t testing.TB, app TestInstance[T], accs []simtypes.Account),
) {
    tb.Helper()

RunWithSeedAndRandAcc(tb, cfg, appFactory, setupStateFactory, seed, fuzzSeed, simtypes.RandomAccounts, postRunActions...)
}

// RunWithSeedAndRandAcc calls RunWithSeed with randAccFn
func RunWithSeedAndRandAcc[T SimulationApp](
	tb testing.TB,
	cfg simtypes.Config,
	appFactory func(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest bool, appOpts servertypes.AppOptions, baseAppOptions ...func(*baseapp.BaseApp))

T,
	setupStateFactory func(app T)

SimStateFactory,
	seed int64,
	fuzzSeed []byte,
	randAccFn simtypes.RandomAccountFn,
	postRunActions ...func(t testing.TB, app TestInstance[T], accs []simtypes.Account),
) {
    tb.Helper()
	// setup environment
    tCfg := cfg.With(tb, seed, fuzzSeed)
    testInstance := NewSimulationAppInstance(tb, tCfg, appFactory)

var runLogger log.Logger
    if cli.FlagVerboseValue {
    runLogger = log.NewTestLogger(tb)
}

else {
    runLogger = log.NewTestLoggerInfo(tb)
}

runLogger = runLogger.With("seed", tCfg.Seed)
    app := testInstance.App
    stateFactory := setupStateFactory(app)

ops, reporter := prepareWeightedOps(app.SimulationManager(), stateFactory, tCfg, testInstance.App.TxConfig(), runLogger)

simParams, accs, err := simulation.SimulateFromSeedX(
		tb,
		runLogger,
		WriteToDebugLog(runLogger),
		app.GetBaseApp(),
		stateFactory.AppStateFn,
		randAccFn,
		ops,
		stateFactory.BlockedAddr,
		tCfg,
		stateFactory.Codec,
		testInstance.ExecLogWriter,
	)

require.NoError(tb, err)

err = simtestutil.CheckExportSimulation(app, tCfg, simParams)

require.NoError(tb, err)
    if tCfg.Commit {
    simtestutil.PrintStats(testInstance.DB)
}
	// not using tb.Log to always print the summary
	fmt.Printf("+++ DONE (seed: %d): \n%s\n", seed, reporter.Summary().String())
    for _, step := range postRunActions {
    step(tb, testInstance, accs)
}

require.NoError(tb, app.Close())
}

type (
	HasWeightedOperationsX interface {
    WeightedOperationsX(weight WeightSource, reg Registry)
}

HasWeightedOperationsXWithProposals interface {
    WeightedOperationsX(weights WeightSource, reg Registry, proposals WeightedProposalMsgIter,
			legacyProposals []simtypes.WeightedProposalContent) //nolint: staticcheck // used for legacy proposal types
}

HasProposalMsgsX interface {
    ProposalMsgsX(weights WeightSource, reg Registry)
}
)

type (
	HasLegacyWeightedOperations interface {
		// WeightedOperations simulation operations (i.e msgs)

with their respective weight
		WeightedOperations(simState module.SimulationState) []simtypes.WeightedOperation
}
	// HasLegacyProposalMsgs defines the messages that can be used to simulate governance (v1)

proposals
	// Deprecated replaced by HasProposalMsgsX
	HasLegacyProposalMsgs interface {
		// ProposalMsgs msg fu	nctions used to simulate governance proposals
		ProposalMsgs(simState module.SimulationState) []simtypes.WeightedProposalMsg
}

	// HasLegacyProposalContents defines the contents that can be used to simulate legacy governance (v1beta1)

proposals
	// Deprecated replaced by HasProposalMsgsX
	HasLegacyProposalContents interface {
		// ProposalContents content functions used to simulate governance proposals
		ProposalContents(simState module.SimulationState) []simtypes.WeightedProposalContent //nolint:staticcheck // legacy v1beta1 governance
}
)

// TestInstance is a generic type that represents an instance of a SimulationApp used for testing simulations.
// It contains the following fields:
//   - App: The instance of the SimulationApp under test.
//   - DB: The LevelDB database for the simulation app.
//   - WorkDir: The temporary working directory for the simulation app.
//   - Cfg: The configuration flags for the simulator.
//   - AppLogger: The logger used for logging in the app during the simulation, with seed value attached.
//   - ExecLogWriter: Captures block and operation data coming from the simulation
type TestInstance[T SimulationApp] struct {
    App           T
	DB            dbm.DB
	WorkDir       string
	Cfg           simtypes.Config
	AppLogger     log.Logger
	ExecLogWriter simulation.LogWriter
}

// included to avoid cyclic dependency in testutils/sims
func prepareWeightedOps(
	sm *module.SimulationManager,
	stateFact SimStateFactory,
	config simtypes.Config,
	txConfig client.TxConfig,
	logger log.Logger,
) (simulation.WeightedOperations, *BasicSimulationReporter) {
    cdc := stateFact.Codec
    simState := module.SimulationState{
    AppParams: make(simtypes.AppParams),
    Cdc:       cdc,
    TxConfig:  txConfig,
    BondDenom: sdk.DefaultBondDenom,
}
    if config.ParamsFile != "" {
    bz, err := os.ReadFile(config.ParamsFile)
    if err != nil {
    panic(err)
}

err = json.Unmarshal(bz, &simState.AppParams)
    if err != nil {
    panic(err)
}
	
}
    weights := ParamWeightSource(simState.AppParams)
    reporter := NewBasicSimulationReporter()
    pReg := make(UniqueTypeRegistry)
    wContent := make([]simtypes.WeightedProposalContent, 0) //nolint:staticcheck // required for legacy type
    legacyPReg := NewWeightedFactoryMethods()
	// add gov proposals types
    for _, m := range sm.Modules {
    switch xm := m.(type) {
    case HasProposalMsgsX:
			xm.ProposalMsgsX(weights, pReg)
    case HasLegacyProposalMsgs:
    for _, p := range xm.ProposalMsgs(simState) {
    weight := weights.Get(p.AppParamsKey(), safeUint(p.DefaultWeight()))

legacyPReg.Add(weight, legacyToMsgFactoryAdapter(p.MsgSimulatorFn()))
}
    case HasLegacyProposalContents:
			wContent = append(wContent, xm.ProposalContents(simState)...)
}
	
}
    oReg := NewSimsMsgRegistryAdapter(
		reporter,
		stateFact.AccountSource,
		stateFact.BalanceSource,
		txConfig,
		logger,
	)
    wOps := make([]simtypes.WeightedOperation, 0, len(sm.Modules))
    for _, m := range sm.Modules {
		// add operations
    switch xm := m.(type) {
    case HasWeightedOperationsX:
			xm.WeightedOperationsX(weights, oReg)
    case HasWeightedOperationsXWithProposals:
			xm.WeightedOperationsX(weights, oReg, AppendIterators(legacyPReg.Iterator(), pReg.Iterator()), wContent)
    case HasLegacyWeightedOperations:
			wOps = append(wOps, xm.WeightedOperations(simState)...)
}
	
}

return append(wOps, Collect(oReg.items, func(a weightedOperation)

simtypes.WeightedOperation {
    return a
})...), reporter
}

func safeUint(p int)

uint32 {
    if p < 0 || p > math.MaxUint32 {
    panic(fmt.Sprintf("can not cast to uint32: %d", p))
}

return uint32(p)
}

// NewSimulationAppInstance initializes and returns a TestInstance of a SimulationApp.
// The function takes a testing.T instance, a simtypes.Config instance, and an appFactory function as parameters.
// It creates a temporary working directory and a LevelDB database for the simulation app.
// The function then initializes a logger based on the verbosity flag and sets the logger's seed to the test configuration's seed.
// The database is closed and cleaned up on test completion.
func NewSimulationAppInstance[T SimulationApp](
	tb testing.TB,
	tCfg simtypes.Config,
	appFactory func(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest bool, appOpts servertypes.AppOptions, baseAppOptions ...func(*baseapp.BaseApp))

T,
)

TestInstance[T] {
    tb.Helper()
    workDir := tb.TempDir()

require.NoError(tb, os.Mkdir(filepath.Join(workDir, "data"), 0o750))
    dbDir := filepath.Join(workDir, "leveldb-app-sim")

var logger log.Logger
    if cli.FlagVerboseValue {
    logger = log.NewTestLogger(tb)
}

else {
    logger = log.NewTestLoggerError(tb)
}

logger = logger.With("seed", tCfg.Seed)

db, err := dbm.NewDB("Simulation", dbm.BackendType(tCfg.DBBackend), dbDir)

require.NoError(tb, err)

tb.Cleanup(func() {
		_ = db.Close() // ensure db is closed
})
    appOptions := make(simtestutil.AppOptionsMap)

appOptions[flags.FlagHome] = workDir
    opts := []func(*baseapp.BaseApp) {
    baseapp.SetChainID(tCfg.ChainID)
}
    if tCfg.FauxMerkle {
    opts = append(opts, FauxMerkleModeOpt)
}
    app := appFactory(logger, db, nil, true, appOptions, opts...)
    if !cli.FlagSigverifyTxValue {
    app.SetNotSigverifyTx()
}

return TestInstance[T]{
    App:           app,
    DB:            db,
    WorkDir:       workDir,
    Cfg:           tCfg,
    AppLogger:     logger,
    ExecLogWriter: &simulation.StandardLogWriter{
    Seed: tCfg.Seed
},
}
}

var _ io.Writer = writerFn(nil)

type writerFn func(p []byte) (n int, err error)

func (w writerFn)

Write(p []byte) (n int, err error) {
    return w(p)
}

// WriteToDebugLog is an adapter to io.Writer interface
func WriteToDebugLog(logger log.Logger)

io.Writer {
    return writerFn(func(p []byte) (n int, err error) {
    logger.Debug(string(p))

return len(p), nil
})
}

// FauxMerkleModeOpt returns a BaseApp option to use a dbStoreAdapter instead of
// an IAVLStore for faster simulation speed.
func FauxMerkleModeOpt(bapp *baseapp.BaseApp) {
    bapp.SetFauxMerkleMode()
}
```

These functions should be called in tests (i.e., app\_test.go, app\_sim\_test.go, etc.)

Example:

```go expandable theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
//go:build sims

package simapp

import (
    
	"encoding/binary"
    "encoding/json"
    "flag"
    "io"
    "math/rand"
    "strings"
    "sync"
    "testing"

	abci "github.com/cometbft/cometbft/abci/types"
	cmtproto "github.com/cometbft/cometbft/proto/tendermint/types"
	dbm "github.com/cosmos/cosmos-db"
    "github.com/stretchr/testify/assert"
    "github.com/stretchr/testify/require"
    "cosmossdk.io/log"
    "cosmossdk.io/store"
	storetypes "cosmossdk.io/store/types"
    "github.com/cosmos/cosmos-sdk/baseapp"
	servertypes "github.com/cosmos/cosmos-sdk/server/types"
	simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims"
	sims "github.com/cosmos/cosmos-sdk/testutil/simsx"
	sdk "github.com/cosmos/cosmos-sdk/types"
	simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
	authzkeeper "github.com/cosmos/cosmos-sdk/x/authz/keeper"
    "github.com/cosmos/cosmos-sdk/x/feegrant"
    "github.com/cosmos/cosmos-sdk/x/simulation"
	simcli "github.com/cosmos/cosmos-sdk/x/simulation/client/cli"
	slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types"
	stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
)

var FlagEnableStreamingValue bool

// Get flags every time the simulator is run
func init() {
    simcli.GetSimulatorFlags()

flag.BoolVar(&FlagEnableStreamingValue, "EnableStreaming", false, "Enable streaming service")
}

// interBlockCacheOpt returns a BaseApp option function that sets the persistent
// inter-block write-through cache.
func interBlockCacheOpt()

func(*baseapp.BaseApp) {
    return baseapp.SetInterBlockCache(store.NewCommitKVStoreCacheManager())
}

func TestFullAppSimulation(t *testing.T) {
    sims.Run(t, NewSimApp, setupStateFactory)
}

func setupStateFactory(app *SimApp)

sims.SimStateFactory {
    return sims.SimStateFactory{
    Codec:         app.AppCodec(),
    AppStateFn:    simtestutil.AppStateFn(app.AppCodec(), app.SimulationManager(), app.DefaultGenesis()),
    BlockedAddr:   BlockedAddresses(),
    AccountSource: app.AccountKeeper,
    BalanceSource: app.BankKeeper,
}
}

var (
	exportAllModules       = []string{
}

exportWithValidatorSet = []string{
}
)

func TestAppImportExport(t *testing.T) {
    sims.Run(t, NewSimApp, setupStateFactory, func(tb testing.TB, ti sims.TestInstance[*SimApp], accs []simtypes.Account) {
    tb.Helper()
    app := ti.App
		tb.Log("exporting genesis...\n")

exported, err := app.ExportAppStateAndValidators(false, exportWithValidatorSet, exportAllModules)

require.NoError(tb, err)

tb.Log("importing genesis...\n")
    newTestInstance := sims.NewSimulationAppInstance(tb, ti.Cfg, NewSimApp)
    newApp := newTestInstance.App
		var genesisState GenesisState
		require.NoError(tb, json.Unmarshal(exported.AppState, &genesisState))
    ctxB := newApp.NewContextLegacy(true, cmtproto.Header{
    Height: app.LastBlockHeight()
})
		_, err = newApp.ModuleManager.InitGenesis(ctxB, newApp.appCodec, genesisState)
    if IsEmptyValidatorSetErr(err) {
    tb.Skip("Skipping simulation as all validators have been unbonded")

return
}

require.NoError(tb, err)

err = newApp.StoreConsensusParams(ctxB, exported.ConsensusParams)

require.NoError(tb, err)

tb.Log("comparing stores...")
		// skip certain prefixes
    skipPrefixes := map[string][][]byte{
    stakingtypes.StoreKey: {
    stakingtypes.UnbondingQueueKey, stakingtypes.RedelegationQueueKey, stakingtypes.ValidatorQueueKey,
				stakingtypes.HistoricalInfoKey, stakingtypes.UnbondingIDKey, stakingtypes.UnbondingIndexKey,
				stakingtypes.UnbondingTypeKey,
				stakingtypes.ValidatorUpdatesKey, // todo (Alex): double check why there is a diff with test-sim-import-export
},
			authzkeeper.StoreKey:   {
    authzkeeper.GrantQueuePrefix
},
			feegrant.StoreKey:      {
    feegrant.FeeAllowanceQueueKeyPrefix
},
			slashingtypes.StoreKey: {
    slashingtypes.ValidatorMissedBlockBitmapKeyPrefix
},
}

AssertEqualStores(tb, app, newApp, app.SimulationManager().StoreDecoders, skipPrefixes)
})
}

// Scenario:
//
//	Start a fresh node and run n blocks, export state
//	set up a new node instance, Init chain from exported genesis
//	run new instance for n blocks
func TestAppSimulationAfterImport(t *testing.T) {
    sims.Run(t, NewSimApp, setupStateFactory, func(tb testing.TB, ti sims.TestInstance[*SimApp], accs []simtypes.Account) {
    tb.Helper()
    app := ti.App
		tb.Log("exporting genesis...\n")

exported, err := app.ExportAppStateAndValidators(false, exportWithValidatorSet, exportAllModules)

require.NoError(tb, err)

tb.Log("importing genesis...\n")
    newTestInstance := sims.NewSimulationAppInstance(tb, ti.Cfg, NewSimApp)
    newApp := newTestInstance.App
		_, err = newApp.InitChain(&abci.RequestInitChain{
    AppStateBytes: exported.AppState,
    ChainId:       sims.SimAppChainID,
})
    if IsEmptyValidatorSetErr(err) {
    tb.Skip("Skipping simulation as all validators have been unbonded")

return
}

require.NoError(tb, err)
    newStateFactory := setupStateFactory(newApp)
		_, _, err = simulation.SimulateFromSeedX(
			tb,
			newTestInstance.AppLogger,
			sims.WriteToDebugLog(newTestInstance.AppLogger),
			newApp.BaseApp,
			newStateFactory.AppStateFn,
			simtypes.RandomAccounts,
			simtestutil.BuildSimulationOperations(newApp, newApp.AppCodec(), newTestInstance.Cfg, newApp.TxConfig()),
			newStateFactory.BlockedAddr,
			newTestInstance.Cfg,
			newStateFactory.Codec,
			ti.ExecLogWriter,
		)

require.NoError(tb, err)
})
}

func IsEmptyValidatorSetErr(err error)

bool {
    return err != nil && strings.Contains(err.Error(), "validator set is empty after InitGenesis")
}

func TestAppStateDeterminism(t *testing.T) {
    const numTimesToRunPerSeed = 3
	var seeds []int64
    if s := simcli.NewConfigFromFlags().Seed; s != simcli.DefaultSeedValue {
		// We will be overriding the random seed and just run a single simulation on the provided seed value
    for j := 0; j < numTimesToRunPerSeed; j++ { // multiple rounds
			seeds = append(seeds, s)
}
	
}

else {
		// setup with 3 random seeds
    for i := 0; i < 3; i++ {
    seed := rand.Int63()
    for j := 0; j < numTimesToRunPerSeed; j++ { // multiple rounds
				seeds = append(seeds, seed)
}
	
}
	
}
	// overwrite default app config
    interBlockCachingAppFactory := func(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest bool, appOpts servertypes.AppOptions, baseAppOptions ...func(*baseapp.BaseApp)) *SimApp {
    if FlagEnableStreamingValue {
    m := map[string]any{
				"streaming.abci.keys":             []string{"*"
},
				"streaming.abci.plugin":           "abci_v1",
				"streaming.abci.stop-node-on-err": true,
}
    others := appOpts
			appOpts = appOptionsFn(func(k string)

any {
    if v, ok := m[k]; ok {
    return v
}

return others.Get(k)
})
}

return NewSimApp(logger, db, nil, true, appOpts, append(baseAppOptions, interBlockCacheOpt())...)
}

var mx sync.Mutex
    appHashResults := make(map[int64][][]byte)
    appSimLogger := make(map[int64][]simulation.LogWriter)
    captureAndCheckHash := func(tb testing.TB, ti sims.TestInstance[*SimApp], _ []simtypes.Account) {
    tb.Helper()

seed, appHash := ti.Cfg.Seed, ti.App.LastCommitID().Hash
		mx.Lock()

otherHashes, execWriters := appHashResults[seed], appSimLogger[seed]
    if len(otherHashes) < numTimesToRunPerSeed-1 {
    appHashResults[seed], appSimLogger[seed] = append(otherHashes, appHash), append(execWriters, ti.ExecLogWriter)
}

else { // cleanup
			delete(appHashResults, seed)

delete(appSimLogger, seed)
}

mx.Unlock()

var failNow bool
		// and check that all app hashes per seed are equal for each iteration
    for i := 0; i < len(otherHashes); i++ {
    if !assert.Equal(tb, otherHashes[i], appHash) {
    execWriters[i].PrintLogs()

failNow = true
}
	
}
    if failNow {
    ti.ExecLogWriter.PrintLogs()

tb.Fatalf("non-determinism in seed %d", seed)
}
	
}
	// run simulations
	sims.RunWithSeeds(t, interBlockCachingAppFactory, setupStateFactory, seeds, []byte{
}, captureAndCheckHash)
}

type ComparableStoreApp interface {
    LastBlockHeight()

int64
	NewContextLegacy(isCheckTx bool, header cmtproto.Header)

sdk.Context
	GetKey(storeKey string) *storetypes.KVStoreKey
	GetStoreKeys() []storetypes.StoreKey
}

func AssertEqualStores(
	tb testing.TB,
	app, newApp ComparableStoreApp,
	storeDecoders simtypes.StoreDecoderRegistry,
	skipPrefixes map[string][][]byte,
) {
    tb.Helper()
    ctxA := app.NewContextLegacy(true, cmtproto.Header{
    Height: app.LastBlockHeight()
})
    ctxB := newApp.NewContextLegacy(true, cmtproto.Header{
    Height: app.LastBlockHeight()
})
    storeKeys := app.GetStoreKeys()

require.NotEmpty(tb, storeKeys)
    for _, appKeyA := range storeKeys {
		// only compare kvstores
    if _, ok := appKeyA.(*storetypes.KVStoreKey); !ok {
    continue
}
    keyName := appKeyA.Name()
    appKeyB := newApp.GetKey(keyName)
    storeA := ctxA.KVStore(appKeyA)
    storeB := ctxB.KVStore(appKeyB)

failedKVAs, failedKVBs := simtestutil.DiffKVStores(storeA, storeB, skipPrefixes[keyName])

require.Equal(tb, len(failedKVAs), len(failedKVBs), "unequal sets of key-values to compare %s, key stores %s and %s", keyName, appKeyA, appKeyB)

tb.Logf("compared %d different key/value pairs between %s and %s\n", len(failedKVAs), appKeyA, appKeyB)
    if !assert.Equal(tb, 0, len(failedKVAs), simtestutil.GetSimulationLog(keyName, storeDecoders, failedKVAs, failedKVBs)) {
    for _, v := range failedKVAs {
    tb.Logf("store mismatch: %q\n", v)
}

tb.FailNow()
}
	
}
}

// appOptionsFn is an adapter to the single method AppOptions interface
type appOptionsFn func(string)

any

func (f appOptionsFn)

Get(k string)

any {
    return f(k)
}

// FauxMerkleModeOpt returns a BaseApp option to use a dbStoreAdapter instead of
// an IAVLStore for faster simulation speed.
func FauxMerkleModeOpt(bapp *baseapp.BaseApp) {
    bapp.SetFauxMerkleMode()
}

func FuzzFullAppSimulation(f *testing.F) {
    f.Fuzz(func(t *testing.T, rawSeed []byte) {
    if len(rawSeed) < 8 {
    t.Skip()

return
}

sims.RunWithSeeds(
			t,
			NewSimApp,
			setupStateFactory,
			[]int64{
    int64(binary.BigEndian.Uint64(rawSeed))
},
			rawSeed[8:],
		)
})
}
```
