Repository: osmosis-labs/osmosis
Pull request #2071 (2022-07-14 21:01:16)

chore(app/upgrades): set app version correctly for v11
<!-- < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < ☺
v                               ✰  Thanks for creating a PR! ✰    
v    Before smashing the submit button please review the checkboxes.
v    If a checkbox is n/a - please still include it but + a little note why
v    If your PR doesn't close an issue, that's OK!  Just remove the Closes: #XXX line!
☺ > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > >  -->

Related to: https://github.com/osmosis-labs/osmosis/issues/1805

## What is the purpose of the change

Although the app version was already set during the v9 upgrade, our v10 was a fork.
As a result, the upgrade handler was not executed to increment the app version.
This change helps to correctly set the app version for v11.


## Testing and Verifying

This change can be verified by e2e upgrade tests

## Documentation and Release Note

  - Does this pull request introduce a new feature or user-facing behavior changes? no
  - Is a relevant changelog entry added to the `Unreleased` section in `CHANGELOG.md`? no
  - How is the feature or change documented? not applicable


Patch:
diff --git a/.github/labeler.yml b/.github/labeler.yml
index 49370713b..f2e92a956 100644
--- a/.github/labeler.yml
+++ b/.github/labeler.yml
@@ -9,6 +9,13 @@
   - app/upgrades/**/*
   # Also match any module.go update
   - x/**/module.go
+"C:simulator":
+  # Match all of simulation & tests/simulator folder
+  - simulation/**/*
+  - simulation/**/**/*
+  - tests/simulator/**
+  # Match any module update
+  - x/**/simulation/*.go
 "C:wasm":
   - app/wasm/**/*
 "C:x/claim":
diff --git a/.github/workflows/import_paths.yml b/.github/workflows/import_paths.yml
new file mode 100644
index 000000000..bf6ea8ec4
--- /dev/null
+++ b/.github/workflows/import_paths.yml
@@ -0,0 +1,73 @@
+# This is a manua workflow that does the following when trigerred:
+# - Runs a script to find and replace Go import path major version with given version.
+# - Commits and pushes changes to the source-branch.
+# - Opens a PR from the source branch to the target-branch.
+
+name: Update Go Import Paths
+
+on:
+  workflow_dispatch:
+    inputs:
+      version:
+        description: 'Current Version that we want to change'
+        default: '10'
+        required: true
+      target-branch:
+        description: 'Target Branch'
+        default: 'main'
+        required: true
+      source-branch:
+        description: 'Source Branch'
+        default: 'update-paths'
+        required: true
+
+jobs:
+  update-import-paths:
+    runs-on: ubuntu-latest
+
+    steps:
+      -
+        name: Check out repository code
+        uses: actions/checkout@v2
+      -
+        name: Setup Golang
+        uses: actions/setup-go@v2.1.4
+        with:
+          go-version: 1.18
+      -
+        name: Display go version
+        run: go version
+      -
+        name: Get data from build cache
+        uses: actions/cache@v2
+        with:
+          # In order:
+          # * Module download cache
+          # * Build cache (Linux)
+          # * Build cache (Mac)
+          # * Build cache (Windows)
+          path: |
+            ~/go/pkg/mod
+            ~/.cache/go-build
+            ~/Library/Caches/go-build
+            ~\AppData\Local\go-build
+          key: ${{ runner.os }}-go-${{ matrix.go-version }}-${{ hashFiles('**/go.sum') }}
+          restore-keys: |
+            ${{ runner.os }}-go-${{ matrix.go-version }}-
+      -
+        name: Run find & replace script
+        run: ./scripts/replace_import_paths.sh ${{ inputs.version }}
+      - name: Create Pull Request
+        uses: peter-evans/create-pull-request@v4
+        with:
+          token: ${{ secrets.ADD_TO_PROJECT_PAT }}
+          title: "auto: update Go import paths to v${{ inputs.version }}"
+          commit-message: "auto: update Go import paths to v${{ inputs.version }}"
+          body: "**Automated pull request**\n\nUpdating Go import paths to v${{ inputs.version }}"
+          base: ${{ inputs.target-branch }}
+          branch-suffix: random
+          branch: ${{ inputs.source-branch }}
+          delete-branch: true
+          assignees: ${{ github.actor }}
+          draft: true
+          labels: T:auto,T:code-hygiene
diff --git a/.gitignore b/.gitignore
index 445b33698..191166787 100644
--- a/.gitignore
+++ b/.gitignore
@@ -204,3 +204,5 @@ tools-stamp
 /tests/localosmosis/.osmosisd/*
 *.save
 *.save.*
+
+mutation_test_result.txt
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b7e31401d..235e00b75 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -42,6 +42,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 
 ## Unreleased
 
+* [#2016](https://github.com/osmosis-labs/osmosis/pull/2016) Add fixed 10000 gas cost for each Balancer swap
+
 ### Breaking Changes
 
 
@@ -62,6 +64,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 * [#1665](https://github.com/osmosis-labs/osmosis/pull/1665) Delete app/App interface, instead use simapp.App
 * [#1630](https://github.com/osmosis-labs/osmosis/pull/1630) Delete the v043_temp module, now that we're on an updated SDK version.
 * [#1667](https://github.com/osmosis-labs/osmosis/pull/1673) Move wasm-bindings code out of app package into its own root level package.
+* [#2013](https://github.com/osmosis-labs/osmosis/pull/2013) Make `SetParams`, `SetPool`, `SetTotalLiquidity`, and `SetDenomLiquidity` GAMM APIs private
 
 ### Features
 
diff --git a/Makefile b/Makefile
index 6eb060d17..79a7f1e4f 100644
--- a/Makefile
+++ b/Makefile
@@ -238,7 +238,7 @@ test-e2e-skip-upgrade:
 	@VERSION=$(VERSION) OSMOSIS_E2E_SKIP_UPGRADE=True go test -mod=readonly -timeout=25m -v $(PACKAGES_E2E)
 
 test-mutation:
-	@sh scripts/mutation-test.sh
+	@bash scripts/mutation-test.sh
 
 benchmark:
 	@go test -mod=readonly -bench=. $(PACKAGES_UNIT)
diff --git a/app/upgrades/v11/upgrades.go b/app/upgrades/v11/upgrades.go
index 58bf08979..f7ec51f18 100644
--- a/app/upgrades/v11/upgrades.go
+++ b/app/upgrades/v11/upgrades.go
@@ -9,6 +9,10 @@ import (
 	"github.com/osmosis-labs/osmosis/v7/app/upgrades"
 )
 
+// We set the app version to pre-upgrade because it will be incremented by one
+// after the upgrade is applied by the handler.
+const preUpgradeAppVersion = 10
+
 func CreateUpgradeHandler(
 	mm *module.Manager,
 	configurator module.Configurator,
@@ -16,6 +20,13 @@ func CreateUpgradeHandler(
 	keepers *keepers.AppKeepers,
 ) upgradetypes.UpgradeHandler {
 	return func(ctx sdk.Context, plan upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) {
+		// Although the app version was already set during the v9 upgrade, our v10 was a fork.
+		// As a result, the upgrade handler was not executed to increment the app version.
+		// This change helps to correctly set the app version for v11.
+		if err := keepers.UpgradeKeeper.SetAppVersion(ctx, preUpgradeAppVersion); err != nil {
+			return nil, err
+		}
+
 		return mm.RunMigrations(ctx, configurator, fromVM)
 	}
 }
diff --git a/app/upgrades/v4/upgrades.go b/app/upgrades/v4/upgrades.go
index e5b60ae36..eac31d0ab 100644
--- a/app/upgrades/v4/upgrades.go
+++ b/app/upgrades/v4/upgrades.go
@@ -7,7 +7,6 @@ import (
 
 	"github.com/osmosis-labs/osmosis/v7/app/keepers"
 	"github.com/osmosis-labs/osmosis/v7/app/upgrades"
-	gammtypes "github.com/osmosis-labs/osmosis/v7/x/gamm/types"
 )
 
 // CreateUpgradeHandler returns an x/upgrade handler for the Osmosis v4 on-chain
@@ -22,8 +21,8 @@ func CreateUpgradeHandler(
 	keepers *keepers.AppKeepers,
 ) upgradetypes.UpgradeHandler {
 	return func(ctx sdk.Context, _plan upgradetypes.Plan, vm module.VersionMap) (module.VersionMap, error) {
-		// configure upgrade for x/gamm module pool creation fee param
-		keepers.GAMMKeeper.SetParams(ctx, gammtypes.NewParams(sdk.Coins{sdk.NewInt64Coin("uosmo", 1)})) // 1 uOSMO
+		// Kept as comments for recordkeeping. SetParams is now private:
+		// 		keepers.GAMMKeeper.SetParams(ctx, gammtypes.NewParams(sdk.Coins{sdk.NewInt64Coin("uosmo", 1)})) // 1 uOSMO
 
 		Prop12(ctx, keepers.BankKeeper, keepers.DistrKeeper)
 
diff --git a/app/upgrades/v9/prop214.go b/app/upgrades/v9/prop214.go
index 769b2cc77..7458c9ede 100644
--- a/app/upgrades/v9/prop214.go
+++ b/app/upgrades/v9/prop214.go
@@ -25,8 +25,9 @@ func ExecuteProp214(ctx sdk.Context, gamm *gammkeeper.Keeper) {
 
 	balancerPool.PoolParams.SwapFee = sdk.MustNewDecFromStr("0.002")
 
-	err = gamm.SetPool(ctx, balancerPool)
-	if err != nil {
-		panic(err)
-	}
+	// Kept as comments for recordkeeping. SetPool is now private:
+	// 		err = gamm.SetPool(ctx, balancerPool)
+	// 		if err != nil {
+	//	 		panic(err)
+	//  	}
 }
diff --git a/osmomath/math.go b/osmomath/math.go
index def0f5014..d8f341bb6 100644
--- a/osmomath/math.go
+++ b/osmomath/math.go
@@ -84,6 +84,10 @@ func Pow(base sdk.Dec, exp sdk.Dec) sdk.Dec {
 // Contract: 0 < base <= 2
 // 0 <= exp < 1.
 func PowApprox(base sdk.Dec, exp sdk.Dec, precision sdk.Dec) sdk.Dec {
+	if !base.IsPositive() {
+		panic(fmt.Errorf("base must be greater than 0"))
+	}
+
 	if exp.IsZero() {
 		return sdk.OneDec()
 	}
diff --git a/scripts/replace_import_paths.sh b/scripts/replace_import_paths.sh
new file mode 100755
index 000000000..7211bfb55
--- /dev/null
+++ b/scripts/replace_import_paths.sh
@@ -0,0 +1,46 @@
+#!/bin/bash
+
+set -euo pipefail
+
+NEXT_MAJOR_VERSION=$1
+import_path_to_replace=$(go list -m)
+
+version_to_replace=$(echo $import_path_to_replace | sed 's/g.*v//') 
+
+echo Current import paths are $version_to_replace, replacing with $NEXT_MAJOR_VERSION
+
+# list all folders containing Go modules.
+modules=$(go list ./... | sed "s/g.*v${version_to_replace}\///")
+
+replace_paths() {
+    file="${1}"
+    sed -i "s/github.com\/osmosis-labs\/osmosis\/v${version_to_replace}/github.com\/osmosis-labs\/osmosis\/v${NEXT_MAJOR_VERSION}/g" ${file}
+}
+
+echo "Replacing import paths in Go files"
+for mod in $modules;
+do
+    for file in $mod/*; do
+        if [ -f "${file}" ]; then
+            replace_paths $file
+        fi
+    done
+done
+
+echo "Replacing import paths in proto files"
+for file in $(find proto/osmosis -type f -name "*.proto"); do
+    replace_paths $file
+done
+
+# protocgen.sh
+replace_paths "scripts/protocgen.sh"
+
+echo "Updating go.mod and vendoring"
+# go.mod
+replace_paths "go.mod"
+go mod vendor >/dev/null
+
+echo "running make proto-gen"
+# ensure protos match generated Go files
+# N.B.: This must be run after go mod vendor.
+make proto-gen >/dev/null
diff --git a/simulation/executor/event_stats.go b/simulation/executor/event_stats.go
index cd2d01a06..8b3f06e9b 100644
--- a/simulation/executor/event_stats.go
+++ b/simulation/executor/event_stats.go
@@ -48,7 +48,7 @@ func (es EventStats) ExportJSON(path string) {
 		panic(err)
 	}
 
-	err = ioutil.WriteFile(path, bz, 0600)
+	err = ioutil.WriteFile(path, bz, 0o600)
 	if err != nil {
 		panic(err)
 	}
diff --git a/simulation/executor/expected_keepers.go b/simulation/executor/expected_keepers.go
deleted file mode 100644
index c54831b8a..000000000
--- a/simulation/executor/expected_keepers.go
+++ /dev/null
@@ -1,16 +0,0 @@
-package simulation
-
-import (
-	sdk "github.com/cosmos/cosmos-sdk/types"
-	"github.com/cosmos/cosmos-sdk/x/auth/types"
-)
-
-// AccountKeeper defines the expected account keeper used for simulations (noalias)
-type AccountKeeper interface {
-	GetAccount(ctx sdk.Context, addr sdk.AccAddress) types.AccountI
-}
-
-// BankKeeper defines the expected interface needed to retrieve account balances.
-type BankKeeper interface {
-	SpendableCoins(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins
-}
diff --git a/simulation/executor/log.go b/simulation/executor/log.go
index df563cc18..d429497a4 100644
--- a/simulation/executor/log.go
+++ b/simulation/executor/log.go
@@ -44,7 +44,6 @@ func (lw *StandardLogWriter) PrintLogs() {
 	for i := 0; i < len(lw.OpEntries); i++ {
 		writeEntry := fmt.Sprintf("%s\n", (lw.OpEntries[i]).MustMarshal())
 		_, err := f.WriteString(writeEntry)
-
 		if err != nil {
 			panic("Failed to write logs to file")
 		}
diff --git a/simulation/executor/mock_tendermint.go b/simulation/executor/mock_tendermint.go
index e4f096db1..e840c39c1 100644
--- a/simulation/executor/mock_tendermint.go
+++ b/simulation/executor/mock_tendermint.go
@@ -126,18 +126,33 @@ func updateValidators(
 func RandomRequestBeginBlock(r *rand.Rand, params Params,
 	validators mockValidators, pastTimes []time.Time,
 	pastVoteInfos [][]abci.VoteInfo,
-	event func(route, op, evResult string), header tmproto.Header) abci.RequestBeginBlock {
+	event func(route, op, evResult string), header tmproto.Header,
+) abci.RequestBeginBlock {
 	if len(validators) == 0 {
 		return abci.RequestBeginBlock{
 			Header: header,
 		}
 	}
 
+	voteInfos := randomVoteInfos(r, params, validators, event)
+	evidence := randomDoubleSignEvidence(r, params, validators, pastTimes, pastVoteInfos, event, header, voteInfos)
+
+	return abci.RequestBeginBlock{
+		Header: header,
+		LastCommitInfo: abci.LastCommitInfo{
+			Votes: voteInfos,
+		},
+		ByzantineValidators: evidence,
+	}
+}
+
+func randomVoteInfos(r *rand.Rand, simParams Params, validators mockValidators, event func(route, op, evResult string),
+) []abci.VoteInfo {
 	voteInfos := make([]abci.VoteInfo, len(validators))
 
 	for i, key := range validators.getKeys() {
 		mVal := validators[key]
-		mVal.livenessState = params.LivenessTransitionMatrix().NextState(r, mVal.livenessState)
+		mVal.livenessState = simParams.LivenessTransitionMatrix().NextState(r, mVal.livenessState)
 		signed := true
 
 		if mVal.livenessState == 1 {
@@ -170,18 +185,19 @@ func RandomRequestBeginBlock(r *rand.Rand, params Params,
 		}
 	}
 
+	return voteInfos
+}
+
+func randomDoubleSignEvidence(r *rand.Rand, params Params,
+	validators mockValidators, pastTimes []time.Time,
+	pastVoteInfos [][]abci.VoteInfo,
+	event func(route, op, evResult string), header tmproto.Header, voteInfos []abci.VoteInfo) []abci.Evidence {
+	evidence := []abci.Evidence{}
 	// return if no past times
 	if len(pastTimes) == 0 {
-		return abci.RequestBeginBlock{
-			Header: header,
-			LastCommitInfo: abci.LastCommitInfo{
-				Votes: voteInfos,
-			},
-		}
+		return evidence
 	}
 
-	// TODO: Determine capacity before allocation
-	evidence := make([]abci.Evidence, 0)
 	// TODO: Change this to be markov based & clean this up
 	for r.Float64() < params.EvidenceFraction() {
 		height := header.Height
@@ -214,12 +230,5 @@ func RandomRequestBeginBlock(r *rand.Rand, params Params,
 
 		event("begin_block", "evidence", "ok")
 	}
-
-	return abci.RequestBeginBlock{
-		Header: header,
-		LastCommitInfo: abci.LastCommitInfo{
-			Votes: voteInfos,
-		},
-		ByzantineValidators: evidence,
-	}
+	return evidence
 }
diff --git a/simulation/executor/operation.go b/simulation/executor/operation.go
index 38a018a61..fcc301352 100644
--- a/simulation/executor/operation.go
+++ b/simulation/executor/operation.go
@@ -1,14 +1,14 @@
 package simulation
 
+// TODO: Figure out how to delete everything in this file OR migrate to improved logging concepts
+
 import (
 	"encoding/json"
 	"math/rand"
-	"sort"
 
 	"github.com/cosmos/cosmos-sdk/types/simulation"
 
 	simtypes "github.com/osmosis-labs/osmosis/v7/simulation/types"
-	// simtypes "github.com/osmosis-labs/osmosis/simulation/types"
 )
 
 // entry kinds for use within OperationEntry
@@ -77,37 +77,21 @@ func NewOperationQueue() OperationQueue {
 
 // queueOperations adds all future operations into the operation queue.
 // TODO: Change FutureOperation to FutureAction
-func queueOperations(queuedOps OperationQueue, queuedTimeOps []simulation.FutureOperation, futureOps []simulation.FutureOperation) {
-	if futureOps == nil {
-		return
-	}
-
+func (simState *simState) queueOperations(futureOps []simulation.FutureOperation) {
 	for _, futureOp := range futureOps {
 		futureOp := futureOp
 		if futureOp.BlockHeight != 0 {
-			if val, ok := queuedOps[futureOp.BlockHeight]; ok {
-				queuedOps[futureOp.BlockHeight] = append(val, futureOp.Op)
+			if val, ok := simState.operationQueue[futureOp.BlockHeight]; ok {
+				simState.operationQueue[futureOp.BlockHeight] = append(val, futureOp.Op)
 			} else {
-				queuedOps[futureOp.BlockHeight] = []simulation.Operation{futureOp.Op}
+				simState.operationQueue[futureOp.BlockHeight] = []simulation.Operation{futureOp.Op}
 			}
 
 			continue
 		}
-
-		// TODO: Replace with proper sorted data structure, so don't have the
-		// copy entire slice
-		index := sort.Search(
-			len(queuedTimeOps),
-			func(i int) bool {
-				return queuedTimeOps[i].BlockTime.After(futureOp.BlockTime)
-			},
-		)
-
-		queuedTimeOps = append(queuedTimeOps, simulation.FutureOperation{})
-		copy(queuedTimeOps[index+1:], queuedTimeOps[index:])
-		queuedTimeOps[index] = futureOp
 	}
 }
+
 func totalWeight(actions []simtypes.Action) int {
 	totalWeight := 0
 	for _, action := range actions {
diff --git a/simulation/executor/params.go b/simulation/executor/params.go
index ccf226334..19a21f9fe 100644
--- a/simulation/executor/params.go
+++ b/simulation/executor/params.go
@@ -89,69 +89,6 @@ func RandomParams(r *rand.Rand) Params {
 	}
 }
 
-// Param change proposals
-
-// ParamChange defines the object used for simulating parameter change proposals
-type ParamChange struct {
-	subspace string
-	key      string
-	simValue simulation.SimValFn
-}
-
-func (spc ParamChange) Subspace() string {
-	return spc.subspace
-}
-
-func (spc ParamChange) Key() string {
-	return spc.key
-}
-
-func (spc ParamChange) SimValue() simulation.SimValFn {
-	return spc.simValue
-}
-
-// NewSimParamChange creates a new ParamChange instance
-func NewSimParamChange(subspace, key string, simVal simulation.SimValFn) simulation.ParamChange {
-	return ParamChange{
-		subspace: subspace,
-		key:      key,
-		simValue: simVal,
-	}
-}
-
-// ComposedKey creates a new composed key for the param change proposal
-func (spc ParamChange) ComposedKey() string {
-	return spc.Subspace() + "/" + spc.Key()
-}
-
-// Proposal Contents
-
-// WeightedProposalContent defines a common struct for proposal contents defined by
-// external modules (i.e outside gov)
-type WeightedProposalContent struct {
-	appParamsKey       string                        // key used to retrieve the value of the weight from the simulation application params
-	defaultWeight      int                           // default weight
-	contentSimulatorFn simulation.ContentSimulatorFn // content simulator function
-}
-
-func NewWeightedProposalContent(appParamsKey string, defaultWeight int, contentSimulatorFn simulation.ContentSimulatorFn) simulation.WeightedProposalContent {
-	return &WeightedProposalContent{appParamsKey: appParamsKey, defaultWeight: defaultWeight, contentSimulatorFn: contentSimulatorFn}
-}
-
-func (w WeightedProposalContent) AppParamsKey() string {
-	return w.appParamsKey
-}
-
-func (w WeightedProposalContent) DefaultWeight() int {
-	return w.defaultWeight
-}
-
-func (w WeightedProposalContent) ContentSimulatorFn() simulation.ContentSimulatorFn {
-	return w.contentSimulatorFn
-}
-
-// Param change proposals
-
 // randomConsensusParams returns random simulation consensus parameters, it extracts the Evidence from the Staking genesis state.
 func randomConsensusParams(r *rand.Rand, appState json.RawMessage, cdc codec.JSONCodec) *abci.ConsensusParams {
 	var genesisState map[string]json.RawMessage
diff --git a/simulation/executor/simulate.go b/simulation/executor/simulate.go
index 13f2b932a..527d87909 100644
--- a/simulation/executor/simulate.go
+++ b/simulation/executor/simulate.go
@@ -31,11 +31,11 @@ func initChain(
 	accounts []simulation.Account,
 	app simtypes.App,
 	appStateFn simulation.AppStateFn,
-	config simulation.Config,
+	config *simulation.Config,
 	cdc codec.JSONCodec,
-) (mockValidators, time.Time, []simulation.Account, string) {
+) (mockValidators, time.Time, []simulation.Account) {
 	// TODO: Cleanup the whole config dependency with appStateFn
-	appState, accounts, chainID, genesisTimestamp := appStateFn(r, accounts, config)
+	appState, accounts, chainID, genesisTimestamp := appStateFn(r, accounts, *config)
 	consensusParams := randomConsensusParams(r, appState, cdc)
 	req := abci.RequestInitChain{
 		AppStateBytes:   appState,
@@ -48,7 +48,13 @@ func initChain(
 	res := app.GetBaseApp().InitChain(req)
 	validators := newMockValidators(r, res.Validators, params)
 
-	return validators, genesisTimestamp, accounts, chainID
+	// update config
+	config.ChainID = chainID
+	if config.InitialBlockHeight == 0 {
+		config.InitialBlockHeight = 1
+	}
+
+	return validators, genesisTimestamp, accounts
 }
 
 // SimulateFromSeedLegacy tests an application by running the provided
@@ -79,6 +85,8 @@ func initChain(
 // * SimManager for module configs
 // * Config file for params
 // * whatever is needed for logging (tb + w rn)
+// OR: Could be a struct or something with options,
+//     to give caller ability to step through / instrument benchmarking if they wanted to, and add a cleanup function.
 func SimulateFromSeed(
 	tb testing.TB,
 	w io.Writer,
@@ -87,43 +95,16 @@ func SimulateFromSeed(
 	actions []simtypes.Action,
 	config simulation.Config,
 	cdc codec.JSONCodec,
-) (stopEarly bool, exportedParams Params, err error) {
+) (stopEarly bool, err error) {
 	// in case we have to end early, don't os.Exit so that we can run cleanup code.
-	testingMode, _, b := getTestingMode(tb)
-
-	fmt.Fprintf(w, "Starting SimulateFromSeed with randomness created with seed %d\n", int(config.Seed))
-	r := rand.New(rand.NewSource(config.Seed))
-	simParams := RandomParams(r)
-	fmt.Fprintf(w, "Randomized simulation params: \n%s\n", mustMarshalJSONIndent(simParams))
-
-	accs := initFunctions.RandomAccountFn(r, simParams.NumKeys())
-	if len(accs) == 0 {
-		return true, simParams, fmt.Errorf("must have greater than zero genesis accounts")
-	}
-
-	validators, genesisTimestamp, accs, chainID := initChain(r, simParams, accs, app, initFunctions.AppInitialStateFn, config, cdc)
-
-	config.ChainID = chainID
-	if config.InitialBlockHeight == 0 {
-		config.InitialBlockHeight = 1
-	}
-
-	fmt.Printf(
-		"Starting the simulation from time %v (unixtime %v)\n",
-		genesisTimestamp.UTC().Format(time.UnixDate), genesisTimestamp.Unix(),
-	)
+	// TODO: Understand exit pattern, this is so screwed up. Then delete ^
 
-	initialHeader := tmproto.Header{
-		ChainID:         chainID,
-		Height:          int64(config.InitialBlockHeight),
-		Time:            genesisTimestamp,
-		ProposerAddress: validators.randomProposer(r),
+	// Encapsulate the bizarre initialization logic that must be cleaned.
+	simCtx, simState, simParams, err := cursedInitializationLogic(tb, w, app, initFunctions, &config, cdc)
+	if err != nil {
+		return true, err
 	}
 
-	simState := newSimulatorState(simParams, initialHeader, tb, w, validators).WithLogParam(config.Lean)
-
-	simCtx := simtypes.NewSimCtx(r, app, accs, simState.header.ChainID)
-
 	// Setup code to catch SIGTERM's
 	c := make(chan os.Signal, 1)
 	signal.Notify(c, os.Interrupt, syscall.SIGTERM, syscall.SIGINT)
@@ -135,6 +116,7 @@ func SimulateFromSeed(
 		stopEarly = true
 	}()
 
+	testingMode, _, b := getTestingMode(tb)
 	blockSimulator := createBlockSimulator(testingMode, w, simParams, actions, simState, config)
 
 	if !testingMode {
@@ -152,33 +134,56 @@ func SimulateFromSeed(
 		}()
 	}
 
-	// set exported params to the initial state
-	if config.ExportParamsPath != "" && config.ExportParamsHeight == 0 {
-		exportedParams = simParams
-	}
+	stopEarly = simState.SimulateAllBlocks(w, simCtx, blockSimulator, config)
 
-	for height := config.InitialBlockHeight; height < config.NumBlocks+config.InitialBlockHeight && !stopEarly; height++ {
-		stopEarly = simState.SimulateBlock(simCtx, blockSimulator)
-		if stopEarly {
-			break
-		}
+	simState.eventStats.exportEvents(config.ExportStatsPath, w)
+	return stopEarly, nil
+}
 
-		if config.Commit {
-			simCtx.App.GetBaseApp().Commit()
-		}
+// The goal of this function is to group the extremely badly abstracted genesis logic,
+// into a single function we can target continuing to improve / abstract better.
+// It outputs SimCtx and SimState which are "cleaner" interface abstractions for the rest of the simulator.
+// It also outputs SimParams which is not great.
+// It also can modify config.
+func cursedInitializationLogic(
+	tb testing.TB,
+	w io.Writer,
+	app simtypes.App,
+	initFunctions simtypes.InitFunctions,
+	config *simulation.Config,
+	cdc codec.JSONCodec) (*simtypes.SimCtx, *simState, Params, error) {
+	fmt.Fprintf(w, "Starting SimulateFromSeed with randomness created with seed %d\n", int(config.Seed))
+
+	r := rand.New(rand.NewSource(config.Seed))
+	simParams := RandomParams(r)
+	fmt.Fprintf(w, "Randomized simulation params: \n%s\n", mustMarshalJSONIndent(simParams))
+
+	accs := initFunctions.RandomAccountFn(r, simParams.NumKeys())
+	if len(accs) == 0 {
+		return nil, nil, simParams, fmt.Errorf("must have greater than zero genesis accounts")
 	}
 
-	if !stopEarly {
-		fmt.Fprintf(
-			w,
-			"\nSimulation complete; Final height (blocks): %d, final time (seconds): %v, operations ran: %d\n",
-			simState.header.Height, simState.header.Time, simState.opCount,
-		)
-		simState.logWriter.PrintLogs()
+	validators, genesisTimestamp, accs := initChain(r, simParams, accs, app, initFunctions.AppInitialStateFn, config, cdc)
+
+	fmt.Printf(
+		"Starting the simulation from time %v (unixtime %v)\n",
+		genesisTimestamp.UTC().Format(time.UnixDate), genesisTimestamp.Unix(),
+	)
+
+	simCtx := simtypes.NewSimCtx(r, app, accs, config.ChainID)
+
+	initialHeader := tmproto.Header{
+		ChainID:         config.ChainID,
+		Height:          int64(config.InitialBlockHeight),
+		Time:            genesisTimestamp,
+		ProposerAddress: validators.randomProposer(r),
 	}
 
-	simState.eventStats.exportEvents(config.ExportStatsPath, w)
-	return stopEarly, exportedParams, nil
+	simState := newSimulatorState(simParams, initialHeader, tb, w, validators).WithLogParam(config.Lean)
+
+	// TODO: If simulation has a param export path configured, export params here.
+
+	return simCtx, simState, simParams, nil
 }
 
 //nolint:deadcode,unused
@@ -205,7 +210,8 @@ type blockSimFn func(simCtx *simtypes.SimCtx, ctx sdk.Context, header tmproto.He
 // Returns a function to simulate blocks. Written like this to avoid constant
 // parameters being passed everytime, to minimize memory overhead.
 func createBlockSimulator(testingMode bool, w io.Writer, params Params, actions []simtypes.Action,
-	simState *simState, config simulation.Config) blockSimFn {
+	simState *simState, config simulation.Config,
+) blockSimFn {
 	lastBlockSizeState := 0 // state for [4 * uniform distribution]
 	blocksize := 0
 	selectAction := getSelectActionFn(actions)
@@ -214,50 +220,54 @@ func createBlockSimulator(testingMode bool, w io.Writer, params Params, actions
 		simCtx *simtypes.SimCtx, ctx sdk.Context, header tmproto.Header,
 	) (opCount int) {
 		_, _ = fmt.Fprintf(
-			w, "\rSimulating... block %d/%d, operation %d/%d.",
-			header.Height, config.NumBlocks, opCount, blocksize,
+			w, "\rSimulating... block %d/%d, operation 0/%d.",
+			header.Height, config.NumBlocks, blocksize,
 		)
 		lastBlockSizeState, blocksize = getBlockSize(simCtx, params, lastBlockSizeState, config.BlockSize)
 
-		// TODO: Fix according to the r plans
-		// Predetermine the blocksize slice so that we can do things like block
-		// out certain operations without changing the ops that follow.
-		// NOTE: This is poor mans seeding, it will improve in our simctx plans =)
-		blockActions := make([]simtypes.Action, 0, blocksize)
+		blockNumStr := fmt.Sprintf("block %d", header.Height)
 		for i := 0; i < blocksize; i++ {
-			blockActions = append(blockActions, selectAction(simCtx.GetRand()))
-		}
+			// Sample and execute every action using independent randomness.
+			// Thus any change within one action's randomness won't waterfall
+			// to every other action and the overall order of txs.
+			// We can also use this to limit which operations we run, in debugging a simulator run.
+			actionSeed := fmt.Sprintf("%s operation %d", blockNumStr, i)
+			actionSimCtx, cleanup := simCtx.WrapRand(actionSeed)
 
-		for i := 0; i < blocksize; i++ {
-			action := blockActions[i]
-			// TODO: We need to make a simCtx.WithSeededRand, that replaces the rand map internally
-			// but allows updates to accounts.
-			opMsg, futureOps, err := action.Execute(simCtx, ctx)
-			opMsg.LogEvent(simState.eventStats.Tally)
-
-			if !simState.leanLogs || opMsg.OK {
-				simState.logWriter.AddEntry(MsgEntry(header.Height, int64(i), opMsg))
-			}
+			// Select and execute tx
+			action := selectAction(actionSimCtx.GetSeededRand("action select"))
+			opMsg, futureOps, err := action.Execute(actionSimCtx, ctx)
+			cleanup()
 
-			if err != nil {
-				simState.logWriter.PrintLogs()
-				simState.tb.Fatalf(`error on block  %d/%d, operation (%d/%d) from x/%s:
-%v
-Comment: %s`,
-					header.Height, config.NumBlocks, opCount, blocksize, opMsg.Route, err, opMsg.Comment)
-			}
+			simState.logActionResult(header, i, config, blocksize, opMsg, err)
 
-			queueOperations(simState.operationQueue, simState.timeOperationQueue, futureOps)
+			simState.queueOperations(futureOps)
 
-			if testingMode && opCount%50 == 0 {
+			if testingMode && i%50 == 0 {
 				fmt.Fprintf(w, "\rSimulating... block %d/%d, operation %d/%d. ",
-					header.Height, config.NumBlocks, opCount, blocksize)
+					header.Height, config.NumBlocks, i, blocksize)
 			}
-
-			opCount++
 		}
 
-		return opCount
+		return blocksize
+	}
+}
+
+// This is inheriting old functionality. We should break this as part of making logging be usable / make sense.
+func (simState *simState) logActionResult(
+	header tmproto.Header, actionIndex int, config simulation.Config, blocksize int,
+	opMsg simulation.OperationMsg, actionErr error) {
+	opMsg.LogEvent(simState.eventStats.Tally)
+	if !simState.leanLogs || opMsg.OK {
+		simState.logWriter.AddEntry(MsgEntry(header.Height, int64(actionIndex), opMsg))
+	}
+
+	if actionErr != nil {
+		simState.logWriter.PrintLogs()
+		simState.tb.Fatalf(`error on block  %d/%d, operation (%d/%d) from x/%s:
+%v
+Comment: %s`,
+			header.Height, config.NumBlocks, actionIndex, blocksize, opMsg.Route, actionErr, opMsg.Comment)
 	}
 }
 
@@ -277,7 +287,7 @@ func (simState *simState) runQueuedOperations(simCtx *simtypes.SimCtx, ctx sdk.C
 		// For now, queued operations cannot queue more operations.
 		// If a need arises for us to support queued messages to queue more messages, this can
 		// be changed.
-		opMsg, _, err := queuedOp[i](r, simCtx.App.GetBaseApp(), ctx, simCtx.Accounts, simCtx.ChainID)
+		opMsg, _, err := queuedOp[i](r, simCtx.BaseApp(), ctx, simCtx.Accounts, simCtx.ChainID())
 		opMsg.LogEvent(simState.eventStats.Tally)
 
 		if !simState.leanLogs || opMsg.OK {
@@ -286,6 +296,10 @@ func (simState *simState) runQueuedOperations(simCtx *simtypes.SimCtx, ctx sdk.C
 
 		if err != nil {
 			simState.logWriter.PrintLogs()
+			simState.tb.Fatalf(`error on block  %d, height queued operation (%d/%d) from x/%s:
+%v
+Comment: %s`,
+				simState.header.Height, i, numOpsRan, opMsg.Route, err, opMsg.Comment)
 			simState.tb.FailNow()
 		}
 	}
@@ -293,34 +307,3 @@ func (simState *simState) runQueuedOperations(simCtx *simtypes.SimCtx, ctx sdk.C
 
 	return numOpsRan
 }
-
-func (simState *simState) runQueuedTimeOperations(simCtx *simtypes.SimCtx, ctx sdk.Context) (
-	numOpsRan int) {
-	queueOps := simState.timeOperationQueue
-	currentTime := simState.header.Time
-	numOpsRan = 0
-	for len(queueOps) > 0 && currentTime.After(queueOps[0].BlockTime) {
-		// TODO: Fix according to the r plans
-		r := simCtx.GetRand()
-
-		// For now, queued operations cannot queue more operations.
-		// If a need arises for us to support queued messages to queue more messages, this can
-		// be changed.
-		opMsg, _, err := queueOps[0].Op(r, simCtx.App.GetBaseApp(), ctx, simCtx.Accounts, simCtx.ChainID)
-		opMsg.LogEvent(simState.eventStats.Tally)
-
-		if !simState.leanLogs || opMsg.OK {
-			simState.logWriter.AddEntry(QueuedMsgEntry(simState.header.Height, opMsg))
-		}
-
-		if err != nil {
-			simState.logWriter.PrintLogs()
-			simState.tb.FailNow()
-		}
-
-		queueOps = queueOps[1:]
-		numOpsRan++
-	}
-	simState.timeOperationQueue = queueOps
-	return numOpsRan
-}
diff --git a/simulation/executor/simulate_dev.go b/simulation/executor/simulate_dev.go
index 8f14b7da0..20ab9bf4d 100644
--- a/simulation/executor/simulate_dev.go
+++ b/simulation/executor/simulate_dev.go
@@ -20,8 +20,7 @@ type simState struct {
 
 	// These are operations which have been queued by previous operations
 	// TODO: Replace with new action syntax
-	operationQueue     map[int][]simulation.Operation
-	timeOperationQueue []simulation.FutureOperation
+	operationQueue map[int][]simulation.Operation
 
 	curValidators  mockValidators
 	nextValidators mockValidators
@@ -49,19 +48,18 @@ type simState struct {
 
 func newSimulatorState(simParams Params, initialHeader tmproto.Header, tb testing.TB, w io.Writer, validators mockValidators) *simState {
 	return &simState{
-		simParams:          simParams,
-		header:             initialHeader,
-		operationQueue:     NewOperationQueue(),
-		timeOperationQueue: []simulation.FutureOperation{},
-		curValidators:      validators.Clone(),
-		nextValidators:     validators.Clone(),
-		tb:                 tb,
-		pastTimes:          []time.Time{},
-		pastVoteInfos:      [][]abci.VoteInfo{},
-		logWriter:          NewLogWriter(tb),
-		w:                  w,
-		eventStats:         NewEventStats(),
-		opCount:            0,
+		simParams:      simParams,
+		header:         initialHeader,
+		operationQueue: NewOperationQueue(),
+		curValidators:  validators.Clone(),
+		nextValidators: validators.Clone(),
+		tb:             tb,
+		pastTimes:      []time.Time{},
+		pastVoteInfos:  [][]abci.VoteInfo{},
+		logWriter:      NewLogWriter(tb),
+		w:              w,
+		eventStats:     NewEventStats(),
+		opCount:        0,
 	}
 }
 
@@ -70,6 +68,34 @@ func (simState *simState) WithLogParam(leanLogs bool) *simState {
 	return simState
 }
 
+func (simState *simState) SimulateAllBlocks(
+	w io.Writer,
+	simCtx *simtypes.SimCtx,
+	blockSimulator blockSimFn,
+	config simulation.Config) (stopEarly bool) {
+	stopEarly = false
+	for height := config.InitialBlockHeight; height < config.NumBlocks+config.InitialBlockHeight && !stopEarly; height++ {
+		stopEarly = simState.SimulateBlock(simCtx, blockSimulator)
+		if stopEarly {
+			break
+		}
+
+		if config.Commit {
+			simCtx.BaseApp().Commit()
+		}
+	}
+
+	if !stopEarly {
+		fmt.Fprintf(
+			w,
+			"\nSimulation complete; Final height (blocks): %d, final time (seconds): %v, operations ran: %d\n",
+			simState.header.Height, simState.header.Time, simState.opCount,
+		)
+		simState.logWriter.PrintLogs()
+	}
+	return stopEarly
+}
+
 // simulate a block, update state
 func (simState *simState) SimulateBlock(simCtx *simtypes.SimCtx, blockSimulator blockSimFn) (stopEarly bool) {
 	if simState.header.ProposerAddress == nil {
@@ -78,16 +104,16 @@ func (simState *simState) SimulateBlock(simCtx *simtypes.SimCtx, blockSimulator
 	}
 
 	requestBeginBlock := simState.beginBlock(simCtx)
-	ctx := simCtx.App.GetBaseApp().NewContext(false, simState.header)
+	ctx := simCtx.BaseApp().NewContext(false, simState.header)
 
 	// Run queued operations. Ignores blocksize if blocksize is too small
 	numQueuedOpsRan := simState.runQueuedOperations(simCtx, ctx)
-	numQueuedTimeOpsRan := simState.runQueuedTimeOperations(simCtx, ctx)
+	// numQueuedTimeOpsRan := simState.runQueuedTimeOperations(simCtx, ctx)
 
 	// run standard operations
 	// TODO: rename blockSimulator arg
 	operations := blockSimulator(simCtx, ctx, simState.header)
-	simState.opCount += operations + numQueuedOpsRan + numQueuedTimeOpsRan
+	simState.opCount += operations + numQueuedOpsRan // + numQueuedTimeOpsRan
 
 	responseEndBlock := simState.endBlock(simCtx)
 
@@ -101,12 +127,12 @@ func (simState *simState) beginBlock(simCtx *simtypes.SimCtx) abci.RequestBeginB
 	requestBeginBlock := RandomRequestBeginBlock(simCtx.GetRand(), simState.simParams, simState.curValidators, simState.pastTimes, simState.pastVoteInfos, simState.eventStats.Tally, simState.header)
 	// Run the BeginBlock handler
 	simState.logWriter.AddEntry(BeginBlockEntry(simState.header.Height))
-	simCtx.App.GetBaseApp().BeginBlock(requestBeginBlock)
+	simCtx.BaseApp().BeginBlock(requestBeginBlock)
 	return requestBeginBlock
 }
 
 func (simState *simState) endBlock(simCtx *simtypes.SimCtx) abci.ResponseEndBlock {
-	res := simCtx.App.GetBaseApp().EndBlock(abci.RequestEndBlock{})
+	res := simCtx.BaseApp().EndBlock(abci.RequestEndBlock{})
 	simState.logWriter.AddEntry(EndBlockEntry(simState.header.Height))
 	return res
 }
diff --git a/simulation/executor/util.go b/simulation/executor/util.go
index e21849d4d..f15a9b5aa 100644
--- a/simulation/executor/util.go
+++ b/simulation/executor/util.go
@@ -3,15 +3,8 @@ package simulation
 import (
 	"encoding/json"
 	"fmt"
-	"math/rand"
 	"testing"
 
-	"github.com/cosmos/cosmos-sdk/baseapp"
-	"github.com/cosmos/cosmos-sdk/client"
-	"github.com/cosmos/cosmos-sdk/codec"
-	sdk "github.com/cosmos/cosmos-sdk/types"
-	simulation "github.com/cosmos/cosmos-sdk/types/simulation"
-
 	simtypes "github.com/osmosis-labs/osmosis/v7/simulation/types"
 )
 
@@ -63,19 +56,3 @@ func mustMarshalJSONIndent(o interface{}) []byte {
 
 	return bz
 }
-
-// OperationInput is a struct that holds all the needed values to generate a tx and deliver it
-type OperationInput struct {
-	R               *rand.Rand
-	App             *baseapp.BaseApp
-	TxGen           client.TxConfig
-	Cdc             *codec.ProtoCodec
-	Msg             sdk.Msg
-	MsgType         string
-	CoinsSpentInMsg sdk.Coins
-	Context         sdk.Context
-	SimAccount      simulation.Account
-	AccountKeeper   AccountKeeper
-	Bankkeeper      BankKeeper
-	ModuleName      string
-}
diff --git a/simulation/types/account.go b/simulation/types/account.go
index dcde70d08..670c345f1 100644
--- a/simulation/types/account.go
+++ b/simulation/types/account.go
@@ -65,7 +65,7 @@ func (sim *SimCtx) FindAccount(address sdk.Address) (simulation.Account, bool) {
 
 func (sim *SimCtx) RandomSimAccountWithBalance(ctx sdk.Context) (simulation.Account, error) {
 	accHasBal := func(acc simulation.Account) bool {
-		return len(sim.App.GetBankKeeper().SpendableCoins(ctx, acc.Address)) != 0
+		return len(sim.BankKeeper().SpendableCoins(ctx, acc.Address)) != 0
 	}
 	acc, found := sim.RandomSimAccountWithConstraint(accHasBal)
 	if !found {
@@ -80,7 +80,7 @@ func (sim *SimCtx) RandomSimAccountWithBalance(ctx sdk.Context) (simulation.Acco
 func (sim *SimCtx) SelAddrWithDenoms(ctx sdk.Context, denoms []string) (simulation.Account, sdk.Coins, bool) {
 	accHasDenoms := func(acc simulation.Account) bool {
 		for _, denom := range denoms {
-			if sim.App.GetBankKeeper().GetBalance(ctx, acc.Address, denom).Amount.IsZero() {
+			if sim.BankKeeper().GetBalance(ctx, acc.Address, denom).Amount.IsZero() {
 				return false
 			}
 		}
@@ -100,7 +100,7 @@ func (sim *SimCtx) SelAddrWithDenoms(ctx sdk.Context, denoms []string) (simulati
 // (Meaning that on average it samples 10% of the chosen balance)
 // Pre-condition: Addr must have a spendable balance
 func (sim *SimCtx) RandExponentialCoin(ctx sdk.Context, addr sdk.AccAddress) sdk.Coin {
-	balances := sim.App.GetBankKeeper().SpendableCoins(ctx, addr)
+	balances := sim.BankKeeper().SpendableCoins(ctx, addr)
 	if len(balances) == 0 {
 		panic("precondition for RandExponentialCoin broken: Addr has 0 spendable balance")
 	}
@@ -124,7 +124,7 @@ func (sim *SimCtx) RandExponentialCoin(ctx sdk.Context, addr sdk.AccAddress) sdk
 func (sim *SimCtx) RandCoinSubset(ctx sdk.Context, addr sdk.AccAddress, denoms []string) sdk.Coins {
 	subsetCoins := sdk.Coins{}
 	for _, denom := range denoms {
-		bal := sim.App.GetBankKeeper().GetBalance(ctx, addr, denom)
+		bal := sim.BankKeeper().GetBalance(ctx, addr, denom)
 		amt, err := sim.RandPositiveInt(bal.Amount)
 		if err != nil {
 			panic(err)
diff --git a/simulation/types/action.go b/simulation/types/action.go
index 64eaac5a9..0d1830556 100644
--- a/simulation/types/action.go
+++ b/simulation/types/action.go
@@ -28,20 +28,26 @@ type Action interface {
 }
 
 type weightedOperationAction struct {
-	op simulation.WeightedOperation
+	moduleName string
+	op         simulation.WeightedOperation
 }
 
-func (a weightedOperationAction) Name() string   { return "weighted_op" }
+func (a weightedOperationAction) Name() string   { return fmt.Sprintf("%s: weighted_op", a.moduleName) }
 func (a weightedOperationAction) Weight() Weight { return Weight(a.op.Weight()) }
 func (a weightedOperationAction) Execute(sim *SimCtx, ctx sdk.Context) (
-	simulation.OperationMsg, []simulation.FutureOperation, error) {
-	return a.op.Op()(sim.GetRand(), sim.App.GetBaseApp(), ctx, sim.Accounts, sim.ChainID)
+	simulation.OperationMsg, []simulation.FutureOperation, error,
+) {
+	return a.op.Op()(sim.GetRand(), sim.BaseApp(), ctx, sim.Accounts, sim.ChainID())
 }
 
 func ActionsFromWeightedOperations(ops legacysimexec.WeightedOperations) []Action {
+	return actionsFromWeightedOperations("no module name", ops)
+}
+
+func actionsFromWeightedOperations(moduleName string, ops legacysimexec.WeightedOperations) []Action {
 	actions := make([]Action, 0, len(ops))
 	for _, op := range ops {
-		actions = append(actions, weightedOperationAction{op: op})
+		actions = append(actions, weightedOperationAction{moduleName: moduleName, op: op})
 	}
 	return actions
 }
@@ -85,7 +91,8 @@ func (m msgBasedAction) WithWeight(weight Weight) msgBasedAction {
 func (m msgBasedAction) Name() string   { return m.name }
 func (m msgBasedAction) Weight() Weight { return m.weight }
 func (m msgBasedAction) Execute(sim *SimCtx, ctx sdk.Context) (
-	OperationMsg simulation.OperationMsg, futureOps []simulation.FutureOperation, err error) {
+	OperationMsg simulation.OperationMsg, futureOps []simulation.FutureOperation, err error,
+) {
 	msg, err := m.msgGenerator(sim, ctx)
 	if err != nil {
 		return simulation.NoOpMsg(m.name, m.name, fmt.Sprintf("unable to build msg due to: %v", err)), nil, nil
diff --git a/simulation/types/manager.go b/simulation/types/manager.go
index 063f693b6..335490fc5 100644
--- a/simulation/types/manager.go
+++ b/simulation/types/manager.go
@@ -19,15 +19,16 @@ import (
 type AppModuleSimulationV2 interface {
 	module.AppModule
 
-	// randomized genesis states
-	// TODO: Come back and improve SimulationState interface
-	// TODO: Move this to an extension interface
-	// default: simState.GenState[types.ModuleName] = app.DefaultGenesis(simState.Cdc)
-	GenerateGenesisState(*module.SimulationState, *SimCtx)
 	Actions() []Action
 	// PropertyTests()
 }
 
+type AppModuleSimulationV2WithRandGenesis interface {
+	AppModuleSimulationV2
+	// TODO: Come back and improve SimulationState interface
+	RandomGenesisState(*module.SimulationState, *SimCtx)
+}
+
 // SimulationManager defines a simulation manager that provides the high level utility
 // for managing and executing simulation functionalities for a group of modules
 type Manager struct {
@@ -100,13 +101,14 @@ func (m Manager) legacyActions(seed int64, cdc codec.JSONCodec) []Action {
 		}
 	}
 	// second pass generate actions
-	weightedOps := []simulation.WeightedOperation{}
+	actions := []Action{}
 	for _, moduleName := range m.moduleManager.OrderInitGenesis {
 		if simModule, ok := m.legacyModules[moduleName]; ok {
-			weightedOps = append(weightedOps, simModule.WeightedOperations(simState)...)
+			weightedOps := simModule.WeightedOperations(simState)
+			actions = append(actions, actionsFromWeightedOperations(moduleName, weightedOps)...)
 		}
 	}
-	return ActionsFromWeightedOperations(weightedOps)
+	return actions
 }
 
 // TODO: Can we use sim here instead? Perhaps by passing in the simulation module manager to the simulator.
@@ -137,7 +139,12 @@ func (m Manager) Actions(seed int64, cdc codec.JSONCodec) []Action {
 func (m Manager) GenerateGenesisStates(simState *module.SimulationState, sim *SimCtx) {
 	for _, moduleName := range m.moduleManager.OrderInitGenesis {
 		if simModule, ok := m.Modules[moduleName]; ok {
-			simModule.GenerateGenesisState(simState, sim)
+			// if we define a random genesis function use it, otherwise use default genesis
+			if mod, ok := simModule.(AppModuleSimulationV2WithRandGenesis); ok {
+				mod.RandomGenesisState(simState, sim)
+			} else {
+				simState.GenState[simModule.Name()] = simModule.DefaultGenesis(simState.Cdc)
+			}
 		}
 		if simModule, ok := m.legacyModules[moduleName]; ok {
 			simModule.GenerateGenesisState(simState)
diff --git a/simulation/types/random/sdkrand.go b/simulation/types/random/sdkrand.go
index a2ab78b86..89c950ef3 100644
--- a/simulation/types/random/sdkrand.go
+++ b/simulation/types/random/sdkrand.go
@@ -53,7 +53,7 @@ func RandPositiveInt(r *rand.Rand, max sdk.Int) (sdk.Int, error) {
 // RandomAmount generates a random amount
 // Note: The range of RandomAmount includes max, and is, in fact, biased to return max as well as 0.
 func RandomAmount(r *rand.Rand, max sdk.Int) sdk.Int {
-	var randInt = big.NewInt(0)
+	randInt := big.NewInt(0)
 
 	switch r.Intn(10) {
 	case 0:
@@ -70,7 +70,7 @@ func RandomAmount(r *rand.Rand, max sdk.Int) sdk.Int {
 // RandomDecAmount generates a random decimal amount
 // Note: The range of RandomDecAmount includes max, and is, in fact, biased to return max as well as 0.
 func RandomDecAmount(r *rand.Rand, max sdk.Dec) sdk.Dec {
-	var randInt = big.NewInt(0)
+	randInt := big.NewInt(0)
 
 	switch r.Intn(10) {
 	case 0:
diff --git a/simulation/types/simctx.go b/simulation/types/simctx.go
index b78267877..fb3b8c1ee 100644
--- a/simulation/types/simctx.go
+++ b/simulation/types/simctx.go
@@ -1,8 +1,12 @@
 package simulation
 
 import (
+	"crypto/sha256"
+	"encoding/binary"
+	"fmt"
 	"math/rand"
 
+	"github.com/cosmos/cosmos-sdk/baseapp"
 	sdk "github.com/cosmos/cosmos-sdk/types"
 
 	"github.com/cosmos/cosmos-sdk/codec"
@@ -12,44 +16,146 @@ import (
 //nolint:structcheck
 //TODO: Contemplate name better
 type SimCtx struct {
-	r *rand.Rand
-	// TODO: delete this, once we cleanup simulator initialization logic,
-	// and can then setup SimCtx with base seed.
-	internalSeed int64
-	rCounter     int64
-	seededMap    map[string]*rand.Rand
+	rm randManager
 
-	App      App
 	Accounts []simulation.Account
 	Cdc      codec.JSONCodec // application codec
-	ChainID  string
+
+	app     App
+	chainID string
 
 	txbuilder func(ctx sdk.Context, msg sdk.Msg, msgName string) (sdk.Tx, error)
 }
 
 func NewSimCtx(r *rand.Rand, app App, accounts []simulation.Account, chainID string) *SimCtx {
 	sim := &SimCtx{
-		r:            r,
-		internalSeed: r.Int63(),
-		rCounter:     0,
-		seededMap:    map[string]*rand.Rand{},
-
-		App:      app,
+		rm:       newRandManager(r),
+		app:      app,
 		Accounts: accounts,
-		ChainID:  chainID,
+		chainID:  chainID,
 	}
 	sim.txbuilder = sim.defaultTxBuilder
 	return sim
 }
 
+// TODO: Consider rename to Rand()
 func (sim *SimCtx) GetRand() *rand.Rand {
-	sim.rCounter += 1
-	r := rand.New(rand.NewSource(sim.internalSeed + sim.rCounter))
-	return r
+	return sim.rm.GetRand()
 }
 
-// TODO: Refactor to eventually seed a new prng from seed
-// and maintain a cache of seed -> rand
+// TODO: Consider rename to SeededRand()
+// or DomainSeparatedRand
 func (sim *SimCtx) GetSeededRand(seed string) *rand.Rand {
-	return sim.r
+	return sim.rm.GetSeededRand(seed)
+}
+
+// WrapRand returns a new sim object and a cleanup function to write
+// Accounts changes to the parent (and invalidate the prior)
+func (sim *SimCtx) WrapRand(domainSeparator string) (wrappedSim *SimCtx, cleanup func()) {
+	wrappedSim = &SimCtx{
+		rm:        sim.rm.WrapRand(domainSeparator),
+		app:       sim.app,
+		Accounts:  sim.Accounts,
+		Cdc:       sim.Cdc,
+		chainID:   sim.chainID,
+		txbuilder: sim.txbuilder,
+	}
+	cleanup = func() {
+		sim.Accounts = wrappedSim.Accounts
+		wrappedSim.Accounts = nil
+	}
+	return wrappedSim, cleanup
+}
+
+func (sim SimCtx) ChainID() string {
+	return sim.chainID
+}
+
+func (sim SimCtx) BaseApp() *baseapp.BaseApp {
+	return sim.app.GetBaseApp()
+}
+
+func (sim SimCtx) AppCodec() codec.Codec {
+	return sim.app.AppCodec()
+}
+
+func (sim SimCtx) AccountKeeper() AccountKeeper {
+	return sim.app.GetAccountKeeper()
+}
+
+func (sim SimCtx) BankKeeper() BankKeeper {
+	return sim.app.GetBankKeeper()
+}
+
+// randManager is built to give API's for randomness access
+// which allow the caller to avoid "butterfly effects".
+// e.g. in the Simulator, I don't want adding one new rand call to a message
+// to create an entirely new "run" shape.
+type randManager struct {
+	// TODO: delete this, once we cleanup simulator initialization logic,
+	// and can then setup SimCtx with base seed.
+	internalSeed int64
+	rCounter     int64
+	seededMap    map[string]*rand.Rand
+
+	// if debug = true, we maintain a list of "seen" calls to Wrap,
+	// to ensure no duplicates ever get made.
+	// TODO: Find a way to expose this to executor.
+	// Perhaps we move this to an internal package?
+	debug     bool
+	seenWraps map[string]bool
+}
+
+// TODO: Refactor to take in seed as API's improve
+func newRandManager(r *rand.Rand) randManager {
+	return randManager{
+		internalSeed: r.Int63(),
+		rCounter:     0,
+		seededMap:    map[string]*rand.Rand{},
+		debug:        false,
+		seenWraps:    map[string]bool{},
+	}
+}
+
+func stringToSeed(s string) int64 {
+	// take first 8 bytes of the sha256 hash of s.
+	// We use this for seeding our rand instances.
+	// We use a hash just for convenience, we don't need cryptographic collision resistance,
+	// just simple collisions being unlikely.
+	bz := sha256.Sum256([]byte(s))
+	seedInt := binary.BigEndian.Uint64(bz[:8])
+	return int64(seedInt)
+}
+
+func (rm *randManager) WrapRand(domainSeparator string) randManager {
+	if rm.debug {
+		if _, found := rm.seenWraps[domainSeparator]; found {
+			panic(fmt.Sprintf("domain separator %s reused!", domainSeparator))
+		}
+		rm.seenWraps[domainSeparator] = true
+	}
+
+	sepInt := stringToSeed(domainSeparator)
+	newSeed := rm.internalSeed + sepInt
+	r := rand.New(rand.NewSource(newSeed))
+	return newRandManager(r)
+}
+
+func (rm *randManager) GetRand() *rand.Rand {
+	rm.rCounter += 1
+	r := rand.New(rand.NewSource(rm.internalSeed + rm.rCounter))
+	return r
+}
+
+// TODO: Consider rename to DomainSeparatedRand
+func (rm *randManager) GetSeededRand(seed string) *rand.Rand {
+	// use value in map if present
+	if r, ok := rm.seededMap[seed]; ok {
+		return r
+	}
+	seedInt := stringToSeed(seed)
+	newSeed := rm.internalSeed + seedInt
+	r := rand.New(rand.NewSource(newSeed))
+	rm.seededMap[seed] = r
+	return r
 }
diff --git a/simulation/types/txbuilder.go b/simulation/types/txbuilder.go
index 05c9c47fb..f7d07d1c5 100644
--- a/simulation/types/txbuilder.go
+++ b/simulation/types/txbuilder.go
@@ -32,7 +32,7 @@ func (sim *SimCtx) defaultTxBuilder(
 	if !found {
 		return nil, errors.New("unable to generate mock tx: sim acct not found")
 	}
-	authAcc := sim.App.GetAccountKeeper().GetAccount(ctx, account.Address)
+	authAcc := sim.AccountKeeper().GetAccount(ctx, account.Address)
 	txConfig := params.MakeEncodingConfig().TxConfig // TODO: unhardcode
 	// TODO: Consider making a default tx builder that charges some random fees
 	// Low value for amount of work right now though.
@@ -56,7 +56,7 @@ func (sim *SimCtx) defaultTxBuilder(
 // TODO: Fix these args
 func (sim *SimCtx) deliverTx(tx sdk.Tx, msg sdk.Msg, msgName string) (simulation.OperationMsg, []simulation.FutureOperation, error) {
 	txConfig := params.MakeEncodingConfig().TxConfig // TODO: unhardcode
-	_, results, err := sim.App.GetBaseApp().Deliver(txConfig.TxEncoder(), tx)
+	_, results, err := sim.BaseApp().Deliver(txConfig.TxEncoder(), tx)
 	if err != nil {
 		return simulation.NoOpMsg(msgName, msgName, fmt.Sprintf("unable to deliver tx. \nreason: %v\n results: %v\n msg: %s\n tx: %s", err, results, msg, tx)), nil, err
 	}
diff --git a/x/gamm/keeper/genesis.go b/x/gamm/keeper/genesis.go
index e299d4f80..ca66abfe5 100644
--- a/x/gamm/keeper/genesis.go
+++ b/x/gamm/keeper/genesis.go
@@ -10,7 +10,7 @@ import (
 // InitGenesis initializes the x/gamm module's state from a provided genesis
 // state, which includes the current live pools, global pool parameters (e.g. pool creation fee), next pool number etc.
 func (k Keeper) InitGenesis(ctx sdk.Context, genState types.GenesisState, unpacker codectypes.AnyUnpacker) {
-	k.SetParams(ctx, genState.Params)
+	k.setParams(ctx, genState.Params)
 	k.setNextPoolNumber(ctx, genState.NextPoolNumber)
 
 	// Sums up the liquidity in all genesis state pools to find the total liquidity across all pools.
@@ -22,7 +22,7 @@ func (k Keeper) InitGenesis(ctx sdk.Context, genState types.GenesisState, unpack
 		if err != nil {
 			panic(err)
 		}
-		err = k.SetPool(ctx, pool)
+		err = k.setPool(ctx, pool)
 		if err != nil {
 			panic(err)
 		}
@@ -33,7 +33,7 @@ func (k Keeper) InitGenesis(ctx sdk.Context, genState types.GenesisState, unpack
 		}
 	}
 
-	k.SetTotalLiquidity(ctx, liquidity)
+	k.setTotalLiquidity(ctx, liquidity)
 }
 
 // ExportGenesis returns the capability module's exported genesis.
diff --git a/x/gamm/keeper/params.go b/x/gamm/keeper/params.go
index 5a65da496..420c3413e 100644
--- a/x/gamm/keeper/params.go
+++ b/x/gamm/keeper/params.go
@@ -13,6 +13,6 @@ func (k Keeper) GetParams(ctx sdk.Context) (params types.Params) {
 }
 
 // SetParams sets the total set of params.
-func (k Keeper) SetParams(ctx sdk.Context, params types.Params) {
+func (k Keeper) setParams(ctx sdk.Context, params types.Params) {
 	k.paramSpace.SetParamSet(ctx, &params)
 }
diff --git a/x/gamm/keeper/pool.go b/x/gamm/keeper/pool.go
index 0a4bd46a8..f347d5eea 100644
--- a/x/gamm/keeper/pool.go
+++ b/x/gamm/keeper/pool.go
@@ -81,7 +81,7 @@ func (k Keeper) GetPoolsAndPoke(ctx sdk.Context) (res []types.PoolI, err error)
 	return res, nil
 }
 
-func (k Keeper) SetPool(ctx sdk.Context, pool types.PoolI) error {
+func (k Keeper) setPool(ctx sdk.Context, pool types.PoolI) error {
 	bz, err := k.MarshalPool(pool)
 	if err != nil {
 		return err
@@ -255,7 +255,7 @@ func (k *Keeper) SetStableSwapScalingFactors(ctx sdk.Context, scalingFactors []u
 
 	stableswapPool.ScalingFactor = scalingFactors
 
-	if err = k.SetPool(ctx, stableswapPool); err != nil {
+	if err = k.setPool(ctx, stableswapPool); err != nil {
 		return err
 	}
 	return nil
diff --git a/x/gamm/keeper/pool_service.go b/x/gamm/keeper/pool_service.go
index 47fe5f03e..fe6aeef3f 100644
--- a/x/gamm/keeper/pool_service.go
+++ b/x/gamm/keeper/pool_service.go
@@ -160,7 +160,7 @@ func (k Keeper) CreatePool(ctx sdk.Context, msg types.CreatePoolMsg) (uint64, er
 		Display: poolShareDisplayDenom,
 	})
 
-	if err := k.SetPool(ctx, pool); err != nil {
+	if err := k.setPool(ctx, pool); err != nil {
 		return 0, err
 	}
 
diff --git a/x/gamm/keeper/share.go b/x/gamm/keeper/share.go
index 7423c264b..a5de41740 100644
--- a/x/gamm/keeper/share.go
+++ b/x/gamm/keeper/share.go
@@ -18,7 +18,7 @@ func (k Keeper) applyJoinPoolStateChange(ctx sdk.Context, pool types.PoolI, join
 		return err
 	}
 
-	err = k.SetPool(ctx, pool)
+	err = k.setPool(ctx, pool)
 	if err != nil {
 		return err
 	}
@@ -40,7 +40,7 @@ func (k Keeper) applyExitPoolStateChange(ctx sdk.Context, pool types.PoolI, exit
 		return err
 	}
 
-	err = k.SetPool(ctx, pool)
+	err = k.setPool(ctx, pool)
 	if err != nil {
 		return err
 	}
diff --git a/x/gamm/keeper/swap.go b/x/gamm/keeper/swap.go
index a9fa3ee65..a899c20bf 100644
--- a/x/gamm/keeper/swap.go
+++ b/x/gamm/keeper/swap.go
@@ -114,6 +114,7 @@ func (k Keeper) swapExactAmountOut(
 		return sdk.Int{}, sdkerrors.Wrapf(types.ErrTooManyTokensOut,
 			"can't get more tokens out than there are tokens in the pool")
 	}
+
 	tokenIn, err := pool.SwapInAmtGivenOut(ctx, sdk.Coins{tokenOut}, tokenInDenom, swapFee)
 	if err != nil {
 		return sdk.Int{}, err
@@ -148,7 +149,7 @@ func (k Keeper) updatePoolForSwap(
 	tokensIn := sdk.Coins{tokenIn}
 	tokensOut := sdk.Coins{tokenOut}
 
-	err := k.SetPool(ctx, pool)
+	err := k.setPool(ctx, pool)
 	if err != nil {
 		return err
 	}
diff --git a/x/gamm/keeper/total_liquidity.go b/x/gamm/keeper/total_liquidity.go
index 851b62c18..c82b0e912 100644
--- a/x/gamm/keeper/total_liquidity.go
+++ b/x/gamm/keeper/total_liquidity.go
@@ -16,13 +16,13 @@ func (k Keeper) GetTotalLiquidity(ctx sdk.Context) sdk.Coins {
 	return coins
 }
 
-func (k Keeper) SetTotalLiquidity(ctx sdk.Context, coins sdk.Coins) {
+func (k Keeper) setTotalLiquidity(ctx sdk.Context, coins sdk.Coins) {
 	for _, coin := range coins {
-		k.SetDenomLiquidity(ctx, coin.Denom, coin.Amount)
+		k.setDenomLiquidity(ctx, coin.Denom, coin.Amount)
 	}
 }
 
-func (k Keeper) SetDenomLiquidity(ctx sdk.Context, denom string, amount sdk.Int) {
+func (k Keeper) setDenomLiquidity(ctx sdk.Context, denom string, amount sdk.Int) {
 	store := ctx.KVStore(k.storeKey)
 	bz, err := amount.Marshal()
 	if err != nil {
@@ -68,7 +68,7 @@ func (k Keeper) RecordTotalLiquidityIncrease(ctx sdk.Context, coins sdk.Coins) {
 	for _, coin := range coins {
 		amount := k.GetDenomLiquidity(ctx, coin.Denom)
 		amount = amount.Add(coin.Amount)
-		k.SetDenomLiquidity(ctx, coin.Denom, amount)
+		k.setDenomLiquidity(ctx, coin.Denom, amount)
 	}
 }
 
@@ -76,6 +76,6 @@ func (k Keeper) RecordTotalLiquidityDecrease(ctx sdk.Context, coins sdk.Coins) {
 	for _, coin := range coins {
 		amount := k.GetDenomLiquidity(ctx, coin.Denom)
 		amount = amount.Sub(coin.Amount)
-		k.SetDenomLiquidity(ctx, coin.Denom, amount)
+		k.setDenomLiquidity(ctx, coin.Denom, amount)
 	}
 }
diff --git a/x/gamm/module.go b/x/gamm/module.go
index df389ae70..ce1f7ae38 100644
--- a/x/gamm/module.go
+++ b/x/gamm/module.go
@@ -158,9 +158,6 @@ func (am AppModule) EndBlock(ctx sdk.Context, _ abci.RequestEndBlock) []abci.Val
 func (AppModule) ConsensusVersion() uint64 { return 1 }
 
 // **** simulation implementation ****
-func (am AppModule) GenerateGenesisState(m *module.SimulationState, s *simulation.SimCtx) {
-	m.GenState[types.ModuleName] = am.DefaultGenesis(m.Cdc)
-}
 
 func (am AppModule) Actions() []simulation.Action {
 	return []simulation.Action{
diff --git a/x/gamm/pool-models/balancer/pool.go b/x/gamm/pool-models/balancer/pool.go
index 2a34b982b..4169067aa 100644
--- a/x/gamm/pool-models/balancer/pool.go
+++ b/x/gamm/pool-models/balancer/pool.go
@@ -584,6 +584,8 @@ func (p *Pool) SwapInAmtGivenOut(
 
 // ApplySwap.
 func (p *Pool) applySwap(ctx sdk.Context, tokensIn sdk.Coins, tokensOut sdk.Coins) error {
+	// Fixed gas consumption per swap to prevent spam
+	ctx.GasMeter().ConsumeGas(types.BalancerGasFeeForSwap, "balancer swap computation")
 	// Also ensures that len(tokensIn) = 1 = len(tokensOut)
 	inPoolAsset, outPoolAsset, err := p.parsePoolAssetsCoins(tokensIn, tokensOut)
 	if err != nil {
diff --git a/x/gamm/types/constants.go b/x/gamm/types/constants.go
index acdde3c66..4043af1c5 100644
--- a/x/gamm/types/constants.go
+++ b/x/gamm/types/constants.go
@@ -11,7 +11,8 @@ const (
 	OneShareExponent = 18
 	// Raise 10 to the power of SigFigsExponent to determine number of significant figures.
 	// i.e. SigFigExponent = 8 is 10^8 which is 100000000. This gives 8 significant figures.
-	SigFigsExponent = 8
+	SigFigsExponent       = 8
+	BalancerGasFeeForSwap = 10_000
 )
 
 var (
diff --git a/x/lockup/module.go b/x/lockup/module.go
index 05de92c6c..f5665e275 100644
--- a/x/lockup/module.go
+++ b/x/lockup/module.go
@@ -185,11 +185,6 @@ func (AppModule) ConsensusVersion() uint64 { return 1 }
 
 // AppModuleSimulationV2 functions
 
-// GenerateGenesisState creates a randomized GenState of the pool-incentives module.
-func (am AppModule) GenerateGenesisState(simState *module.SimulationState, s *simulation.SimCtx) {
-	simState.GenState[types.ModuleName] = am.DefaultGenesis(simState.Cdc)
-}
-
 // WeightedOperations returns the all the lockup module operations with their respective weights.
 func (am AppModule) Actions() []simulation.Action {
 	return []simulation.Action{


Test patch:
diff --git a/app/apptesting/test_suite.go b/app/apptesting/test_suite.go
index a73be4ece..0e8922955 100644
--- a/app/apptesting/test_suite.go
+++ b/app/apptesting/test_suite.go
@@ -174,16 +174,11 @@ func (s *KeeperTestHelper) AllocateRewardsToValidator(valAddr sdk.ValAddress, re
 
 // SetupGammPoolsWithBondDenomMultiplier uses given multipliers to set initial pool supply of bond denom.
 func (s *KeeperTestHelper) SetupGammPoolsWithBondDenomMultiplier(multipliers []sdk.Dec) []gammtypes.PoolI {
-	s.App.GAMMKeeper.SetParams(s.Ctx, gammtypes.Params{
-		PoolCreationFee: sdk.Coins{},
-	})
-
 	bondDenom := s.App.StakingKeeper.BondDenom(s.Ctx)
 	// TODO: use sdk crypto instead of tendermint to generate address
 	acc1 := sdk.AccAddress(ed25519.GenPrivKey().PubKey().Address().Bytes())
 
-	poolCreationFee := s.App.GAMMKeeper.GetParams(s.Ctx)
-	s.FundAcc(acc1, poolCreationFee.PoolCreationFee)
+	params := s.App.GAMMKeeper.GetParams(s.Ctx)
 
 	pools := []gammtypes.PoolI{}
 	for index, multiplier := range multipliers {
@@ -193,7 +188,7 @@ func (s *KeeperTestHelper) SetupGammPoolsWithBondDenomMultiplier(multipliers []s
 		s.FundAcc(acc1, sdk.NewCoins(
 			sdk.NewCoin(bondDenom, uosmoAmount.Mul(sdk.NewInt(10))),
 			sdk.NewInt64Coin(token, 100000),
-		))
+		).Add(params.PoolCreationFee...))
 
 		var (
 			defaultFutureGovernor = ""
diff --git a/app/upgrades/v4/upgrade_test.go b/app/upgrades/v4/upgrade_test.go
index 0a402b6f7..0f66dd3df 100644
--- a/app/upgrades/v4/upgrade_test.go
+++ b/app/upgrades/v4/upgrade_test.go
@@ -7,12 +7,13 @@ import (
 	"testing"
 	"time"
 
-	"github.com/osmosis-labs/osmosis/v7/app"
-	v4 "github.com/osmosis-labs/osmosis/v7/app/upgrades/v4"
 	"github.com/stretchr/testify/suite"
 	abci "github.com/tendermint/tendermint/abci/types"
 	tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
 
+	"github.com/osmosis-labs/osmosis/v7/app"
+	v4 "github.com/osmosis-labs/osmosis/v7/app/upgrades/v4"
+
 	sdk "github.com/cosmos/cosmos-sdk/types"
 	upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types"
 )
@@ -107,9 +108,11 @@ func (suite *UpgradeTestSuite) TestUpgradePayments() {
 				suite.Require().Equal(feePool.GetCommunityPool(), sdk.NewDecCoins(sdk.NewInt64DecCoin("uosmo", expectedBal)))
 
 				// Check that gamm Minimum Fee has been set correctly
-				gammParams := suite.app.GAMMKeeper.GetParams(suite.ctx)
-				expectedCreationFee := sdk.NewCoins(sdk.NewCoin("uosmo", sdk.OneInt()))
-				suite.Require().Equal(gammParams.PoolCreationFee, expectedCreationFee)
+
+				// Kept as comments for recordkeeping. Since SetParams is now private, the changes being tested for can no longer be made:
+				//  	gammParams := suite.app.GAMMKeeper.GetParams(suite.ctx)
+				//  	expectedCreationFee := sdk.NewCoins(sdk.NewCoin("uosmo", sdk.OneInt()))
+				//  	suite.Require().Equal(gammParams.PoolCreationFee, expectedCreationFee)
 			},
 			true,
 		},
diff --git a/app/upgrades/v9/prop214_test.go b/app/upgrades/v9/prop214_test.go
index 4445d2791..0fc62d6cb 100644
--- a/app/upgrades/v9/prop214_test.go
+++ b/app/upgrades/v9/prop214_test.go
@@ -3,7 +3,6 @@ package v9_test
 import (
 	"testing"
 
-	sdk "github.com/cosmos/cosmos-sdk/types"
 	"github.com/stretchr/testify/suite"
 
 	"github.com/osmosis-labs/osmosis/v7/app/apptesting"
@@ -26,11 +25,12 @@ func (suite *UpgradeTestSuite) TestProp214() {
 	poolId := suite.PrepareBalancerPool()
 	v9.ExecuteProp214(suite.Ctx, suite.App.GAMMKeeper)
 
-	pool, err := suite.App.GAMMKeeper.GetPoolAndPoke(suite.Ctx, poolId)
+	_, err := suite.App.GAMMKeeper.GetPoolAndPoke(suite.Ctx, poolId)
 	suite.Require().NoError(err)
 
-	swapFee := pool.GetSwapFee(suite.Ctx)
-	expectedSwapFee := sdk.MustNewDecFromStr("0.002")
-
-	suite.Require().Equal(expectedSwapFee, swapFee)
+	// Kept as comments for recordkeeping. Since SetPool is now private, the changes being tested for can no longer be made:
+	// 		swapFee := pool.GetSwapFee(suite.Ctx)
+	//  	expectedSwapFee := sdk.MustNewDecFromStr("0.002")
+	//
+	//  	suite.Require().Equal(expectedSwapFee, swapFee)
 }
diff --git a/osmomath/math_test.go b/osmomath/math_test.go
index c01caf80e..b369db336 100644
--- a/osmomath/math_test.go
+++ b/osmomath/math_test.go
@@ -1,10 +1,13 @@
 package osmomath
 
 import (
+	"fmt"
 	"testing"
 
 	sdk "github.com/cosmos/cosmos-sdk/types"
 
+	"github.com/osmosis-labs/osmosis/v7/osmoutils"
+
 	"github.com/stretchr/testify/require"
 )
 
@@ -23,50 +26,143 @@ func TestAbsDifferenceWithSign(t *testing.T) {
 }
 
 func TestPowApprox(t *testing.T) {
-	base, err := sdk.NewDecFromStr("0.8")
-	require.NoError(t, err)
-	exp, err := sdk.NewDecFromStr("0.32")
-	require.NoError(t, err)
-
-	s := PowApprox(base, exp, powPrecision)
-	expectedDec, err := sdk.NewDecFromStr("0.93108385")
-	require.NoError(t, err)
-
-	require.True(
-		t,
-		expectedDec.Sub(s).Abs().LTE(powPrecision),
-		"expected value & actual value's difference should less than precision",
-	)
+	testCases := []struct {
+		base           sdk.Dec
+		exp            sdk.Dec
+		powPrecision   sdk.Dec
+		expectedResult sdk.Dec
+	}{
+		{
+			// medium base, small exp
+			base:           sdk.MustNewDecFromStr("0.8"),
+			exp:            sdk.MustNewDecFromStr("0.32"),
+			powPrecision:   sdk.MustNewDecFromStr("0.00000001"),
+			expectedResult: sdk.MustNewDecFromStr("0.93108385"),
+		},
+		{
+			// zero exp
+			base:           sdk.MustNewDecFromStr("0.8"),
+			exp:            sdk.ZeroDec(),
+			powPrecision:   sdk.MustNewDecFromStr("0.00001"),
+			expectedResult: sdk.OneDec(),
+		},
+		{
+			// zero base, this should panic
+			base:           sdk.ZeroDec(),
+			exp:            sdk.OneDec(),
+			powPrecision:   sdk.MustNewDecFromStr("0.00001"),
+			expectedResult: sdk.ZeroDec(),
+		},
+		{
+			// large base, small exp
+			base:           sdk.MustNewDecFromStr("1.9999"),
+			exp:            sdk.MustNewDecFromStr("0.23"),
+			powPrecision:   sdk.MustNewDecFromStr("0.000000001"),
+			expectedResult: sdk.MustNewDecFromStr("1.172821461"),
+		},
+		{
+			// large base, large integer exp
+			base:           sdk.MustNewDecFromStr("1.777"),
+			exp:            sdk.MustNewDecFromStr("20"),
+			powPrecision:   sdk.MustNewDecFromStr("0.000000000001"),
+			expectedResult: sdk.MustNewDecFromStr("98570.862372081602"),
+		},
+		{
+			// medium base, large exp, high precision
+			base:           sdk.MustNewDecFromStr("1.556"),
+			exp:            sdk.MustNewDecFromStr("20.9123"),
+			powPrecision:   sdk.MustNewDecFromStr("0.0000000000000001"),
+			expectedResult: sdk.MustNewDecFromStr("10360.058421529811344618"),
+		},
+		{
+			// high base, large exp, high precision
+			base:           sdk.MustNewDecFromStr("1.886"),
+			exp:            sdk.MustNewDecFromStr("31.9123"),
+			powPrecision:   sdk.MustNewDecFromStr("0.00000000000001"),
+			expectedResult: sdk.MustNewDecFromStr("621110716.84727942280335811"),
+		},
+		{
+			// base equal one
+			base:           sdk.MustNewDecFromStr("1"),
+			exp:            sdk.MustNewDecFromStr("123"),
+			powPrecision:   sdk.MustNewDecFromStr("0.00000001"),
+			expectedResult: sdk.OneDec(),
+		},
+	}
 
-	base, err = sdk.NewDecFromStr("0.8")
-	require.NoError(t, err)
-	exp = sdk.ZeroDec()
-	require.NoError(t, err)
-
-	s = PowApprox(base, exp, powPrecision)
-	expectedDec = sdk.OneDec()
-	require.NoError(t, err)
-
-	require.True(
-		t,
-		expectedDec.Sub(s).Abs().LTE(powPrecision),
-		"expected value & actual value's difference should less than precision",
-	)
+	for i, tc := range testCases {
+		var actualResult sdk.Dec
+		osmoutils.ConditionalPanic(t, tc.base.Equal(sdk.ZeroDec()), func() {
+			fmt.Println(tc.base)
+			actualResult = PowApprox(tc.base, tc.exp, tc.powPrecision)
+			require.True(
+				t,
+				tc.expectedResult.Sub(actualResult).Abs().LTE(tc.powPrecision),
+				fmt.Sprintf("test %d failed: expected value & actual value's difference should be less than precision", i),
+			)
+		})
+	}
 }
 
 func TestPow(t *testing.T) {
-	base, err := sdk.NewDecFromStr("1.68")
-	require.NoError(t, err)
-	exp, err := sdk.NewDecFromStr("0.32")
-	require.NoError(t, err)
-
-	s := Pow(base, exp)
-	expectedDec, err := sdk.NewDecFromStr("1.18058965")
-	require.NoError(t, err)
+	testCases := []struct {
+		base           sdk.Dec
+		exp            sdk.Dec
+		expectedResult sdk.Dec
+	}{
+		{
+			// medium base, small exp
+			base:           sdk.MustNewDecFromStr("0.8"),
+			exp:            sdk.MustNewDecFromStr("0.32"),
+			expectedResult: sdk.MustNewDecFromStr("0.93108385"),
+		},
+		{
+			// zero exp
+			base:           sdk.MustNewDecFromStr("0.8"),
+			exp:            sdk.ZeroDec(),
+			expectedResult: sdk.OneDec(),
+		},
+		{
+			// zero base, this should panic
+			base:           sdk.ZeroDec(),
+			exp:            sdk.OneDec(),
+			expectedResult: sdk.ZeroDec(),
+		},
+		{
+			// large base, small exp
+			base:           sdk.MustNewDecFromStr("1.9999"),
+			exp:            sdk.MustNewDecFromStr("0.23"),
+			expectedResult: sdk.MustNewDecFromStr("1.172821461"),
+		},
+		{
+			// small base, large exp
+			base:           sdk.MustNewDecFromStr("0.0000123"),
+			exp:            sdk.MustNewDecFromStr("123"),
+			expectedResult: sdk.ZeroDec(),
+		},
+		{
+			// large base, large exp
+			base:           sdk.MustNewDecFromStr("1.777"),
+			exp:            sdk.MustNewDecFromStr("20"),
+			expectedResult: sdk.MustNewDecFromStr("98570.862372081602"),
+		},
+		{
+			// base equal one
+			base:           sdk.MustNewDecFromStr("1"),
+			exp:            sdk.MustNewDecFromStr("123"),
+			expectedResult: sdk.OneDec(),
+		},
+	}
 
-	require.True(
-		t,
-		expectedDec.Sub(s).Abs().LTE(powPrecision),
-		"expected value & actual value's difference should less than precision",
-	)
+	for i, tc := range testCases {
+		var actualResult sdk.Dec
+		osmoutils.ConditionalPanic(t, tc.base.Equal(sdk.ZeroDec()), func() {
+			actualResult = Pow(tc.base, tc.exp)
+			require.True(
+				t,
+				tc.expectedResult.Sub(actualResult).Abs().LTE(powPrecision),
+				fmt.Sprintf("test %d failed: expected value & actual value's difference should be less than precision", i),
+			)
+		})
+	}
 }
diff --git a/scripts/mutation-test.sh b/scripts/mutation-test.sh
old mode 100644
new mode 100755
index 350aa0d9c..7653a6551
--- a/scripts/mutation-test.sh
+++ b/scripts/mutation-test.sh
@@ -23,6 +23,9 @@ OUTPUT=$(go run github.com/zimmski/go-mutesting/cmd/go-mutesting --disable=$DISA
 RESULT=$(echo "$OUTPUT" | grep 'The mutation score')
 SCORE=$(echo "$RESULT" | grep -Eo '[[:digit:]]\.[[:digit:]]+')
 
+echo "writing mutation test result to mutation_test_result.txt"
+echo "$OUTPUT" > mutation_test_result.txt
+
 echo $RESULT
 
 # Return a non-zero exit code if the score is below 75%
diff --git a/simulation/executor/params_test.go b/simulation/executor/params_test.go
deleted file mode 100644
index 3eb3ad8bc..000000000
--- a/simulation/executor/params_test.go
+++ /dev/null
@@ -1,56 +0,0 @@
-package simulation
-
-import (
-	"fmt"
-	"math/rand"
-	"testing"
-
-	"github.com/stretchr/testify/require"
-	tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
-
-	sdk "github.com/cosmos/cosmos-sdk/types"
-	simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
-)
-
-func TestParamChange(t *testing.T) {
-	subspace, key := "theSubspace", "key"
-	f := func(r *rand.Rand) string {
-		return "theResult"
-	}
-
-	pChange := NewSimParamChange(subspace, key, f)
-
-	require.Equal(t, subspace, pChange.Subspace())
-	require.Equal(t, key, pChange.Key())
-	require.Equal(t, f(nil), pChange.SimValue()(nil))
-	require.Equal(t, fmt.Sprintf("%s/%s", subspace, key), pChange.ComposedKey())
-}
-
-func TestNewWeightedProposalContent(t *testing.T) {
-	key := "theKey"
-	weight := 1
-	content := &testContent{}
-	f := func(r *rand.Rand, ctx sdk.Context, accs []simtypes.Account) simtypes.Content {
-		return content
-	}
-
-	pContent := NewWeightedProposalContent(key, weight, f)
-
-	require.Equal(t, key, pContent.AppParamsKey())
-	require.Equal(t, weight, pContent.DefaultWeight())
-
-	ctx := sdk.NewContext(nil, tmproto.Header{}, true, nil)
-	require.Equal(t, content, pContent.ContentSimulatorFn()(nil, ctx, nil))
-}
-
-type testContent struct {
-}
-
-func (t testContent) GetTitle() string                { return "" }
-func (t testContent) GetDescription() string          { return "" }
-func (t testContent) GetIsExpedited() bool            { return false }
-func (t testContent) SetIsExpedited(isExpedited bool) {}
-func (t testContent) ProposalRoute() string           { return "" }
-func (t testContent) ProposalType() string            { return "" }
-func (t testContent) ValidateBasic() error            { return nil }
-func (t testContent) String() string                  { return "" }
diff --git a/simulation/types/randmanager_test.go b/simulation/types/randmanager_test.go
new file mode 100644
index 000000000..4e7fa116d
--- /dev/null
+++ b/simulation/types/randmanager_test.go
@@ -0,0 +1,87 @@
+package simulation
+
+import (
+	"math/rand"
+	"testing"
+
+	"github.com/stretchr/testify/require"
+)
+
+var defaultSeed = int64(10)
+
+func getDefaultRandInstance() *rand.Rand {
+	return rand.New(rand.NewSource(defaultSeed))
+}
+
+func getKDefaultRandManager(k int) []randManager {
+	rms := make([]randManager, k)
+	for i := 0; i < k; i++ {
+		rms[i] = newRandManager(getDefaultRandInstance())
+	}
+	return rms
+}
+
+func randInstancesEqual(rands []*rand.Rand) bool {
+	value := rands[0].Int()
+	for i := 1; i < len(rands); i++ {
+		if rands[i].Int() != value {
+			return false
+		}
+	}
+	return true
+}
+
+// Test that the rand manager GetRand() are all independent of one another.
+func TestRandManagerGetRandIndependence(t *testing.T) {
+	rms := getKDefaultRandManager(3)
+	expectedEqualRands := []*rand.Rand{}
+	// We want to test that in each of the the following three scenarios, r2 is equal:
+	// 1) r1 := rm.GetRand(); r2 := rm.GetRand();
+	// 2) r1 := rm.GetRand(); r2 := rm.GetRand(); _ = r1.Int()
+	// 3) r1 := rm.GetRand(); r1.Int(); r2 := rm.GetRand();
+	scenario1RM := rms[0]
+	scenario1RM.GetRand()
+	r2 := scenario1RM.GetRand()
+	expectedEqualRands = append(expectedEqualRands, r2)
+
+	scenario2RM := rms[1]
+	r1 := scenario2RM.GetRand()
+	r2 = scenario2RM.GetRand()
+	r1.Int()
+	expectedEqualRands = append(expectedEqualRands, r2)
+
+	scenario3RM := rms[2]
+	r1 = scenario3RM.GetRand()
+	r1.Int()
+	r2 = scenario3RM.GetRand()
+	expectedEqualRands = append(expectedEqualRands, r2)
+	require.True(t, randInstancesEqual(expectedEqualRands))
+}
+
+// Test that the rand manager GetSeededRand() for the same seed are all returning the same rand instance.
+func TestRandManagerSameSeedGetSeededRand(t *testing.T) {
+	rms := getKDefaultRandManager(3)
+	seed := "test seed"
+	// We want to test that in each of the the following three scenarios, we generated the same 'trace' of values.
+	// 1) r1 := rm.GetSeededRand(seed); r1.Int(); r2 := rm.GetSeededRand(seed); r2.Int();
+	// 2) r1 := rm.GetSeededRand(seed); r2 := rm.GetSeededRand(seed); r1.Int(); r2.Int();
+	// 3) r1 := rm.GetSeededRand(seed); r2 := rm.GetSeededRand(seed); r2.Int(); r1.Int();
+	scenario1RM := rms[0]
+	r1 := scenario1RM.GetSeededRand(seed)
+	v1 := r1.Int()
+	r2 := scenario1RM.GetSeededRand(seed)
+	scenario1Trace := []int{v1, r2.Int()}
+
+	scenario2RM := rms[1]
+	r1 = scenario2RM.GetSeededRand(seed)
+	r2 = scenario2RM.GetSeededRand(seed)
+	scenario2Trace := []int{r1.Int(), r2.Int()}
+
+	scenario3RM := rms[2]
+	r1 = scenario3RM.GetSeededRand(seed)
+	r2 = scenario3RM.GetSeededRand(seed)
+	scenario3Trace := []int{r2.Int(), r1.Int()}
+
+	require.Equal(t, scenario1Trace, scenario2Trace)
+	require.Equal(t, scenario1Trace, scenario3Trace)
+}
diff --git a/tests/e2e/configurer/base.go b/tests/e2e/configurer/base.go
index 023a53e04..3826e10fc 100644
--- a/tests/e2e/configurer/base.go
+++ b/tests/e2e/configurer/base.go
@@ -177,7 +177,9 @@ func (bc *baseConfigurer) connectIBCChains(chainA *chain.Config, chainB *chain.C
 func (bc *baseConfigurer) initializeChainConfigFromInitChain(initializedChain *initialization.Chain, chainConfig *chain.Config) {
 	chainConfig.ChainMeta = initializedChain.ChainMeta
 	chainConfig.NodeConfigs = make([]*chain.NodeConfig, 0, len(initializedChain.Nodes))
+	setupTime := time.Now()
 	for _, validator := range initializedChain.Nodes {
-		chainConfig.NodeConfigs = append(chainConfig.NodeConfigs, chain.NewNodeConfig(bc.t, validator, chainConfig.Id, bc.containerManager))
+		conf := chain.NewNodeConfig(bc.t, validator, chainConfig.Id, bc.containerManager).WithSetupTime(setupTime)
+		chainConfig.NodeConfigs = append(chainConfig.NodeConfigs, conf)
 	}
 }
diff --git a/tests/e2e/configurer/chain/commands.go b/tests/e2e/configurer/chain/commands.go
index 488ccd76d..ac806545f 100644
--- a/tests/e2e/configurer/chain/commands.go
+++ b/tests/e2e/configurer/chain/commands.go
@@ -10,92 +10,94 @@ import (
 )
 
 func (n *NodeConfig) CreatePool(poolFile, from string) {
-	n.t.Logf("creating pool for chain-id: %s", n.chainId)
+	n.LogActionF("creating pool from file %s", poolFile)
 	cmd := []string{"osmosisd", "tx", "gamm", "create-pool", fmt.Sprintf("--pool-file=/osmosis/%s", poolFile), fmt.Sprintf("--from=%s", from)}
 	_, _, err := n.containerManager.ExecTxCmd(n.t, n.chainId, n.Name, cmd)
 	require.NoError(n.t, err)
-	n.t.Logf("successfully created pool from container: %s", n.Name)
+	n.LogActionF("successfully created pool")
 }
 
 func (n *NodeConfig) SubmitUpgradeProposal(upgradeVersion string, upgradeHeight int64) {
-	n.t.Logf("submitting upgrade proposal on container: %s", n.Name)
+	n.LogActionF("submitting upgrade proposal %s for height %d", upgradeVersion, upgradeHeight)
 	cmd := []string{"osmosisd", "tx", "gov", "submit-proposal", "software-upgrade", upgradeVersion, fmt.Sprintf("--title=\"%s upgrade\"", upgradeVersion), "--description=\"upgrade proposal submission\"", fmt.Sprintf("--upgrade-height=%d", upgradeHeight), "--upgrade-info=\"\"", "--from=val"}
 	_, _, err := n.containerManager.ExecTxCmd(n.t, n.chainId, n.Name, cmd)
 	require.NoError(n.t, err)
-	n.t.Log("successfully submitted upgrade proposal")
+	n.LogActionF("successfully submitted upgrade proposal")
 }
 
 func (n *NodeConfig) SubmitSuperfluidProposal(asset string) {
-	n.t.Logf("submitting superfluid proposal for asset %s on container: %s", asset, n.Name)
+	n.LogActionF("submitting superfluid proposal for asset %s", asset)
 	cmd := []string{"osmosisd", "tx", "gov", "submit-proposal", "set-superfluid-assets-proposal", fmt.Sprintf("--superfluid-assets=%s", asset), fmt.Sprintf("--title=\"%s superfluid asset\"", asset), fmt.Sprintf("--description=\"%s superfluid asset\"", asset), "--from=val"}
 	_, _, err := n.containerManager.ExecTxCmd(n.t, n.chainId, n.Name, cmd)
 	require.NoError(n.t, err)
-	n.t.Log("successfully submitted superfluid proposal")
+	n.LogActionF("successfully submitted superfluid proposal for asset %s", asset)
 }
 
 func (n *NodeConfig) SubmitTextProposal(text string) {
-	n.t.Logf("submitting text proposal on container: %s", n.Name)
+	n.LogActionF("submitting text gov proposal")
 	cmd := []string{"osmosisd", "tx", "gov", "submit-proposal", "--type=text", fmt.Sprintf("--title=\"%s\"", text), "--description=\"test text proposal\"", "--from=val"}
 	_, _, err := n.containerManager.ExecTxCmd(n.t, n.chainId, n.Name, cmd)
 	require.NoError(n.t, err)
-	n.t.Log("successfully submitted text proposal")
+	n.LogActionF("successfully submitted text gov proposal")
 }
 
 func (n *NodeConfig) DepositProposal(proposalNumber int) {
-	n.t.Logf("depositing to proposal from container: %s", n.Name)
+	n.LogActionF("depositing on proposal: %d", proposalNumber)
 	cmd := []string{"osmosisd", "tx", "gov", "deposit", fmt.Sprintf("%d", proposalNumber), "500000000uosmo", "--from=val"}
 	_, _, err := n.containerManager.ExecTxCmd(n.t, n.chainId, n.Name, cmd)
 	require.NoError(n.t, err)
-	n.t.Log("successfully deposited to proposal")
+	n.LogActionF("successfully deposited on proposal %d", proposalNumber)
 }
 
 func (n *NodeConfig) VoteYesProposal(from string, proposalNumber int) {
-	n.t.Logf("voting yes on proposal for chain-id: %s", n.chainId)
+	n.LogActionF("voting yes on proposal: %d", proposalNumber)
 	cmd := []string{"osmosisd", "tx", "gov", "vote", fmt.Sprintf("%d", proposalNumber), "yes", fmt.Sprintf("--from=%s", from)}
 	_, _, err := n.containerManager.ExecTxCmd(n.t, n.chainId, n.Name, cmd)
 	require.NoError(n.t, err)
-	n.t.Logf("successfully voted yes on proposal from container: %s", n.Name)
+	n.LogActionF("successfully voted yes on proposal %d", proposalNumber)
 }
 
 func (n *NodeConfig) VoteNoProposal(from string, proposalNumber int) {
-	n.t.Logf("voting no on proposal for chain-id: %s", n.chainId)
+	n.LogActionF("voting no on proposal: %d", proposalNumber)
 	cmd := []string{"osmosisd", "tx", "gov", "vote", fmt.Sprintf("%d", proposalNumber), "no", fmt.Sprintf("--from=%s", from)}
 	_, _, err := n.containerManager.ExecTxCmd(n.t, n.chainId, n.Name, cmd)
 	require.NoError(n.t, err)
-	n.t.Logf("successfully voted no for proposal from container: %s", n.Name)
+	n.LogActionF("successfully voted no on proposal: %d", proposalNumber)
 }
 
 func (n *NodeConfig) LockTokens(tokens string, duration string, from string) {
-	n.t.Logf("locking %s for %s on chain-id: %s", tokens, duration, n.chainId)
+	n.LogActionF("locking %s for %s", tokens, duration)
 	cmd := []string{"osmosisd", "tx", "lockup", "lock-tokens", tokens, fmt.Sprintf("--duration=%s", duration), fmt.Sprintf("--from=%s", from)}
 	_, _, err := n.containerManager.ExecTxCmd(n.t, n.chainId, n.Name, cmd)
 	require.NoError(n.t, err)
-	n.t.Logf("successfully created lock from container: %s", n.Name)
+	n.LogActionF("successfully created lock")
 }
 
 func (n *NodeConfig) SuperfluidDelegate(lockNumber int, valAddress string, from string) {
 	lockStr := strconv.Itoa(lockNumber)
-	n.t.Logf("superfluid delegating lock %s to %s on chain-id: %s", lockStr, valAddress, n.chainId)
+	n.LogActionF("superfluid delegating lock %s to %s", lockStr, valAddress)
 	cmd := []string{"osmosisd", "tx", "superfluid", "delegate", lockStr, valAddress, fmt.Sprintf("--from=%s", from)}
 	_, _, err := n.containerManager.ExecTxCmd(n.t, n.chainId, n.Name, cmd)
 	require.NoError(n.t, err)
-	n.t.Logf("successfully superfluid delegated from container: %s", n.Name)
+	n.LogActionF("successfully superfluid delegated lock %s to %s", lockStr, valAddress)
 }
 
 func (n *NodeConfig) BankSend(amount string, sendAddress string, receiveAddress string) {
-	n.t.Logf("bank sending %s from %s to %s on chain-id: %s", amount, sendAddress, receiveAddress, n.chainId)
+	n.LogActionF("bank sending %s from address %s to %s", amount, sendAddress, receiveAddress)
 	cmd := []string{"osmosisd", "tx", "bank", "send", sendAddress, receiveAddress, amount, "--from=val"}
 	_, _, err := n.containerManager.ExecTxCmd(n.t, n.chainId, n.Name, cmd)
 	require.NoError(n.t, err)
-	n.t.Logf("successfully sent tx from container: %s", n.Name)
+	n.LogActionF("successfully sent bank sent %s from address %s to %s", amount, sendAddress, receiveAddress)
 }
 
 func (n *NodeConfig) CreateWallet(walletName string) string {
+	n.LogActionF("creating wallet %s", walletName)
 	cmd := []string{"osmosisd", "keys", "add", walletName, "--keyring-backend=test"}
 	outBuf, _, err := n.containerManager.ExecCmd(n.t, n.Name, cmd, "")
 	require.NoError(n.t, err)
 	re := regexp.MustCompile("osmo1(.{38})")
 	walletAddr := fmt.Sprintf("%s\n", re.FindString(outBuf.String()))
 	walletAddr = strings.TrimSuffix(walletAddr, "\n")
+	n.LogActionF("created wallet %s, waller address - %s", walletName, walletAddr)
 	return walletAddr
 }
diff --git a/tests/e2e/configurer/chain/node.go b/tests/e2e/configurer/chain/node.go
index 7c082af2b..7af3a36d8 100644
--- a/tests/e2e/configurer/chain/node.go
+++ b/tests/e2e/configurer/chain/node.go
@@ -24,6 +24,9 @@ type NodeConfig struct {
 	rpcClient        *rpchttp.HTTP
 	t                *testing.T
 	containerManager *containers.Manager
+
+	// Add this to help with logging / tracking time since start.
+	setupTime time.Time
 }
 
 // NewNodeConfig returens new initialized NodeConfig.
@@ -33,6 +36,7 @@ func NewNodeConfig(t *testing.T, initNode *initialization.Node, chainId string,
 		chainId:          chainId,
 		containerManager: containerManager,
 		t:                t,
+		setupTime:        time.Now(),
 	}
 }
 
@@ -113,3 +117,14 @@ func (n *NodeConfig) extractOperatorAddressIfValidator() error {
 	n.OperatorAddress = strings.TrimSuffix(operAddr, "\n")
 	return nil
 }
+
+func (n *NodeConfig) WithSetupTime(t time.Time) *NodeConfig {
+	n.setupTime = t
+	return n
+}
+
+func (n *NodeConfig) LogActionF(msg string, args ...interface{}) {
+	timeSinceStart := time.Since(n.setupTime).Round(time.Millisecond)
+	s := fmt.Sprintf(msg, args...)
+	n.t.Logf("[%s] %s. From container %s", timeSinceStart, s, n.Name)
+}
diff --git a/tests/e2e/configurer/chain/queries.go b/tests/e2e/configurer/chain/queries.go
index 3e44415e6..b9fb7dff0 100644
--- a/tests/e2e/configurer/chain/queries.go
+++ b/tests/e2e/configurer/chain/queries.go
@@ -26,24 +26,15 @@ func (n *NodeConfig) QueryGRPCGateway(path string) ([]byte, error) {
 	fullQueryPath := fmt.Sprintf("%s/%s", endpoint, path)
 
 	var resp *http.Response
-	retriesLeft := 5
-	for {
+	require.Eventually(n.t, func() bool {
 		resp, err = http.Get(fullQueryPath)
-
-		if resp.StatusCode == http.StatusServiceUnavailable {
-			retriesLeft--
-			if retriesLeft == 0 {
-				return nil, err
-			}
-			time.Sleep(10 * time.Second)
-		} else {
-			break
+		if err != nil {
+			n.t.Logf("error while executing HTTP request: %s", err.Error())
+			return false
 		}
-	}
 
-	if err != nil {
-		return nil, fmt.Errorf("failed to execute HTTP request: %w", err)
-	}
+		return resp.StatusCode != http.StatusServiceUnavailable
+	}, time.Minute, time.Millisecond*10, "failed to execute HTTP request")
 
 	defer resp.Body.Close()
 
diff --git a/tests/e2e/configurer/upgrade.go b/tests/e2e/configurer/upgrade.go
index b4c9f73b2..3131a52d5 100644
--- a/tests/e2e/configurer/upgrade.go
+++ b/tests/e2e/configurer/upgrade.go
@@ -71,7 +71,6 @@ func (uc *UpgradeConfigurer) ConfigureChain(chainConfig *chain.Config) error {
 	}
 
 	chainInitResource, err := uc.containerManager.RunChainInitResource(chainConfig.Id, int(chainConfig.VotingPeriod), validatorConfigBytes, tmpDir, int(forkHeight))
-
 	if err != nil {
 		return err
 	}
@@ -143,21 +142,19 @@ func (uc *UpgradeConfigurer) runProposalUpgrade() error {
 	// submit, deposit, and vote for upgrade proposal
 	// prop height = current height + voting period + time it takes to submit proposal + small buffer
 	for _, chainConfig := range uc.chainConfigs {
-		node, err := chainConfig.GetDefaultNode()
-		if err != nil {
-			return err
-		}
-		currentHeight, err := node.QueryCurrentHeight()
-		if err != nil {
-			return err
+		for validatorIdx, node := range chainConfig.NodeConfigs {
+			if validatorIdx == 0 {
+				currentHeight, err := node.QueryCurrentHeight()
+				if err != nil {
+					return err
+				}
+				chainConfig.UpgradePropHeight = currentHeight + int64(chainConfig.VotingPeriod) + int64(config.PropSubmitBlocks) + int64(config.PropBufferBlocks)
+				node.SubmitUpgradeProposal(uc.upgradeVersion, chainConfig.UpgradePropHeight)
+				chainConfig.LatestProposalNumber += 1
+				node.DepositProposal(chainConfig.LatestProposalNumber)
+			}
+			node.VoteYesProposal(initialization.ValidatorWalletName, chainConfig.LatestProposalNumber)
 		}
-
-		chainConfig.UpgradePropHeight = currentHeight + int64(chainConfig.VotingPeriod) + int64(config.PropSubmitBlocks) + int64(config.PropBufferBlocks)
-		node.SubmitUpgradeProposal(uc.upgradeVersion, chainConfig.UpgradePropHeight)
-		chainConfig.LatestProposalNumber += 1
-
-		node.DepositProposal(chainConfig.LatestProposalNumber)
-		node.VoteYesProposal(initialization.ValidatorWalletName, chainConfig.LatestProposalNumber)
 	}
 
 	// wait till all chains halt at upgrade height
diff --git a/tests/e2e/containers/containers.go b/tests/e2e/containers/containers.go
index c49523406..a45637d67 100644
--- a/tests/e2e/containers/containers.go
+++ b/tests/e2e/containers/containers.go
@@ -125,7 +125,7 @@ func (m *Manager) ExecCmd(t *testing.T, containerName string, command []string,
 			return true
 		},
 		time.Minute,
-		time.Second,
+		50*time.Millisecond,
 		"tx returned a non-zero code",
 	)
 
diff --git a/tests/e2e/e2e_test.go b/tests/e2e/e2e_test.go
index d80b04334..0113b675d 100644
--- a/tests/e2e/e2e_test.go
+++ b/tests/e2e/e2e_test.go
@@ -85,7 +85,7 @@ func (s *IntegrationTestSuite) TestSuperfluidVoting() {
 			return true
 		},
 		1*time.Minute,
-		time.Second,
+		10*time.Millisecond,
 		"Osmosis node failed to retrieve prop tally",
 	)
 	noTotal, _, _, _, _ := node.QueryPropTally(chain.LatestProposalNumber)
@@ -106,7 +106,7 @@ func (s *IntegrationTestSuite) TestSuperfluidVoting() {
 			return true
 		},
 		1*time.Minute,
-		time.Second,
+		10*time.Millisecond,
 		"superfluid delegation vote overwrite not working as expected",
 	)
 }
diff --git a/tests/e2e/initialization/node.go b/tests/e2e/initialization/node.go
index 1f4733896..3300cfbd0 100644
--- a/tests/e2e/initialization/node.go
+++ b/tests/e2e/initialization/node.go
@@ -310,6 +310,7 @@ func (n *internalNode) initValidatorConfigs(c *internalChain, persistentPeers []
 	valConfig.StateSync.Enable = false
 	valConfig.LogLevel = "info"
 	valConfig.P2P.PersistentPeers = strings.Join(persistentPeers, ",")
+	valConfig.Consensus = tmconfig.TestConsensusConfig()
 
 	tmconfig.WriteConfigFile(tmCfgPath, valConfig)
 	return nil
diff --git a/tests/simulator/sim_test.go b/tests/simulator/sim_test.go
index 195e3455b..af74440d8 100644
--- a/tests/simulator/sim_test.go
+++ b/tests/simulator/sim_test.go
@@ -95,7 +95,7 @@ func fullAppSimulation(tb testing.TB, is_testing bool) {
 	}
 
 	// Run randomized simulation:
-	_, simParams, simErr := osmosim.SimulateFromSeed(
+	_, simErr := osmosim.SimulateFromSeed(
 		tb,
 		os.Stdout,
 		osmosis,
@@ -104,11 +104,6 @@ func fullAppSimulation(tb testing.TB, is_testing bool) {
 		config,
 		osmosis.AppCodec(),
 	)
-	simParams = simParams
-	// export state and simParams before the simulation error is checked
-	// if err = sdkSimapp.CheckExportSimulation(osmosis, config, simParams); err != nil {
-	// 	tb.Fatal(err)
-	// }
 
 	if simErr != nil {
 		tb.Fatal(simErr)
@@ -186,7 +181,7 @@ func TestAppStateDeterminism(t *testing.T) {
 			}
 
 			// Run randomized simulation:
-			_, _, simErr := osmosim.SimulateFromSeed(
+			_, simErr := osmosim.SimulateFromSeed(
 				t,
 				os.Stdout,
 				osmosis,
diff --git a/x/gamm/keeper/export_test.go b/x/gamm/keeper/export_test.go
new file mode 100644
index 000000000..005c6960e
--- /dev/null
+++ b/x/gamm/keeper/export_test.go
@@ -0,0 +1,12 @@
+package keeper
+
+import (
+	sdk "github.com/cosmos/cosmos-sdk/types"
+
+	"github.com/osmosis-labs/osmosis/v7/x/gamm/types"
+)
+
+// SetParams sets the total set of params.
+func (k Keeper) SetParams(ctx sdk.Context, params types.Params) {
+	k.setParams(ctx, params)
+}
diff --git a/x/gamm/keeper/internal/events/emit_test.go b/x/gamm/keeper/internal/events/emit_test.go
index dcaa845b4..15d60dc5d 100644
--- a/x/gamm/keeper/internal/events/emit_test.go
+++ b/x/gamm/keeper/internal/events/emit_test.go
@@ -29,7 +29,6 @@ func TestGammEventsTestSuite(t *testing.T) {
 }
 
 func (suite *GammEventsTestSuite) TestEmitSwapEvent() {
-
 	testcases := map[string]struct {
 		ctx             sdk.Context
 		testAccountAddr sdk.AccAddress
diff --git a/x/gamm/keeper/pool_service_test.go b/x/gamm/keeper/pool_service_test.go
index 343aded9f..2e8492ee9 100644
--- a/x/gamm/keeper/pool_service_test.go
+++ b/x/gamm/keeper/pool_service_test.go
@@ -579,10 +579,10 @@ func (suite *KeeperTestSuite) TestJoinPoolExitPool_InverseRelationship() {
 			poolId, err := suite.App.GAMMKeeper.CreatePool(suite.Ctx, tc.pool)
 			suite.Require().NoError(err)
 
-		  balanceBeforeJoin := suite.App.BankKeeper.GetAllBalances(suite.Ctx, joinPoolAcc)
+			balanceBeforeJoin := suite.App.BankKeeper.GetAllBalances(suite.Ctx, joinPoolAcc)
 
-		  _, _, err = suite.App.GAMMKeeper.JoinPoolNoSwap(suite.Ctx, joinPoolAcc, poolId, tc.joinPoolShareAmt, sdk.Coins{})
-		  suite.Require().NoError(err)
+			_, _, err = suite.App.GAMMKeeper.JoinPoolNoSwap(suite.Ctx, joinPoolAcc, poolId, tc.joinPoolShareAmt, sdk.Coins{})
+			suite.Require().NoError(err)
 
 			_, err = suite.App.GAMMKeeper.ExitPool(suite.Ctx, joinPoolAcc, poolId, tc.joinPoolShareAmt, sdk.Coins{})
 
diff --git a/x/gamm/keeper/swap_test.go b/x/gamm/keeper/swap_test.go
index 9b647d093..4837a9f25 100644
--- a/x/gamm/keeper/swap_test.go
+++ b/x/gamm/keeper/swap_test.go
@@ -95,9 +95,13 @@ func (suite *KeeperTestSuite) TestBalancerPoolSimpleSwapExactAmountIn() {
 				spotPriceBefore, err := keeper.CalculateSpotPrice(ctx, poolId, test.param.tokenIn.Denom, test.param.tokenOutDenom)
 				suite.NoError(err, "test: %v", test.name)
 
+				prevGasConsumed := suite.Ctx.GasMeter().GasConsumed()
 				tokenOutAmount, err := keeper.SwapExactAmountIn(ctx, suite.TestAccs[0], poolId, test.param.tokenIn, test.param.tokenOutDenom, test.param.tokenOutMinAmount)
 				suite.NoError(err, "test: %v", test.name)
 				suite.True(tokenOutAmount.Equal(test.param.expectedTokenOut), "test: %v", test.name)
+				gasConsumedForSwap := suite.Ctx.GasMeter().GasConsumed() - prevGasConsumed
+				// We consume `types.GasFeeForSwap` directly, so the extra I/O operation mean we end up consuming more.
+				suite.Assert().Greater(gasConsumedForSwap, uint64(types.BalancerGasFeeForSwap))
 
 				assertEventEmitted(suite, ctx, types.TypeEvtTokenSwapped, 1)
 
@@ -199,11 +203,15 @@ func (suite *KeeperTestSuite) TestBalancerPoolSimpleSwapExactAmountOut() {
 				spotPriceBefore, err := keeper.CalculateSpotPrice(ctx, poolId, test.param.tokenInDenom, test.param.tokenOut.Denom)
 				suite.NoError(err, "test: %v", test.name)
 
+				prevGasConsumed := suite.Ctx.GasMeter().GasConsumed()
 				tokenInAmount, err := keeper.SwapExactAmountOut(ctx, suite.TestAccs[0], poolId, test.param.tokenInDenom, test.param.tokenInMaxAmount, test.param.tokenOut)
 				suite.NoError(err, "test: %v", test.name)
 				suite.True(tokenInAmount.Equal(test.param.expectedTokenInAmount),
 					"test: %v\n expect_eq actual: %s, expected: %s",
 					test.name, tokenInAmount, test.param.expectedTokenInAmount)
+				gasConsumedForSwap := suite.Ctx.GasMeter().GasConsumed() - prevGasConsumed
+				// We consume `types.GasFeeForSwap` directly, so the extra I/O operation mean we end up consuming more.
+				suite.Assert().Greater(gasConsumedForSwap, uint64(types.BalancerGasFeeForSwap))
 
 				assertEventEmitted(suite, ctx, types.TypeEvtTokenSwapped, 1)
 
diff --git a/x/incentives/client/cli/cli_test.go b/x/incentives/client/cli/cli_test.go
index fce100e12..719307651 100644
--- a/x/incentives/client/cli/cli_test.go
+++ b/x/incentives/client/cli/cli_test.go
@@ -78,7 +78,6 @@ func (s *IntegrationTestSuite) SetupSuite() {
 
 	_, err = s.network.WaitForHeight(1)
 	s.Require().NoError(err)
-
 }
 
 func (s *IntegrationTestSuite) TearDownSuite() {
diff --git a/x/incentives/keeper/distribute_test.go b/x/incentives/keeper/distribute_test.go
index 9699cf05a..59077e2fb 100644
--- a/x/incentives/keeper/distribute_test.go
+++ b/x/incentives/keeper/distribute_test.go
@@ -174,7 +174,6 @@ func (suite *KeeperTestSuite) TestSyntheticDistribute() {
 			suite.Require().Equal(tc.expectedRewards[i].String(), rewards, "test %v, person %d", tc.name, i)
 		}
 	}
-
 }
 
 // TestGetModuleToDistributeCoins tests the sum of coins yet to be distributed for all of the module is correct.
diff --git a/x/incentives/keeper/gauge_test.go b/x/incentives/keeper/gauge_test.go
index 653202ad1..e46fb22cb 100644
--- a/x/incentives/keeper/gauge_test.go
+++ b/x/incentives/keeper/gauge_test.go
@@ -236,5 +236,4 @@ func (suite *KeeperTestSuite) TestGaugeOperations() {
 			suite.Require().Len(gaugeIdsByDenom, 1)
 		}
 	}
-
 }
diff --git a/x/mint/keeper/keeper_test.go b/x/mint/keeper/keeper_test.go
index 3483eb790..73baaa8c3 100644
--- a/x/mint/keeper/keeper_test.go
+++ b/x/mint/keeper/keeper_test.go
@@ -168,7 +168,8 @@ func (suite *KeeperTestSuite) TestDistributeMintedCoin_ToDeveloperRewardsAddr()
 				{
 					Address: testAddressOne.String(),
 					Weight:  sdk.NewDec(1),
-				}},
+				},
+			},
 			mintCoin: sdk.NewCoin("stake", sdk.NewInt(10000)),
 		},
 		{
@@ -181,7 +182,8 @@ func (suite *KeeperTestSuite) TestDistributeMintedCoin_ToDeveloperRewardsAddr()
 				{
 					Address: testAddressFour.String(),
 					Weight:  sdk.NewDecWithPrec(4, 1),
-				}},
+				},
+			},
 			mintCoin: sdk.NewCoin("stake", sdk.NewInt(100000)),
 		},
 		{
@@ -236,7 +238,7 @@ func (suite *KeeperTestSuite) TestDistributeMintedCoin_ToDeveloperRewardsAddr()
 					feePool.CommunityPool.AmountOf("stake"))
 			} else {
 				suite.Equal(
-					//distribution go to community pool because nil dev reward addresses.
+					// distribution go to community pool because nil dev reward addresses.
 					tc.mintCoin.Amount.ToDec().Mul((params.DistributionProportions.DeveloperRewards).Add(params.DistributionProportions.CommunityPool)),
 					feePool.CommunityPool.AmountOf("stake"))
 			}
diff --git a/x/superfluid/keeper/distribution_test.go b/x/superfluid/keeper/distribution_test.go
index dad228dc5..1e77f51c8 100644
--- a/x/superfluid/keeper/distribution_test.go
+++ b/x/superfluid/keeper/distribution_test.go
@@ -63,16 +63,13 @@ func (suite *KeeperTestSuite) TestMoveSuperfluidDelegationRewardToGauges() {
 		suite.Run(tc.name, func() {
 			suite.SetupTest()
 
-			// Generate delegator addresses
-			delAddrs := CreateRandomAccounts(tc.delegatorNumber)
-
 			// setup validators
 			valAddrs := suite.SetupValidators(tc.validatorStats)
 
 			denoms, _ := suite.SetupGammPoolsAndSuperfluidAssets([]sdk.Dec{sdk.NewDec(20), sdk.NewDec(20)})
 
 			// setup superfluid delegations
-			intermediaryAccs, _ := suite.SetupSuperfluidDelegations(delAddrs, valAddrs, tc.superDelegations, denoms)
+			_, intermediaryAccs, _ := suite.setupSuperfluidDelegations(valAddrs, tc.superDelegations, denoms)
 			unbondingDuration := suite.App.StakingKeeper.GetParams(suite.Ctx).UnbondingTime
 
 			// allocate rewards to first validator
diff --git a/x/superfluid/keeper/edge_case_test.go b/x/superfluid/keeper/edge_case_test.go
index c4ba9287a..a03a17883 100644
--- a/x/superfluid/keeper/edge_case_test.go
+++ b/x/superfluid/keeper/edge_case_test.go
@@ -6,6 +6,7 @@ import (
 	sdk "github.com/cosmos/cosmos-sdk/types"
 	evidencetypes "github.com/cosmos/cosmos-sdk/x/evidence/types"
 	stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
+
 	lockuptypes "github.com/osmosis-labs/osmosis/v7/x/lockup/types"
 )
 
@@ -49,7 +50,7 @@ func (suite *KeeperTestSuite) TestSuperfluidDelegatedValidatorJailed() {
 			for _, del := range tc.superDelegations {
 				valAddr := valAddrs[del.valIndex]
 				delAddr := delAddrs[del.delIndex]
-				lock := suite.SetupSuperfluidDelegate(delAddr, valAddr, denoms[del.lpIndex], del.lpAmount)
+				lock := suite.setupSuperfluidDelegate(delAddr, valAddr, denoms[del.lpIndex], del.lpAmount)
 
 				// save accounts and locks for future use
 				locks = append(locks, lock)
@@ -125,8 +126,6 @@ func (suite *KeeperTestSuite) TestTryUnbondingSuperfluidLockupDirectly() {
 		tc := tc
 		suite.Run(tc.name, func() {
 			suite.SetupTest()
-			// Generate delegator addresses
-			delAddrs := CreateRandomAccounts(tc.delegatorNumber)
 
 			// setup validators
 			valAddrs := suite.SetupValidators(tc.validatorStats)
@@ -134,8 +133,7 @@ func (suite *KeeperTestSuite) TestTryUnbondingSuperfluidLockupDirectly() {
 			denoms, _ := suite.SetupGammPoolsAndSuperfluidAssets([]sdk.Dec{sdk.NewDec(20), sdk.NewDec(20)})
 
 			// setup superfluid delegations
-			_, _, _ = delAddrs, valAddrs, denoms
-			_, locks := suite.SetupSuperfluidDelegations(delAddrs, valAddrs, tc.superDelegations, denoms)
+			_, _, locks := suite.setupSuperfluidDelegations(valAddrs, tc.superDelegations, denoms)
 
 			for _, lock := range locks {
 				err := suite.App.LockupKeeper.BeginUnlock(suite.Ctx, lock.ID, sdk.Coins{})
diff --git a/x/superfluid/keeper/grpc_query_test.go b/x/superfluid/keeper/grpc_query_test.go
index 8b027179e..cd9f6aabe 100644
--- a/x/superfluid/keeper/grpc_query_test.go
+++ b/x/superfluid/keeper/grpc_query_test.go
@@ -43,9 +43,6 @@ func (suite *KeeperTestSuite) TestGRPCSuperfluidAsset() {
 func (suite *KeeperTestSuite) TestGRPCQuerySuperfluidDelegations() {
 	suite.SetupTest()
 
-	// Generate delegator addresses
-	delAddrs := CreateRandomAccounts(2)
-
 	// setup 2 validators
 	valAddrs := suite.SetupValidators([]stakingtypes.BondStatus{stakingtypes.Bonded, stakingtypes.Bonded})
 
@@ -60,13 +57,13 @@ func (suite *KeeperTestSuite) TestGRPCQuerySuperfluidDelegations() {
 	}
 
 	// setup superfluid delegations
-	_, locks := suite.SetupSuperfluidDelegations(delAddrs, valAddrs, superfluidDelegations, denoms)
+	delegatorAddresses, _, locks := suite.setupSuperfluidDelegations(valAddrs, superfluidDelegations, denoms)
 
 	// for each superfluid delegation, query the amount and make sure it is 1000000
 	for _, delegation := range superfluidDelegations {
 		lpDenom := denoms[delegation.lpIndex]
 		res, err := suite.queryClient.SuperfluidDelegationAmount(sdk.WrapSDKContext(suite.Ctx), &types.SuperfluidDelegationAmountRequest{
-			DelegatorAddress: delAddrs[delegation.delIndex].String(),
+			DelegatorAddress: delegatorAddresses[delegation.delIndex].String(),
 			ValidatorAddress: valAddrs[delegation.valIndex].String(),
 			Denom:            lpDenom,
 		})
@@ -75,7 +72,7 @@ func (suite *KeeperTestSuite) TestGRPCQuerySuperfluidDelegations() {
 	}
 
 	// for each delegator, query all their superfluid delegations and make sure they have 2 delegations
-	for _, delegator := range delAddrs {
+	for _, delegator := range delegatorAddresses {
 		res, err := suite.queryClient.SuperfluidDelegationsByDelegator(sdk.WrapSDKContext(suite.Ctx), &types.SuperfluidDelegationsByDelegatorRequest{
 			DelegatorAddress: delegator.String(),
 		})
@@ -139,12 +136,8 @@ func (suite *KeeperTestSuite) TestGRPCQuerySuperfluidDelegations() {
 func (suite *KeeperTestSuite) TestGRPCQuerySuperfluidDelegationsDontIncludeUnbonding() {
 	suite.SetupTest()
 
-	// Generate delegator addresses
-	delAddrs := CreateRandomAccounts(2)
-
 	// setup 2 validators
 	valAddrs := suite.SetupValidators([]stakingtypes.BondStatus{stakingtypes.Bonded, stakingtypes.Bonded})
-
 	denoms, _ := suite.SetupGammPoolsAndSuperfluidAssets([]sdk.Dec{sdk.NewDec(20), sdk.NewDec(20)})
 
 	// create a delegation of 1000000 for every combination of 2 delegations, 2 validators, and 2 superfluid denoms
@@ -156,7 +149,7 @@ func (suite *KeeperTestSuite) TestGRPCQuerySuperfluidDelegationsDontIncludeUnbon
 	}
 
 	// setup superfluid delegations
-	_, locks := suite.SetupSuperfluidDelegations(delAddrs, valAddrs, superfluidDelegations, denoms)
+	delegatorAddresses, _, locks := suite.setupSuperfluidDelegations(valAddrs, superfluidDelegations, denoms)
 
 	// start unbonding the superfluid delegations of denom0 from delegator0 to validator0
 	err := suite.querier.SuperfluidUndelegate(suite.Ctx, locks[0].Owner, locks[0].ID)
@@ -164,7 +157,7 @@ func (suite *KeeperTestSuite) TestGRPCQuerySuperfluidDelegationsDontIncludeUnbon
 
 	// query to make sure that the amount delegated for the now unbonding delegation is 0
 	res, err := suite.queryClient.SuperfluidDelegationAmount(sdk.WrapSDKContext(suite.Ctx), &types.SuperfluidDelegationAmountRequest{
-		DelegatorAddress: delAddrs[0].String(),
+		DelegatorAddress: delegatorAddresses[0].String(),
 		ValidatorAddress: valAddrs[0].String(),
 		Denom:            denoms[0],
 	})
@@ -173,7 +166,7 @@ func (suite *KeeperTestSuite) TestGRPCQuerySuperfluidDelegationsDontIncludeUnbon
 
 	// query to make sure that the unbonding delegation is not included in delegator query
 	res2, err := suite.queryClient.SuperfluidDelegationsByDelegator(sdk.WrapSDKContext(suite.Ctx), &types.SuperfluidDelegationsByDelegatorRequest{
-		DelegatorAddress: delAddrs[0].String(),
+		DelegatorAddress: delegatorAddresses[0].String(),
 	})
 	suite.Require().NoError(err)
 	suite.Require().Len(res2.SuperfluidDelegationRecords, 1)
@@ -206,9 +199,6 @@ func (suite *KeeperTestSuite) TestGRPCQuerySuperfluidDelegationsDontIncludeUnbon
 func (suite *KeeperTestSuite) TestGRPCQueryTotalDelegationByDelegator() {
 	suite.SetupTest()
 
-	// Generate delegator addresses
-	delAddrs := CreateRandomAccounts(2)
-
 	// setup 2 validators
 	valAddrs := suite.SetupValidators([]stakingtypes.BondStatus{stakingtypes.Bonded, stakingtypes.Bonded})
 
@@ -223,13 +213,13 @@ func (suite *KeeperTestSuite) TestGRPCQueryTotalDelegationByDelegator() {
 	}
 
 	// setup superfluid delegations
-	suite.SetupSuperfluidDelegations(delAddrs, valAddrs, superfluidDelegations, denoms)
+	delegatorAddresses, _, _ := suite.setupSuperfluidDelegations(valAddrs, superfluidDelegations, denoms)
 
 	// setup normal delegations
-	bond0to0 := stakingtypes.NewDelegation(delAddrs[0], valAddrs[0], sdk.NewDec(9000000))
-	bond0to1 := stakingtypes.NewDelegation(delAddrs[0], valAddrs[1], sdk.NewDec(9000000))
-	bond1to0 := stakingtypes.NewDelegation(delAddrs[1], valAddrs[0], sdk.NewDec(9000000))
-	bond1to1 := stakingtypes.NewDelegation(delAddrs[1], valAddrs[1], sdk.NewDec(9000000))
+	bond0to0 := stakingtypes.NewDelegation(delegatorAddresses[0], valAddrs[0], sdk.NewDec(9000000))
+	bond0to1 := stakingtypes.NewDelegation(delegatorAddresses[0], valAddrs[1], sdk.NewDec(9000000))
+	bond1to0 := stakingtypes.NewDelegation(delegatorAddresses[1], valAddrs[0], sdk.NewDec(9000000))
+	bond1to1 := stakingtypes.NewDelegation(delegatorAddresses[1], valAddrs[1], sdk.NewDec(9000000))
 
 	suite.App.StakingKeeper.SetDelegation(suite.Ctx, bond0to0)
 	suite.App.StakingKeeper.SetDelegation(suite.Ctx, bond0to1)
@@ -245,7 +235,7 @@ func (suite *KeeperTestSuite) TestGRPCQueryTotalDelegationByDelegator() {
 
 	// for each delegator, query all their superfluid delegations and normal delegations. Making sure they have 4 delegations
 	// Making sure TotalEquivalentStakedAmount is equal to converted amount + normal delegations
-	for _, delegator := range delAddrs {
+	for _, delegator := range delegatorAddresses {
 		res, err := suite.queryClient.TotalDelegationByDelegator(sdk.WrapSDKContext(suite.Ctx), &types.QueryTotalDelegationByDelegatorRequest{
 			DelegatorAddress: delegator.String(),
 		})
diff --git a/x/superfluid/keeper/hooks_test.go b/x/superfluid/keeper/hooks_test.go
index ecfc0ff37..901746735 100644
--- a/x/superfluid/keeper/hooks_test.go
+++ b/x/superfluid/keeper/hooks_test.go
@@ -49,8 +49,7 @@ func (suite *KeeperTestSuite) TestSuperfluidAfterEpochEnd() {
 			denoms, poolIds := suite.SetupGammPoolsAndSuperfluidAssets([]sdk.Dec{sdk.NewDec(20)})
 
 			// Generate delegator addresses
-			delAddrs := CreateRandomAccounts(tc.delegatorNumber)
-			intermediaryAccs, locks := suite.SetupSuperfluidDelegations(delAddrs, valAddrs, tc.superDelegations, denoms)
+			delAddrs, intermediaryAccs, locks := suite.setupSuperfluidDelegations(valAddrs, tc.superDelegations, denoms)
 			suite.checkIntermediaryAccountDelegations(intermediaryAccs)
 
 			// run swap and set spot price
@@ -257,16 +256,13 @@ func (suite *KeeperTestSuite) TestBeforeSlashingUnbondingDelegationHook() {
 
 			slashFactor := sdk.NewDecWithPrec(5, 2)
 
-			// Generate delegator addresses
-			delAddrs := CreateRandomAccounts(tc.delegatorNumber)
-
 			// setup validators
 			valAddrs := suite.SetupValidators(tc.validatorStats)
 
 			denoms, _ := suite.SetupGammPoolsAndSuperfluidAssets([]sdk.Dec{sdk.NewDec(20), sdk.NewDec(20)})
 
 			// setup superfluid delegations
-			intermediaryAccs, _ := suite.SetupSuperfluidDelegations(delAddrs, valAddrs, tc.superDelegations, denoms)
+			_, intermediaryAccs, _ := suite.setupSuperfluidDelegations(valAddrs, tc.superDelegations, denoms)
 			suite.checkIntermediaryAccountDelegations(intermediaryAccs)
 
 			for _, lockId := range tc.superUnbondingLockIds {
diff --git a/x/superfluid/keeper/intermediary_account_test.go b/x/superfluid/keeper/intermediary_account_test.go
index ee86ab52e..29cbe67a3 100644
--- a/x/superfluid/keeper/intermediary_account_test.go
+++ b/x/superfluid/keeper/intermediary_account_test.go
@@ -52,7 +52,7 @@ func (suite *KeeperTestSuite) TestIntermediaryAccountCreation() {
 				suite.Require().Equal(uint64(0), interAcc.GaugeId)
 				suite.Require().Equal("", interAcc.ValAddr)
 
-				lock := suite.SetupSuperfluidDelegate(delAddr, valAddr, denom, superDelegation.lpAmount)
+				lock := suite.setupSuperfluidDelegate(delAddr, valAddr, denom, superDelegation.lpAmount)
 
 				// check that intermediary Account connection is established
 				interAccConnection := suite.App.SuperfluidKeeper.GetLockIdIntermediaryAccountConnection(suite.Ctx, lock.ID)
diff --git a/x/superfluid/keeper/keeper_test.go b/x/superfluid/keeper/keeper_test.go
index a6bd2272c..fa5a73d1f 100644
--- a/x/superfluid/keeper/keeper_test.go
+++ b/x/superfluid/keeper/keeper_test.go
@@ -14,6 +14,7 @@ import (
 	epochtypes "github.com/osmosis-labs/osmosis/v7/x/epochs/types"
 	"github.com/osmosis-labs/osmosis/v7/x/gamm/pool-models/balancer"
 	gammtypes "github.com/osmosis-labs/osmosis/v7/x/gamm/types"
+	lockuptypes "github.com/osmosis-labs/osmosis/v7/x/lockup/types"
 	minttypes "github.com/osmosis-labs/osmosis/v7/x/mint/types"
 	"github.com/osmosis-labs/osmosis/v7/x/superfluid/keeper"
 	"github.com/osmosis-labs/osmosis/v7/x/superfluid/types"
@@ -152,6 +153,98 @@ func (suite *KeeperTestSuite) SetupGammPoolsAndSuperfluidAssets(multipliers []sd
 	return denoms, poolIds
 }
 
+func (suite *KeeperTestSuite) setupSuperfluidDelegations(valAddrs []sdk.ValAddress, superDelegations []superfluidDelegation, denoms []string) ([]sdk.AccAddress, []types.SuperfluidIntermediaryAccount, []lockuptypes.PeriodLock) {
+	flagIntermediaryAcc := make(map[string]bool)
+	intermediaryAccs := []types.SuperfluidIntermediaryAccount{}
+	locks := []lockuptypes.PeriodLock{}
+	delAddrs := []sdk.AccAddress{}
+
+	// we do sanity check on the test cases.
+	// if superfluid staking is happening with single val and multiple superfluid delegations,
+	// we should be running `AddTokensToLockByID`, instead of creating new locks
+	delegatorAddressMap := make(map[int64]sdk.AccAddress)
+	for _, superDelegation := range superDelegations {
+		// either create or use existing delegator address
+		var delAddr sdk.AccAddress
+		if cachedAddr, ok := delegatorAddressMap[superDelegation.delIndex]; ok {
+			delAddr = cachedAddr
+		} else {
+			pk := ed25519.GenPrivKey().PubKey()
+			delAddr = sdk.AccAddress(pk.Address())
+			delegatorAddressMap[superDelegation.delIndex] = delAddr
+			delAddrs = append(delAddrs, delAddr)
+		}
+
+		valAddr := valAddrs[superDelegation.valIndex]
+		lock := suite.setupSuperfluidDelegate(delAddr, valAddr, denoms[superDelegation.lpIndex], superDelegation.lpAmount)
+		address := suite.App.SuperfluidKeeper.GetLockIdIntermediaryAccountConnection(suite.Ctx, lock.ID)
+		gotAcc := suite.App.SuperfluidKeeper.GetIntermediaryAccount(suite.Ctx, address)
+
+		// save accounts for future use
+		if flagIntermediaryAcc[gotAcc.String()] == false {
+			flagIntermediaryAcc[gotAcc.String()] = true
+			intermediaryAccs = append(intermediaryAccs, gotAcc)
+		}
+		// save locks for future use
+		locks = append(locks, lock)
+	}
+	return delAddrs, intermediaryAccs, locks
+}
+
+func (suite *KeeperTestSuite) checkIntermediaryAccountDelegations(intermediaryAccs []types.SuperfluidIntermediaryAccount) {
+	for _, acc := range intermediaryAccs {
+		valAddr, err := sdk.ValAddressFromBech32(acc.ValAddr)
+		suite.Require().NoError(err)
+
+		// check delegation from intermediary account to validator
+		delegation, found := suite.App.StakingKeeper.GetDelegation(suite.Ctx, acc.GetAccAddress(), valAddr)
+		suite.Require().True(found)
+		suite.Require().True(delegation.Shares.GTE(sdk.NewDec(10000000)))
+
+		// check delegated tokens
+		validator, found := suite.App.StakingKeeper.GetValidator(suite.Ctx, valAddr)
+		suite.Require().True(found)
+		delegatedTokens := validator.TokensFromShares(delegation.Shares).TruncateInt()
+		suite.Require().True(delegatedTokens.GTE(sdk.NewInt(10000000)))
+	}
+}
+
+func (suite *KeeperTestSuite) setupSuperfluidDelegate(delAddr sdk.AccAddress, valAddr sdk.ValAddress, denom string, amount int64) lockuptypes.PeriodLock {
+	unbondingDuration := suite.App.StakingKeeper.GetParams(suite.Ctx).UnbondingTime
+
+	// create lockup of LP token
+	coins := sdk.Coins{sdk.NewInt64Coin(denom, amount)}
+	lastLockID := suite.App.LockupKeeper.GetLastLockID(suite.Ctx)
+
+	lockID := suite.LockTokens(delAddr, coins, unbondingDuration)
+	lock, err := suite.App.LockupKeeper.GetLockByID(suite.Ctx, lockID)
+	suite.Require().NoError(err)
+
+	// here we check if check `LockTokens` added to existing locks or created a new lock.
+	// if `LockTokens` created a new lock, we continue SuperfluidDelegate
+	// if lock has been existing before, we wouldn't have to call SuperfluidDelegate separately, as hooks on LockTokens would have automatically called IncreaseSuperfluidDelegation
+	if lastLockID != lockID {
+		err = suite.App.SuperfluidKeeper.SuperfluidDelegate(suite.Ctx, lock.Owner, lock.ID, valAddr.String())
+		suite.Require().NoError(err)
+	} else {
+		// here we handle two cases.
+		// 1. the lock has existed before but has not been superflud staking
+		// 2. the lock has existed before and has been superfluid staking
+
+		// we check if synth lock that has existed before, if it did, it means that the lock has been superfluid staked
+		// we do not care about unbonding synthlocks, as superfluid delegation has no effect
+
+		_, err := suite.App.LockupKeeper.GetSyntheticLockup(suite.Ctx, lockID, keeper.StakingSyntheticDenom(lock.Coins[0].Denom, valAddr.String()))
+		// if lock has existed before but has not been superfluid staked, we do initial superfluid staking
+		if err != nil {
+			err = suite.App.SuperfluidKeeper.SuperfluidDelegate(suite.Ctx, lock.Owner, lock.ID, valAddr.String())
+			suite.Require().NoError(err)
+		}
+	}
+
+	return *lock
+}
+
 func TestKeeperTestSuite(t *testing.T) {
 	suite.Run(t, new(KeeperTestSuite))
 }
diff --git a/x/superfluid/keeper/slash_test.go b/x/superfluid/keeper/slash_test.go
index 8f09c51bc..bbe302047 100644
--- a/x/superfluid/keeper/slash_test.go
+++ b/x/superfluid/keeper/slash_test.go
@@ -72,7 +72,7 @@ func (suite *KeeperTestSuite) TestBeforeValidatorSlashed() {
 			for _, del := range tc.superDelegations {
 				valAddr := valAddrs[del.valIndex]
 				delAddr := delAddrs[del.delIndex]
-				lock := suite.SetupSuperfluidDelegate(delAddr, valAddr, denoms[del.lpIndex], del.lpAmount)
+				lock := suite.setupSuperfluidDelegate(delAddr, valAddr, denoms[del.lpIndex], del.lpAmount)
 
 				// save accounts and locks for future use
 				locks = append(locks, lock)
@@ -145,16 +145,13 @@ func (suite *KeeperTestSuite) TestSlashLockupsForUnbondingDelegationSlash() {
 		suite.Run(tc.name, func() {
 			suite.SetupTest()
 
-			// Generate delegator addresses
-			delAddrs := CreateRandomAccounts(tc.delegatorNumber)
-
 			// setup validators
 			valAddrs := suite.SetupValidators(tc.validatorStats)
 
 			denoms, _ := suite.SetupGammPoolsAndSuperfluidAssets([]sdk.Dec{sdk.NewDec(20), sdk.NewDec(20)})
 
 			// setup superfluid delegations
-			intermediaryAccs, _ := suite.SetupSuperfluidDelegations(delAddrs, valAddrs, tc.superDelegations, denoms)
+			_, intermediaryAccs, _ := suite.setupSuperfluidDelegations(valAddrs, tc.superDelegations, denoms)
 			suite.checkIntermediaryAccountDelegations(intermediaryAccs)
 
 			for _, lockId := range tc.superUnbondingLockIds {
diff --git a/x/superfluid/keeper/stake_test.go b/x/superfluid/keeper/stake_test.go
index 9a4b487ce..f72ce7162 100644
--- a/x/superfluid/keeper/stake_test.go
+++ b/x/superfluid/keeper/stake_test.go
@@ -1,13 +1,11 @@
 package keeper_test
 
 import (
-	"fmt"
 	"time"
 
 	abci "github.com/tendermint/tendermint/abci/types"
 
 	lockuptypes "github.com/osmosis-labs/osmosis/v7/x/lockup/types"
-	minttypes "github.com/osmosis-labs/osmosis/v7/x/mint/types"
 	"github.com/osmosis-labs/osmosis/v7/x/superfluid/keeper"
 	"github.com/osmosis-labs/osmosis/v7/x/superfluid/types"
 
@@ -15,146 +13,35 @@ import (
 	stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
 )
 
-type normalDelegation struct {
-	delIndex   int64
-	valIndex   int64
-	coinAmount int64
-}
-
 type superfluidDelegation struct {
 	delIndex int64
 	valIndex int64
 	lpIndex  int64
 	lpAmount int64
 }
-type superfluidRedelegation struct {
-	lockId      uint64
-	oldValIndex int64
-	newValIndex int64
-}
-
-type osmoEquivalentMultiplier struct {
-	lpIndex int64
-	price   sdk.Dec
-}
-
-func (suite *KeeperTestSuite) SetupNormalDelegation(delAddrs []sdk.AccAddress, valAddrs []sdk.ValAddress, del normalDelegation) error {
-	val, found := suite.App.StakingKeeper.GetValidator(suite.Ctx, valAddrs[del.valIndex])
-	if !found {
-		return fmt.Errorf("validator not found")
-	}
-	_, err := suite.App.StakingKeeper.Delegate(suite.Ctx, delAddrs[del.delIndex], sdk.NewIntFromUint64(uint64(del.coinAmount)), stakingtypes.Bonded, val, false)
-	return err
-}
-
-func (suite *KeeperTestSuite) SetupSuperfluidDelegations(delAddrs []sdk.AccAddress, valAddrs []sdk.ValAddress, superDelegations []superfluidDelegation, denoms []string) ([]types.SuperfluidIntermediaryAccount, []lockuptypes.PeriodLock) {
-	flagIntermediaryAcc := make(map[string]bool)
-	intermediaryAccs := []types.SuperfluidIntermediaryAccount{}
-	locks := []lockuptypes.PeriodLock{}
-
-	// setup superfluid delegations
-
-	// we do sanity check on the test cases.
-	// if superfluid staking is happening with single val and multiple superfluid delegations,
-	// we should be running `AddTokensToLockByID`, instead of creating new locks
-	for _, del := range superDelegations {
-		delAddr := delAddrs[del.delIndex]
-		valAddr := valAddrs[del.valIndex]
-		lock := suite.SetupSuperfluidDelegate(delAddr, valAddr, denoms[del.lpIndex], del.lpAmount)
-		address := suite.App.SuperfluidKeeper.GetLockIdIntermediaryAccountConnection(suite.Ctx, lock.ID)
-		gotAcc := suite.App.SuperfluidKeeper.GetIntermediaryAccount(suite.Ctx, address)
-
-		// save accounts for future use
-		if flagIntermediaryAcc[gotAcc.String()] == false {
-			flagIntermediaryAcc[gotAcc.String()] = true
-			intermediaryAccs = append(intermediaryAccs, gotAcc)
-		}
-		// save locks for future use
-		locks = append(locks, lock)
-	}
-	return intermediaryAccs, locks
-}
-
-func (suite *KeeperTestSuite) checkIntermediaryAccountDelegations(intermediaryAccs []types.SuperfluidIntermediaryAccount) {
-	for _, acc := range intermediaryAccs {
-		valAddr, err := sdk.ValAddressFromBech32(acc.ValAddr)
-		suite.Require().NoError(err)
-
-		// check delegation from intermediary account to validator
-		delegation, found := suite.App.StakingKeeper.GetDelegation(suite.Ctx, acc.GetAccAddress(), valAddr)
-		suite.Require().True(found)
-		suite.Require().True(delegation.Shares.GTE(sdk.NewDec(10000000)))
-
-		// check delegated tokens
-		validator, found := suite.App.StakingKeeper.GetValidator(suite.Ctx, valAddr)
-		suite.Require().True(found)
-		delegatedTokens := validator.TokensFromShares(delegation.Shares).TruncateInt()
-		suite.Require().True(delegatedTokens.GTE(sdk.NewInt(10000000)))
-	}
-}
-
-func (suite *KeeperTestSuite) SetupSuperfluidDelegate(delAddr sdk.AccAddress, valAddr sdk.ValAddress, denom string, amount int64) lockuptypes.PeriodLock {
-	unbondingDuration := suite.App.StakingKeeper.GetParams(suite.Ctx).UnbondingTime
-
-	// create lockup of LP token
-	coins := sdk.Coins{sdk.NewInt64Coin(denom, amount)}
-	lastLockID := suite.App.LockupKeeper.GetLastLockID(suite.Ctx)
-
-	lockID := suite.LockTokens(delAddr, coins, unbondingDuration)
-	lock, err := suite.App.LockupKeeper.GetLockByID(suite.Ctx, lockID)
-	suite.Require().NoError(err)
-
-	// here we check if check `LockTokens` added to existing locks or created a new lock.
-	// if `LockTokens` created a new lock, we continue SuperfluidDelegate
-	// if lock has been existing before, we wouldn't have to call SuperfluidDelegate separately, as hooks on LockTokens would have automatically called IncreaseSuperfluidDelegation
-	if lastLockID != lockID {
-		err = suite.App.SuperfluidKeeper.SuperfluidDelegate(suite.Ctx, lock.Owner, lock.ID, valAddr.String())
-		suite.Require().NoError(err)
-	} else {
-		// here we handle two cases.
-		// 1. the lock has existed before but has not been superflud staking
-		// 2. the lock has existed before and has been superfluid staking
-
-		// we check if synth lock that has existed before, if it did, it means that the lock has been superfluid staked
-		// we do not care about unbonding synthlocks, as superfluid delegation has no effect
-
-		_, err := suite.App.LockupKeeper.GetSyntheticLockup(suite.Ctx, lockID, keeper.StakingSyntheticDenom(lock.Coins[0].Denom, valAddr.String()))
-		// if lock has existed before but has not been superfluid staked, we do initial superfluid staking
-		if err != nil {
-			err = suite.App.SuperfluidKeeper.SuperfluidDelegate(suite.Ctx, lock.Owner, lock.ID, valAddr.String())
-			suite.Require().NoError(err)
-		}
-	}
-
-	return *lock
-}
 
 func (suite *KeeperTestSuite) TestSuperfluidDelegate() {
 	testCases := []struct {
 		name               string
 		validatorStats     []stakingtypes.BondStatus
-		delegatorNumber    int
 		superDelegations   []superfluidDelegation
 		expInterDelegation []sdk.Dec
 	}{
 		{
 			"with single validator and single superfluid delegation",
 			[]stakingtypes.BondStatus{stakingtypes.Bonded},
-			1,
 			[]superfluidDelegation{{0, 0, 0, 1000000}},
 			[]sdk.Dec{sdk.NewDec(10000000)}, // 50% x 20 x 1000000
 		},
 		{
 			"with single validator and additional superfluid delegations",
 			[]stakingtypes.BondStatus{stakingtypes.Bonded},
-			1,
 			[]superfluidDelegation{{0, 0, 0, 1000000}, {0, 0, 0, 1000000}},
 			[]sdk.Dec{sdk.NewDec(20000000)}, // 50% x 20 x 1000000 x 2
 		},
 		{
 			"with multiple validators and multiple superfluid delegations",
 			[]stakingtypes.BondStatus{stakingtypes.Bonded, stakingtypes.Bonded},
-			2,
 			[]superfluidDelegation{{0, 0, 0, 1000000}, {1, 1, 0, 1000000}},
 			[]sdk.Dec{sdk.NewDec(10000000), sdk.NewDec(10000000)}, // 50% x 20 x 1000000
 		},
@@ -166,9 +53,6 @@ func (suite *KeeperTestSuite) TestSuperfluidDelegate() {
 			suite.SetupTest()
 			bondDenom := suite.App.StakingKeeper.BondDenom(suite.Ctx)
 
-			// Generate delegator addresses
-			delAddrs := CreateRandomAccounts(tc.delegatorNumber)
-
 			// setup validators
 			valAddrs := suite.SetupValidators(tc.validatorStats)
 
@@ -179,8 +63,7 @@ func (suite *KeeperTestSuite) TestSuperfluidDelegate() {
 			presupplyWithOffset := suite.App.BankKeeper.GetSupplyWithOffset(suite.Ctx, bondDenom)
 
 			// setup superfluid delegations
-			_, _, _ = delAddrs, valAddrs, denoms
-			intermediaryAccs, locks := suite.SetupSuperfluidDelegations(delAddrs, valAddrs, tc.superDelegations, denoms)
+			_, intermediaryAccs, locks := suite.setupSuperfluidDelegations(valAddrs, tc.superDelegations, denoms)
 
 			// ensure post-superfluid delegations osmo supplywithoffset is the same while supply is not
 			postsupply := suite.App.BankKeeper.GetSupply(suite.Ctx, bondDenom)
@@ -257,9 +140,7 @@ func (suite *KeeperTestSuite) TestSuperfluidUndelegate() {
 	testCases := []struct {
 		name                  string
 		validatorStats        []stakingtypes.BondStatus
-		delegatorNumber       int
 		superDelegations      []superfluidDelegation
-		addMoreTokensLockIds  []uint64
 		superUnbondingLockIds []uint64
 		expSuperUnbondingErr  []bool
 		// expected amount of delegation to intermediary account
@@ -268,9 +149,7 @@ func (suite *KeeperTestSuite) TestSuperfluidUndelegate() {
 		{
 			"with single validator and single superfluid delegation and single undelegation",
 			[]stakingtypes.BondStatus{stakingtypes.Bonded},
-			1,
 			[]superfluidDelegation{{0, 0, 0, 1000000}},
-			[]uint64{},
 			[]uint64{1},
 			[]bool{false},
 			[]sdk.Dec{sdk.ZeroDec()},
@@ -287,9 +166,7 @@ func (suite *KeeperTestSuite) TestSuperfluidUndelegate() {
 		{
 			"with single validator and additional superfluid delegations and single undelegation",
 			[]stakingtypes.BondStatus{stakingtypes.Bonded},
-			1,
 			[]superfluidDelegation{{0, 0, 0, 1000000}, {0, 0, 0, 1000000}},
-			[]uint64{},
 			[]uint64{1},
 			[]bool{false},
 			[]sdk.Dec{sdk.ZeroDec()},
@@ -297,9 +174,7 @@ func (suite *KeeperTestSuite) TestSuperfluidUndelegate() {
 		{
 			"with multiple validators and multiple superfluid delegations and multiple undelegations",
 			[]stakingtypes.BondStatus{stakingtypes.Bonded, stakingtypes.Bonded},
-			2,
 			[]superfluidDelegation{{0, 0, 0, 1000000}, {1, 1, 0, 1000000}},
-			[]uint64{},
 			[]uint64{1, 2},
 			[]bool{false, false},
 			[]sdk.Dec{sdk.ZeroDec()},
@@ -307,9 +182,7 @@ func (suite *KeeperTestSuite) TestSuperfluidUndelegate() {
 		{
 			"undelegating not available lock id",
 			[]stakingtypes.BondStatus{stakingtypes.Bonded},
-			1,
 			[]superfluidDelegation{{0, 0, 0, 1000000}},
-			[]uint64{},
 			[]uint64{2},
 			[]bool{true},
 			[]sdk.Dec{},
@@ -317,9 +190,7 @@ func (suite *KeeperTestSuite) TestSuperfluidUndelegate() {
 		{
 			"try undelegating twice for same lock id",
 			[]stakingtypes.BondStatus{stakingtypes.Bonded},
-			1,
 			[]superfluidDelegation{{0, 0, 0, 1000000}},
-			[]uint64{},
 			[]uint64{1, 1},
 			[]bool{false, true},
 			[]sdk.Dec{sdk.ZeroDec()},
@@ -333,30 +204,15 @@ func (suite *KeeperTestSuite) TestSuperfluidUndelegate() {
 
 			bondDenom := suite.App.StakingKeeper.GetParams(suite.Ctx).BondDenom
 
-			// Generate delegator addresses
-			delAddrs := CreateRandomAccounts(tc.delegatorNumber)
-
 			// setup validators
 			valAddrs := suite.SetupValidators(tc.validatorStats)
 
 			denoms, _ := suite.SetupGammPoolsAndSuperfluidAssets([]sdk.Dec{sdk.NewDec(20), sdk.NewDec(20)})
 
 			// setup superfluid delegations
-			intermediaryAccs, _ := suite.SetupSuperfluidDelegations(delAddrs, valAddrs, tc.superDelegations, denoms)
+			_, intermediaryAccs, _ := suite.setupSuperfluidDelegations(valAddrs, tc.superDelegations, denoms)
 			suite.checkIntermediaryAccountDelegations(intermediaryAccs)
 
-			for _, lockId := range tc.addMoreTokensLockIds {
-				lock, err := suite.App.LockupKeeper.GetLockByID(suite.Ctx, lockId)
-				suite.Require().NoError(err)
-				lockOwner, err := sdk.AccAddressFromBech32(lock.Owner)
-				suite.Require().NoError(err)
-				coin := sdk.NewInt64Coin("gamm/pool/1", 1000000)
-				suite.App.BankKeeper.MintCoins(suite.Ctx, minttypes.ModuleName, sdk.NewCoins(coin))
-				suite.App.BankKeeper.SendCoinsFromModuleToAccount(suite.Ctx, minttypes.ModuleName, lockOwner, sdk.NewCoins(coin))
-				_, err = suite.App.LockupKeeper.AddTokensToLockByID(suite.Ctx, lockId, lockOwner, coin)
-				suite.Require().NoError(err)
-			}
-
 			for index, lockId := range tc.superUnbondingLockIds {
 				// get intermediary account
 				accAddr := suite.App.SuperfluidKeeper.GetLockIdIntermediaryAccountConnection(suite.Ctx, lockId)
@@ -445,16 +301,13 @@ func (suite *KeeperTestSuite) TestSuperfluidUndelegate() {
 func (suite *KeeperTestSuite) TestSuperfluidUnbondLock() {
 	suite.SetupTest()
 
-	// Generate delegator addresses
-	delAddrs := CreateRandomAccounts(1)
-
 	// setup validators
 	valAddrs := suite.SetupValidators([]stakingtypes.BondStatus{stakingtypes.Bonded})
 
 	denoms, _ := suite.SetupGammPoolsAndSuperfluidAssets([]sdk.Dec{sdk.NewDec(20), sdk.NewDec(20)})
 
 	// setup superfluid delegations
-	intermediaryAccs, locks := suite.SetupSuperfluidDelegations(delAddrs, valAddrs, []superfluidDelegation{{0, 0, 0, 1000000}}, denoms)
+	_, intermediaryAccs, locks := suite.setupSuperfluidDelegations(valAddrs, []superfluidDelegation{{0, 0, 0, 1000000}}, denoms)
 	suite.checkIntermediaryAccountDelegations(intermediaryAccs)
 
 	for _, lock := range locks {
@@ -527,6 +380,151 @@ func (suite *KeeperTestSuite) TestSuperfluidUnbondLock() {
 	}
 }
 
+func (suite *KeeperTestSuite) TestRefreshIntermediaryDelegationAmounts() {
+	testCases := []struct {
+		name             string
+		validatorStats   []stakingtypes.BondStatus
+		superDelegations []superfluidDelegation
+		// denom of the superfluid asset is the key, multiplier is the value
+		multipliersByDenom map[string]sdk.Dec
+	}{
+		{
+			"with single validator and single delegation",
+			[]stakingtypes.BondStatus{stakingtypes.Bonded},
+			[]superfluidDelegation{{0, 0, 0, 1000000}},
+			map[string]sdk.Dec{"gamm/pool/1": sdk.NewDec(10)},
+		},
+		{
+			"with single validator and additional delegations",
+			[]stakingtypes.BondStatus{stakingtypes.Bonded},
+			[]superfluidDelegation{{0, 0, 0, 1000000}, {0, 0, 0, 1000000}},
+			map[string]sdk.Dec{"gamm/pool/1": sdk.NewDec(10)},
+		},
+		{
+			"with multiple validator and multiple superfluid delegations",
+			[]stakingtypes.BondStatus{stakingtypes.Bonded, stakingtypes.Bonded},
+			[]superfluidDelegation{{0, 0, 0, 1000000}, {1, 1, 0, 1000000}},
+			map[string]sdk.Dec{"gamm/pool/1": sdk.NewDec(10)},
+		},
+		{
+			"with single validator and multiple denom superfluid delegations",
+			[]stakingtypes.BondStatus{stakingtypes.Bonded, stakingtypes.Bonded},
+			[]superfluidDelegation{{0, 0, 0, 1000000}, {0, 0, 1, 1000000}},
+			map[string]sdk.Dec{"gamm/pool/1": sdk.NewDec(10), "gamm/pool/2": sdk.NewDec(10)},
+		},
+		{
+			"with multiple validators and multiple denom superfluid delegations",
+			[]stakingtypes.BondStatus{stakingtypes.Bonded, stakingtypes.Bonded},
+			[]superfluidDelegation{{0, 0, 0, 1000000}, {0, 1, 1, 1000000}},
+			map[string]sdk.Dec{"gamm/pool/1": sdk.NewDec(10), "gamm/pool/2": sdk.NewDec(10)},
+		},
+		{
+			"zero price multiplier check",
+			[]stakingtypes.BondStatus{stakingtypes.Bonded},
+			[]superfluidDelegation{{0, 0, 0, 1000000}},
+			map[string]sdk.Dec{"gamm/pool/1": sdk.NewDec(0)},
+		},
+		{
+			"dust price multiplier check",
+			[]stakingtypes.BondStatus{stakingtypes.Bonded},
+			[]superfluidDelegation{{0, 0, 0, 1000000}},
+			map[string]sdk.Dec{"gamm/pool/1": sdk.NewDecWithPrec(1, 10)}, // 10^-10
+		},
+	}
+
+	for _, tc := range testCases {
+		tc := tc
+		suite.Run(tc.name, func() {
+			suite.SetupTest()
+
+			// setup validators
+			valAddrs := suite.SetupValidators(tc.validatorStats)
+
+			denoms, _ := suite.SetupGammPoolsAndSuperfluidAssets([]sdk.Dec{sdk.NewDec(20), sdk.NewDec(20)})
+
+			// setup superfluid delegations
+			_, intermediaryAccs, locks := suite.setupSuperfluidDelegations(valAddrs, tc.superDelegations, denoms)
+			suite.checkIntermediaryAccountDelegations(intermediaryAccs)
+
+			// we make a map of intermediary account to delegation shares to store delegation share
+			// before refreshing intermediary account delegations on epoch
+			interAccIndexToDenomShare := make(map[int]sdk.Dec)
+			for accIndex, intermediaryAcc := range intermediaryAccs {
+				valAddr, err := sdk.ValAddressFromBech32(intermediaryAcc.ValAddr)
+				suite.Require().NoError(err)
+				delegation, found := suite.App.StakingKeeper.GetDelegation(suite.Ctx, intermediaryAcc.GetAccAddress(), valAddr)
+				suite.Require().True(found)
+
+				interAccIndexToDenomShare[accIndex] = delegation.Shares
+			}
+
+			for denom, multiplier := range tc.multipliersByDenom {
+				suite.App.SuperfluidKeeper.SetOsmoEquivalentMultiplier(suite.Ctx, 2, denom, multiplier)
+			}
+
+			suite.App.SuperfluidKeeper.RefreshIntermediaryDelegationAmounts(suite.Ctx)
+
+			originalMultiplier := sdk.NewDec(20)
+			for interAccIndex, intermediaryAcc := range intermediaryAccs {
+				multiplier := tc.multipliersByDenom[intermediaryAcc.Denom]
+				oldDelegation := interAccIndexToDenomShare[interAccIndex]
+				expDelegation := oldDelegation.Mul(multiplier).Quo(originalMultiplier)
+				lpTokenAmount := sdk.NewInt(1000000)
+				decAmt := multiplier.Mul(lpTokenAmount.ToDec())
+				asset := suite.App.SuperfluidKeeper.GetSuperfluidAsset(suite.Ctx, intermediaryAcc.Denom)
+				expAmount := suite.App.SuperfluidKeeper.GetRiskAdjustedOsmoValue(suite.Ctx, asset, decAmt.RoundInt())
+
+				// check delegation changes
+				valAddr, err := sdk.ValAddressFromBech32(intermediaryAcc.ValAddr)
+				suite.Require().NoError(err)
+				delegation, found := suite.App.StakingKeeper.GetDelegation(suite.Ctx, intermediaryAcc.GetAccAddress(), valAddr)
+				if expAmount.IsPositive() {
+					suite.Require().True(found)
+					suite.Require().Equal(delegation.Shares, expDelegation)
+				} else {
+					suite.Require().False(found)
+				}
+			}
+
+			// unbond all lockups
+			for _, lock := range locks {
+				// superfluid undelegate
+				// handling the case same lockup is used for further delegation
+				cacheCtx, write := suite.Ctx.CacheContext()
+				err := suite.App.SuperfluidKeeper.SuperfluidUndelegate(cacheCtx, lock.Owner, lock.ID)
+				if err == nil {
+					write()
+				}
+			}
+			unbondingDuration := suite.App.StakingKeeper.GetParams(suite.Ctx).UnbondingTime
+
+			for _, intermediaryAcc := range intermediaryAccs {
+				suite.Ctx = suite.Ctx.WithBlockTime(suite.Ctx.BlockTime().Add(unbondingDuration + time.Second))
+				suite.App.EndBlocker(suite.Ctx, abci.RequestEndBlock{Height: suite.Ctx.BlockHeight()})
+
+				unbonded := suite.App.BankKeeper.GetBalance(suite.Ctx, intermediaryAcc.GetAccAddress(), sdk.DefaultBondDenom)
+				suite.Require().True(unbonded.IsZero())
+			}
+
+			// refresh intermediary account delegations
+			suite.App.SuperfluidKeeper.RefreshIntermediaryDelegationAmounts(suite.Ctx)
+
+			for _, intermediaryAcc := range intermediaryAccs {
+				// check unbonded amount is removed after refresh operation
+				refreshed := suite.App.BankKeeper.GetBalance(suite.Ctx, intermediaryAcc.GetAccAddress(), sdk.DefaultBondDenom)
+				suite.Require().True(refreshed.IsZero())
+			}
+
+		})
+	}
+}
+
+// type superfluidRedelegation struct {
+// 	lockId      uint64
+// 	oldValIndex int64
+// 	newValIndex int64
+// }
+
 // func (suite *KeeperTestSuite) TestSuperfluidRedelegate() {
 // 	testCases := []struct {
 // 		name                    string
@@ -676,367 +674,3 @@ func (suite *KeeperTestSuite) TestSuperfluidUnbondLock() {
 // 		})
 // 	}
 // }
-
-func (suite *KeeperTestSuite) TestRefreshIntermediaryDelegationAmounts() {
-	testCases := []struct {
-		name                string
-		validatorStats      []stakingtypes.BondStatus
-		delegatorNumber     int
-		superDelegations    []superfluidDelegation
-		roundOneMultipliers []osmoEquivalentMultiplier
-		roundTwoMultipliers []osmoEquivalentMultiplier
-		checkAccIndexes     []int64
-	}{
-		{
-			"with single validator and single delegation",
-			[]stakingtypes.BondStatus{stakingtypes.Bonded},
-			1,
-			[]superfluidDelegation{{0, 0, 0, 1000000}},
-			[]osmoEquivalentMultiplier{{0, sdk.NewDec(10)}},
-			[]osmoEquivalentMultiplier{},
-			[]int64{0},
-		},
-		{
-			"with single validator and additional delegations",
-			[]stakingtypes.BondStatus{stakingtypes.Bonded},
-			1,
-			[]superfluidDelegation{{0, 0, 0, 1000000}, {0, 0, 0, 1000000}},
-			[]osmoEquivalentMultiplier{{0, sdk.NewDec(10)}},
-			[]osmoEquivalentMultiplier{},
-			[]int64{0},
-		},
-		{
-			"with multiple validator and multiple superfluid delegations",
-			[]stakingtypes.BondStatus{stakingtypes.Bonded, stakingtypes.Bonded},
-			2,
-			[]superfluidDelegation{{0, 0, 0, 1000000}, {1, 1, 0, 1000000}},
-			[]osmoEquivalentMultiplier{{0, sdk.NewDec(10)}},
-			[]osmoEquivalentMultiplier{},
-			[]int64{0, 1},
-		},
-		{
-			"with single validator and multiple denom superfluid delegations",
-			[]stakingtypes.BondStatus{stakingtypes.Bonded, stakingtypes.Bonded},
-			2,
-			[]superfluidDelegation{{0, 0, 0, 1000000}, {0, 0, 1, 1000000}},
-			[]osmoEquivalentMultiplier{{0, sdk.NewDec(10)}, {1, sdk.NewDec(10)}},
-			[]osmoEquivalentMultiplier{},
-			[]int64{0, 1},
-		},
-		{
-			"with multiple validators and multiple denom superfluid delegations",
-			[]stakingtypes.BondStatus{stakingtypes.Bonded, stakingtypes.Bonded},
-			2,
-			[]superfluidDelegation{{0, 0, 0, 1000000}, {0, 1, 1, 1000000}},
-			[]osmoEquivalentMultiplier{{0, sdk.NewDec(10)}, {1, sdk.NewDec(10)}},
-			[]osmoEquivalentMultiplier{},
-			[]int64{0, 1},
-		},
-		{
-			"zero price multiplier check",
-			[]stakingtypes.BondStatus{stakingtypes.Bonded},
-			2,
-			[]superfluidDelegation{{0, 0, 0, 1000000}},
-			[]osmoEquivalentMultiplier{{0, sdk.NewDec(0)}},
-			[]osmoEquivalentMultiplier{},
-			[]int64{0},
-		},
-		{
-			"refresh case from zero to non-zero",
-			[]stakingtypes.BondStatus{stakingtypes.Bonded},
-			2,
-			[]superfluidDelegation{{0, 0, 0, 1000000}},
-			[]osmoEquivalentMultiplier{{0, sdk.NewDec(0)}},
-			[]osmoEquivalentMultiplier{{0, sdk.NewDec(10)}},
-			[]int64{0},
-		},
-		{
-			"dust price multiplier check",
-			[]stakingtypes.BondStatus{stakingtypes.Bonded},
-			2,
-			[]superfluidDelegation{{0, 0, 0, 1000000}},
-			[]osmoEquivalentMultiplier{{0, sdk.NewDecWithPrec(1, 10)}}, // 10^-10
-			[]osmoEquivalentMultiplier{},
-			[]int64{0},
-		},
-		{
-			"refresh case from dust to non-dust",
-			[]stakingtypes.BondStatus{stakingtypes.Bonded},
-			2,
-			[]superfluidDelegation{{0, 0, 0, 1000000}},
-			[]osmoEquivalentMultiplier{{0, sdk.NewDecWithPrec(1, 10)}}, // 10^-10
-			[]osmoEquivalentMultiplier{{0, sdk.NewDec(10)}},
-			[]int64{0},
-		},
-	}
-
-	for _, tc := range testCases {
-		tc := tc
-		suite.Run(tc.name, func() {
-			suite.SetupTest()
-
-			bondDenom := suite.App.StakingKeeper.BondDenom(suite.Ctx)
-
-			// Generate delegator addresses
-			delAddrs := CreateRandomAccounts(tc.delegatorNumber)
-
-			// setup validators
-			valAddrs := suite.SetupValidators(tc.validatorStats)
-
-			denoms, _ := suite.SetupGammPoolsAndSuperfluidAssets([]sdk.Dec{sdk.NewDec(20), sdk.NewDec(20)})
-
-			// setup superfluid delegations
-			intermediaryAccs, locks := suite.SetupSuperfluidDelegations(delAddrs, valAddrs, tc.superDelegations, denoms)
-			suite.checkIntermediaryAccountDelegations(intermediaryAccs)
-			intermediaryDels := []sdk.Dec{}
-
-			for _, intAccIndex := range tc.checkAccIndexes {
-				expAcc := intermediaryAccs[intAccIndex]
-				valAddr, err := sdk.ValAddressFromBech32(expAcc.ValAddr)
-				suite.Require().NoError(err)
-
-				// check delegation from intermediary account to validator
-				delegation, found := suite.App.StakingKeeper.GetDelegation(suite.Ctx, expAcc.GetAccAddress(), valAddr)
-				suite.Require().True(found)
-				intermediaryDels = append(intermediaryDels, delegation.Shares)
-			}
-
-			// multiplier change before refresh
-			multiplierByDenom := make(map[string]sdk.Dec)
-			for _, multiplier := range tc.roundOneMultipliers {
-				denom := denoms[multiplier.lpIndex]
-				multiplierByDenom[denom] = multiplier.price
-				suite.App.SuperfluidKeeper.SetOsmoEquivalentMultiplier(suite.Ctx, 2, denom, multiplier.price)
-			}
-
-			// get pre-superfluid delgations osmo supply and supplyWithOffset
-			presupply := suite.App.BankKeeper.GetSupply(suite.Ctx, bondDenom)
-			presupplyWithOffset := suite.App.BankKeeper.GetSupplyWithOffset(suite.Ctx, bondDenom)
-
-			// refresh intermediary account delegations
-			suite.App.SuperfluidKeeper.RefreshIntermediaryDelegationAmounts(suite.Ctx)
-
-			// ensure post-superfluid delegations osmo supplywithoffset is the same while supply is not
-			postsupply := suite.App.BankKeeper.GetSupply(suite.Ctx, bondDenom)
-			postsupplyWithOffset := suite.App.BankKeeper.GetSupplyWithOffset(suite.Ctx, bondDenom)
-			suite.Require().False(postsupply.IsEqual(presupply), "presupply: %s   postsupply: %s", presupply, postsupply)
-			suite.Require().True(postsupplyWithOffset.IsEqual(presupplyWithOffset))
-
-			originMultiplier := sdk.NewDec(20)
-			for index, intAccIndex := range tc.checkAccIndexes {
-				expAcc := intermediaryAccs[intAccIndex]
-				multiplier, ok := multiplierByDenom[expAcc.Denom]
-				if !ok {
-					multiplier = originMultiplier
-				}
-
-				// calculating the estimated delegation amount for multiplier change
-				expDelegation := intermediaryDels[index].Mul(multiplier).Quo(originMultiplier)
-				lpTokenAmount := sdk.NewInt(1000000)
-				decAmt := multiplier.Mul(lpTokenAmount.ToDec())
-				asset := suite.App.SuperfluidKeeper.GetSuperfluidAsset(suite.Ctx, expAcc.Denom)
-				expAmount := suite.App.SuperfluidKeeper.GetRiskAdjustedOsmoValue(suite.Ctx, asset, decAmt.RoundInt())
-
-				valAddr, err := sdk.ValAddressFromBech32(expAcc.ValAddr)
-				suite.Require().NoError(err)
-
-				// check delegation changes
-				delegation, found := suite.App.StakingKeeper.GetDelegation(suite.Ctx, expAcc.GetAccAddress(), valAddr)
-				if expAmount.IsPositive() {
-					suite.Require().True(found)
-					suite.Require().Equal(delegation.Shares, expDelegation)
-				} else {
-					suite.Require().False(found)
-				}
-			}
-
-			// if second round multipliers exists, execute round two multipliers mock and finish tests
-			if len(tc.roundTwoMultipliers) > 0 {
-				multiplier2ByDenom := make(map[string]sdk.Dec)
-				for _, multiplier := range tc.roundTwoMultipliers {
-					denom := denoms[multiplier.lpIndex]
-					multiplier2ByDenom[denom] = multiplier.price
-					suite.App.SuperfluidKeeper.SetOsmoEquivalentMultiplier(suite.Ctx, 3, denom, multiplier.price)
-				}
-				// refresh intermediary account delegations
-				suite.App.SuperfluidKeeper.RefreshIntermediaryDelegationAmounts(suite.Ctx)
-
-				for index, intAccIndex := range tc.checkAccIndexes {
-					expAcc := intermediaryAccs[intAccIndex]
-					valAddr, err := sdk.ValAddressFromBech32(expAcc.ValAddr)
-					suite.Require().NoError(err)
-
-					expDelegation := intermediaryDels[index].Mul(multiplier2ByDenom[expAcc.Denom]).Quo(originMultiplier)
-
-					// check delegation changes
-					delegation, found := suite.App.StakingKeeper.GetDelegation(suite.Ctx, expAcc.GetAccAddress(), valAddr)
-
-					suite.Require().True(found)
-					suite.Require().Equal(delegation.Shares, expDelegation)
-				}
-				return
-			}
-
-			// unbond all lockups
-			for _, lock := range locks {
-				// superfluid undelegate
-				// handling the case same lockup is used for further delegation
-				cacheCtx, write := suite.Ctx.CacheContext()
-				err := suite.App.SuperfluidKeeper.SuperfluidUndelegate(cacheCtx, lock.Owner, lock.ID)
-				if err == nil {
-					write()
-				}
-			}
-			unbondingDuration := suite.App.StakingKeeper.GetParams(suite.Ctx).UnbondingTime
-
-			// check intermediary account changes after unbonding operations
-			for _, intAccIndex := range tc.checkAccIndexes {
-				expAcc := intermediaryAccs[intAccIndex]
-				suite.Ctx = suite.Ctx.WithBlockTime(suite.Ctx.BlockTime().Add(unbondingDuration + time.Second))
-				suite.App.EndBlocker(suite.Ctx, abci.RequestEndBlock{Height: suite.Ctx.BlockHeight()})
-
-				unbonded := suite.App.BankKeeper.GetBalance(suite.Ctx, expAcc.GetAccAddress(), sdk.DefaultBondDenom)
-				suite.Require().True(unbonded.IsZero())
-			}
-
-			// refresh intermediary account delegations
-			suite.App.SuperfluidKeeper.RefreshIntermediaryDelegationAmounts(suite.Ctx)
-
-			// check if intermediary accounts does not have free balance after refresh operation
-			for _, intAccIndex := range tc.checkAccIndexes {
-				expAcc := intermediaryAccs[intAccIndex]
-				// check unbonded amount is removed after refresh operation
-				refreshed := suite.App.BankKeeper.GetBalance(suite.Ctx, expAcc.GetAccAddress(), sdk.DefaultBondDenom)
-				suite.Require().True(refreshed.IsZero())
-			}
-		})
-	}
-}
-
-func (suite *KeeperTestSuite) TestSuperfluidDelegationGovernanceVoting() {
-	testCases := []struct {
-		name              string
-		validatorStats    []stakingtypes.BondStatus
-		superDelegations  [][]superfluidDelegation
-		normalDelegations []normalDelegation
-	}{
-		{
-			"with single validator and single delegation",
-			[]stakingtypes.BondStatus{stakingtypes.Bonded},
-			[][]superfluidDelegation{{{0, 0, 0, 1000000}}},
-			nil,
-		},
-		{
-			"with single validator and additional delegations",
-			[]stakingtypes.BondStatus{stakingtypes.Bonded},
-			[][]superfluidDelegation{{{0, 0, 0, 1000000}, {0, 0, 0, 1000000}}},
-			nil,
-		},
-		{
-			"with multiple validator and multiple superfluid delegations",
-			[]stakingtypes.BondStatus{stakingtypes.Bonded, stakingtypes.Bonded},
-			[][]superfluidDelegation{{{0, 0, 0, 1000000}}, {{1, 1, 0, 1000000}}},
-			nil,
-		},
-		{
-			"with single validator and multiple denom superfluid delegations",
-			[]stakingtypes.BondStatus{stakingtypes.Bonded, stakingtypes.Bonded},
-			[][]superfluidDelegation{{{0, 0, 0, 1000000}, {0, 0, 1, 1000000}}},
-			nil,
-		},
-		{
-			"with multiple validators and multiple denom superfluid delegations",
-			[]stakingtypes.BondStatus{stakingtypes.Bonded, stakingtypes.Bonded},
-			[][]superfluidDelegation{{{0, 0, 0, 1000000}, {0, 1, 1, 1000000}}},
-			nil,
-		},
-		{
-			"many delegations",
-			[]stakingtypes.BondStatus{stakingtypes.Bonded, stakingtypes.Bonded},
-			[][]superfluidDelegation{
-				{{0, 0, 0, 1000000}, {0, 1, 1, 1000000}},
-				{{1, 0, 0, 1000000}, {1, 0, 1, 1000000}},
-				{{2, 1, 1, 1000000}, {2, 1, 0, 1000000}},
-				{{3, 0, 0, 1000000}, {3, 1, 1, 1000000}},
-			},
-			nil,
-		},
-		{
-			"with normal delegations",
-			[]stakingtypes.BondStatus{stakingtypes.Bonded},
-			[][]superfluidDelegation{
-				{{0, 0, 0, 1000000}, {0, 0, 1, 1000000}},
-			},
-			[]normalDelegation{
-				{0, 0, 1000000},
-			},
-		},
-	}
-
-	for _, tc := range testCases {
-		tc := tc
-
-		suite.Run(tc.name, func() {
-			suite.SetupTest()
-
-			denoms, _ := suite.SetupGammPoolsAndSuperfluidAssets([]sdk.Dec{sdk.NewDec(20), sdk.NewDec(20)})
-
-			// Generate delegator addresses
-			delAddrs := CreateRandomAccounts(len(tc.superDelegations))
-
-			// setup validators
-			valAddrs := suite.SetupValidators(tc.validatorStats)
-
-			// setup superfluid delegations
-			for _, sfdel := range tc.superDelegations {
-				intermediaryAccs, _ := suite.SetupSuperfluidDelegations(delAddrs, valAddrs, sfdel, denoms)
-				suite.checkIntermediaryAccountDelegations(intermediaryAccs)
-			}
-
-			// setup normal delegations
-			for _, del := range tc.normalDelegations {
-				err := suite.SetupNormalDelegation(delAddrs, valAddrs, del)
-				suite.NoError(err)
-			}
-
-			// all expected delegated amounts to a validator from a delegator
-			delegatedAmount := func(delidx, validx int) sdk.Int {
-				res := sdk.ZeroInt()
-				for _, del := range tc.superDelegations[delidx] {
-					if del.valIndex == int64(validx) {
-						res = res.AddRaw(del.lpAmount)
-					}
-				}
-				if len(tc.normalDelegations) != 0 {
-					del := tc.normalDelegations[delidx]
-					res = res.AddRaw(del.coinAmount / 10) // LP price is 10 osmo in this test
-				}
-				return res
-			}
-			for delidx := range tc.superDelegations {
-				// store all actual delegations to a validator
-				sharePerValidatorMap := make(map[string]sdk.Dec)
-				for validx := range tc.validatorStats {
-					sharePerValidatorMap[valAddrs[validx].String()] = sdk.ZeroDec()
-				}
-				addToSharePerValidatorMap := func(val sdk.ValAddress, share sdk.Dec) {
-					if existing, ok := sharePerValidatorMap[val.String()]; ok {
-						share.AddMut(existing)
-					}
-					sharePerValidatorMap[val.String()] = share
-				}
-
-				// iterate delegations and add eligible shares to the sharePerValidatorMap
-				suite.App.SuperfluidKeeper.IterateDelegations(suite.Ctx, delAddrs[delidx], func(_ int64, del stakingtypes.DelegationI) bool {
-					addToSharePerValidatorMap(del.GetValidatorAddr(), del.GetShares())
-					return false
-				})
-
-				// check if the expected delegated amount equals to actual
-				for validx := range tc.validatorStats {
-					suite.Equal(delegatedAmount(delidx, validx).Int64()*10, sharePerValidatorMap[valAddrs[validx].String()].RoundInt().Int64())
-				}
-			}
-		})
-	}
-}
diff --git a/x/txfees/keeper/hooks_test.go b/x/txfees/keeper/hooks_test.go
index 9995ea275..6b5f97b1e 100644
--- a/x/txfees/keeper/hooks_test.go
+++ b/x/txfees/keeper/hooks_test.go
@@ -64,7 +64,7 @@ func (suite *KeeperTestSuite) TestTxFeesAfterEpochEnd() {
 		},
 	}
 
-	var finalOutputAmount = sdk.NewInt(0)
+	finalOutputAmount := sdk.NewInt(0)
 
 	for _, tc := range tests {
 		tc := tc