Repository: osmosis-labs/osmosis
Pull request #5269 (2023-05-23 10:03:13)

More test simplification
<!-- < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < ☺
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!
☺ > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > >  -->

## What is the purpose of the change

Remove more lines of code from tests, fixes some bugs.

- Merges a lot of the boilerplate for sqrt price rounding tests
- makes one, zero and sqrt(5000) a constant we can reuse
- Fixes locations where we see `three = 2` by accident
- Deletes unused configuration in tests
- Abstract lock state in lock state tests
- Abstract validate basic tests
- Remove redundant lines in incentives_test.go
- Push complexity for edge case tests for Growth Inside/Outside range to its own test
- Combine GrowthInside and GrowthOutside test cases together.

## Testing and Verifying

This change is a trivial rework / code cleanup without any test coverage.

## Suggested review strategy

- LP_test.go can be reviewed pretty easily via the diff viewer
- math_test.go can be reviewed pretty easily via the diff viewer
- fees_test & swaps_test & export_test don't really have any meaningful change
- swap_strategy can be reviewed line by line, and checking that things were copied into `swap_strategy_test.go` correctly
- msgs_test.go can be reviewed pretty easily via the diff viewer
- incentives_test.go
  - for TestGetUptimeGrowthRange, check that the new OutsideRange field makes sense (these were all copied from elsewhere)
  - for TestQueryAndCollectIncentives, can be reviewed extremely easily line by line.



Patch:
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index bb472acee..327de5f6a 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -5,10 +5,15 @@ updates:
   schedule:
     interval: daily
   open-pull-requests-limit: 10
+  labels:
+    - "A:no-changelog"
+    - "V:state/compatible/no_backport"
 - package-ecosystem: gomod
   directory: "/"
   schedule:
     interval: weekly
+  labels:
+    - "A:no-changelog"
   ignore:
     - dependency-name: "github.com/tendermint/tendermint"
       update-types: ["version-update:semver-major", "version-update:semver-minor"]
diff --git a/.github/mergify.yml b/.github/mergify.yml
index e9d4385aa..813908c8b 100644
--- a/.github/mergify.yml
+++ b/.github/mergify.yml
@@ -20,8 +20,8 @@ pull_request_rules:
         name: default
         method: squash
         commit_message_template: |
-           {{ title }} (#{{ number }})
-           {{ body }}
+          {{ title }} (#{{ number }})
+          {{ body }}
   - name: backport patches to v3.x branch
     conditions:
       - base=main
@@ -102,3 +102,11 @@ pull_request_rules:
       backport:
         branches:
           - v15.x
+  - name: backport patches to v16.x branch
+    conditions:
+      - base=main
+      - label=A:backport/v16.x
+    actions:
+      backport:
+        branches:
+          - v16.x
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7e605d96a..a7e6f5181 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -70,6 +70,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
   * [#5165](https://github.com/osmosis-labs/osmosis/pull/5165) Improve error message when fully exiting from a pool.
   * [#5187](https://github.com/osmosis-labs/osmosis/pull/5187) Expand `IncentivizedPools` query to include internally incentivized CL pools.
   * [#5239](https://github.com/osmosis-labs/osmosis/pull/5239) Implement `GetTotalPoolShares` public keeper function for GAMM.
+  * [#5261](https://github.com/osmosis-labs/osmosis/pull/5261) Allows `UpdateFeeTokenProposal` to take in multiple fee tokens instead of just one.
   
 ### API breaks
 
diff --git a/go.mod b/go.mod
index 85d0f29b8..39bc772c6 100644
--- a/go.mod
+++ b/go.mod
@@ -317,8 +317,8 @@ replace (
 	github.com/CosmWasm/wasmd => github.com/osmosis-labs/wasmd v0.31.0-osmo-v16
 	// dragonberry
 	github.com/confio/ics23/go => github.com/cosmos/cosmos-sdk/ics23/go v0.8.0
-	// Our cosmos-sdk branch is:  https://github.com/osmosis-labs/cosmos-sdk, current branch: v16.x. Direct commit link: https://github.com/osmosis-labs/cosmos-sdk/commit/43c58d9061e3b8e0f06c3d9efef8c728800ab554
-	github.com/cosmos/cosmos-sdk => github.com/osmosis-labs/cosmos-sdk v0.45.1-0.20230326212251-7a2cf2993434
+	// Our cosmos-sdk branch is:  https://github.com/osmosis-labs/cosmos-sdk, current branch: v16.x. Direct commit link: https://github.com/osmosis-labs/cosmos-sdk/commit/193959b898ecdcae36b52f97927e6a0a4389e98c
+	github.com/cosmos/cosmos-sdk => github.com/osmosis-labs/cosmos-sdk v0.45.1-0.20230523200430-193959b898ec
 
 	// N.B. v0.19.5 contains a breaking change to the IAVL API
 	github.com/cosmos/iavl v0.19.5 => github.com/cosmos/iavl v0.19.4
diff --git a/go.sum b/go.sum
index f59f480a0..20a2215dc 100644
--- a/go.sum
+++ b/go.sum
@@ -932,8 +932,8 @@ github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnh
 github.com/ory/dockertest v3.3.5+incompatible h1:iLLK6SQwIhcbrG783Dghaaa3WPzGc+4Emza6EbVUUGA=
 github.com/ory/dockertest/v3 v3.10.0 h1:4K3z2VMe8Woe++invjaTB7VRyQXQy5UY+loujO4aNE4=
 github.com/ory/dockertest/v3 v3.10.0/go.mod h1:nr57ZbRWMqfsdGdFNLHz5jjNdDb7VVFnzAeW1n5N1Lg=
-github.com/osmosis-labs/cosmos-sdk v0.45.1-0.20230326212251-7a2cf2993434 h1:RetElHdhDl6f00Tjj7ii2r+HX2aa/u+dhgwQb5hKv8Y=
-github.com/osmosis-labs/cosmos-sdk v0.45.1-0.20230326212251-7a2cf2993434/go.mod h1:ss3tUfPTwaa6NsoPZrCR7xOqLqCK0LwoNbc2Q8Zs5/Y=
+github.com/osmosis-labs/cosmos-sdk v0.45.1-0.20230523200430-193959b898ec h1:p7tmT1OljDKFAue6FuKqE9WlFUO7Z0hXcWKEPzFTKBE=
+github.com/osmosis-labs/cosmos-sdk v0.45.1-0.20230523200430-193959b898ec/go.mod h1:ss3tUfPTwaa6NsoPZrCR7xOqLqCK0LwoNbc2Q8Zs5/Y=
 github.com/osmosis-labs/go-mutesting v0.0.0-20221208041716-b43bcd97b3b3 h1:YlmchqTmlwdWSmrRmXKR+PcU96ntOd8u10vTaTZdcNY=
 github.com/osmosis-labs/go-mutesting v0.0.0-20221208041716-b43bcd97b3b3/go.mod h1:lV6KnqXYD/ayTe7310MHtM3I2q8Z6bBfMAi+bhwPYtI=
 github.com/osmosis-labs/osmosis/osmomath v0.0.3-dev.0.20230516205127-c213fddde069 h1:ZgDrTJ2GCH4CJGbV6rudw4O9rPMAuwWoLVZnG6cUr+A=
diff --git a/osmomath/go.mod b/osmomath/go.mod
index 8f94e4688..b988e7e0f 100644
--- a/osmomath/go.mod
+++ b/osmomath/go.mod
@@ -4,7 +4,7 @@ go 1.20
 
 require (
 	github.com/cosmos/cosmos-sdk v0.47.2
-	github.com/stretchr/testify v1.8.2
+	github.com/stretchr/testify v1.8.3
 	gopkg.in/yaml.v2 v2.4.0
 )
 
@@ -26,7 +26,6 @@ require (
 	github.com/dgraph-io/ristretto v0.1.0 // indirect
 	github.com/dustin/go-humanize v1.0.1-0.20200219035652-afde56e7acac // indirect
 	github.com/felixge/httpsnoop v1.0.2 // indirect
-	github.com/frankban/quicktest v1.14.4 // indirect
 	github.com/fsnotify/fsnotify v1.6.0 // indirect
 	github.com/go-kit/kit v0.12.0 // indirect
 	github.com/go-kit/log v0.2.1 // indirect
@@ -67,7 +66,7 @@ require (
 	github.com/rogpeppe/go-internal v1.10.0 // indirect
 	github.com/sasha-s/go-deadlock v0.3.1 // indirect
 	github.com/spf13/afero v1.9.3 // indirect
-	github.com/spf13/cast v1.5.0 // indirect
+	github.com/spf13/cast v1.5.1 // indirect
 	github.com/spf13/cobra v1.7.0 // indirect
 	github.com/spf13/jwalterweatherman v1.1.0 // indirect
 	github.com/spf13/pflag v1.0.5 // indirect
@@ -91,8 +90,8 @@ require (
 )
 
 replace (
-	// Our cosmos-sdk branch is:  https://github.com/osmosis-labs/cosmos-sdk, current branch: v16.x. Direct commit link: https://github.com/osmosis-labs/cosmos-sdk/commit/43c58d9061e3b8e0f06c3d9efef8c728800ab554
-	github.com/cosmos/cosmos-sdk => github.com/osmosis-labs/cosmos-sdk v0.45.1-0.20230326212251-7a2cf2993434
+	// Our cosmos-sdk branch is:  https://github.com/osmosis-labs/cosmos-sdk, current branch: v16.x. Direct commit link: https://github.com/osmosis-labs/cosmos-sdk/commit/193959b898ecdcae36b52f97927e6a0a4389e98c
+	github.com/cosmos/cosmos-sdk => github.com/osmosis-labs/cosmos-sdk v0.45.1-0.20230523200430-193959b898ec
 	// use cosmos-compatible protobufs
 	github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1
 	github.com/tendermint/tendermint => github.com/informalsystems/tendermint v0.34.24
diff --git a/osmomath/go.sum b/osmomath/go.sum
index beca09192..0fe2d6187 100644
--- a/osmomath/go.sum
+++ b/osmomath/go.sum
@@ -298,8 +298,7 @@ github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7J
 github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
 github.com/onsi/gomega v1.26.0 h1:03cDLK28U6hWvCAns6NeydX3zIm4SF3ci69ulidS32Q=
 github.com/onsi/gomega v1.26.0/go.mod h1:r+zV744Re+DiYCIPRlYOTxn0YkOLcAnW8k1xXdMPGhM=
-github.com/osmosis-labs/cosmos-sdk v0.45.1-0.20230326212251-7a2cf2993434 h1:RetElHdhDl6f00Tjj7ii2r+HX2aa/u+dhgwQb5hKv8Y=
-github.com/osmosis-labs/cosmos-sdk v0.45.1-0.20230326212251-7a2cf2993434/go.mod h1:ss3tUfPTwaa6NsoPZrCR7xOqLqCK0LwoNbc2Q8Zs5/Y=
+github.com/osmosis-labs/cosmos-sdk v0.45.1-0.20230523200430-193959b898ec h1:p7tmT1OljDKFAue6FuKqE9WlFUO7Z0hXcWKEPzFTKBE=
 github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY=
 github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
 github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
@@ -337,7 +336,6 @@ github.com/regen-network/cosmos-proto v0.3.1 h1:rV7iM4SSFAagvy8RiyhiACbWEGotmqzy
 github.com/regen-network/protobuf v1.3.3-alpha.regen.1 h1:OHEc+q5iIAXpqiqFKeLpu5NwTIkVXUs48vFMwzqpqY4=
 github.com/regen-network/protobuf v1.3.3-alpha.regen.1/go.mod h1:2DjTFR1HhMQhiWC5sZ4OhQ3+NtdbZ6oBDKQwq5Ou+FI=
 github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
-github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
 github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
 github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
 github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
@@ -352,8 +350,7 @@ github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B
 github.com/spf13/afero v1.9.3 h1:41FoI0fD7OR7mGcKE/aOiLkGreyf8ifIOQmJANWogMk=
 github.com/spf13/afero v1.9.3/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y=
 github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
-github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w=
-github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU=
+github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA=
 github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
 github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I=
 github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
@@ -377,8 +374,7 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
 github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
 github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
-github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
-github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
+github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY=
 github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8=
 github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0=
 github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY=
diff --git a/osmoutils/go.mod b/osmoutils/go.mod
index b1420af89..8b9122343 100644
--- a/osmoutils/go.mod
+++ b/osmoutils/go.mod
@@ -9,7 +9,7 @@ require (
 	github.com/gogo/protobuf v1.3.3
 	github.com/spf13/cobra v1.7.0
 	github.com/spf13/pflag v1.0.5
-	github.com/stretchr/testify v1.8.2
+	github.com/stretchr/testify v1.8.3
 	github.com/tendermint/tendermint v0.34.26
 	github.com/tendermint/tm-db v0.6.8-0.20220506192307-f628bb5dc95b
 	golang.org/x/exp v0.0.0-20230131160201-f062dba9d201
@@ -43,7 +43,6 @@ require (
 	github.com/dustin/go-humanize v1.0.1-0.20200219035652-afde56e7acac // indirect
 	github.com/dvsekhvalnov/jose2go v1.5.0 // indirect
 	github.com/felixge/httpsnoop v1.0.2 // indirect
-	github.com/frankban/quicktest v1.14.4 // indirect
 	github.com/fsnotify/fsnotify v1.6.0 // indirect
 	github.com/gin-gonic/gin v1.8.1 // indirect
 	github.com/go-kit/kit v0.12.0 // indirect
@@ -108,7 +107,7 @@ require (
 	github.com/rs/zerolog v1.27.0 // indirect
 	github.com/sasha-s/go-deadlock v0.3.1 // indirect
 	github.com/spf13/afero v1.9.3 // indirect
-	github.com/spf13/cast v1.5.0 // indirect
+	github.com/spf13/cast v1.5.1 // indirect
 	github.com/spf13/jwalterweatherman v1.1.0 // indirect
 	github.com/spf13/viper v1.15.0 // indirect
 	github.com/subosito/gotenv v1.4.2 // indirect
@@ -136,8 +135,8 @@ require (
 )
 
 replace (
-	// Our cosmos-sdk branch is:  https://github.com/osmosis-labs/cosmos-sdk, current branch: v16.x. Direct commit link: https://github.com/osmosis-labs/cosmos-sdk/commit/43c58d9061e3b8e0f06c3d9efef8c728800ab554
-	github.com/cosmos/cosmos-sdk => github.com/osmosis-labs/cosmos-sdk v0.45.1-0.20230326212251-7a2cf2993434
+	// Our cosmos-sdk branch is:  https://github.com/osmosis-labs/cosmos-sdk, current branch: v16.x. Direct commit link: https://github.com/osmosis-labs/cosmos-sdk/commit/193959b898ecdcae36b52f97927e6a0a4389e98c
+	github.com/cosmos/cosmos-sdk => github.com/osmosis-labs/cosmos-sdk v0.45.1-0.20230523200430-193959b898ec
 	// use cosmos-compatible protobufs
 	github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1
 	github.com/tendermint/tendermint => github.com/informalsystems/tendermint v0.34.24
diff --git a/osmoutils/go.sum b/osmoutils/go.sum
index 83551dba0..50ad66bc5 100644
--- a/osmoutils/go.sum
+++ b/osmoutils/go.sum
@@ -680,8 +680,7 @@ github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJ
 github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
 github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
 github.com/ory/dockertest v3.3.5+incompatible h1:iLLK6SQwIhcbrG783Dghaaa3WPzGc+4Emza6EbVUUGA=
-github.com/osmosis-labs/cosmos-sdk v0.45.1-0.20230326212251-7a2cf2993434 h1:RetElHdhDl6f00Tjj7ii2r+HX2aa/u+dhgwQb5hKv8Y=
-github.com/osmosis-labs/cosmos-sdk v0.45.1-0.20230326212251-7a2cf2993434/go.mod h1:ss3tUfPTwaa6NsoPZrCR7xOqLqCK0LwoNbc2Q8Zs5/Y=
+github.com/osmosis-labs/cosmos-sdk v0.45.1-0.20230523200430-193959b898ec h1:p7tmT1OljDKFAue6FuKqE9WlFUO7Z0hXcWKEPzFTKBE=
 github.com/otiai10/copy v1.7.0 h1:hVoPiN+t+7d2nzzwMiDHPSOogsWAStewq3TwU05+clE=
 github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM=
 github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
@@ -757,7 +756,6 @@ github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRr
 github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
 github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
 github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
-github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
 github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
 github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
 github.com/rs/cors v1.8.2 h1:KCooALfAYGs415Cwu5ABvv9n9509fSiG5SQJn/AQo4U=
@@ -795,8 +793,7 @@ github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B
 github.com/spf13/afero v1.9.3 h1:41FoI0fD7OR7mGcKE/aOiLkGreyf8ifIOQmJANWogMk=
 github.com/spf13/afero v1.9.3/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y=
 github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
-github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w=
-github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU=
+github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA=
 github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
 github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
 github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I=
@@ -829,8 +826,7 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
 github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
 github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
-github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
-github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
+github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY=
 github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8=
 github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0=
 github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY=
diff --git a/proto/osmosis/txfees/v1beta1/gov.proto b/proto/osmosis/txfees/v1beta1/gov.proto
index ab251d982..f2b9891de 100644
--- a/proto/osmosis/txfees/v1beta1/gov.proto
+++ b/proto/osmosis/txfees/v1beta1/gov.proto
@@ -8,11 +8,11 @@ import "osmosis/txfees/v1beta1/feetoken.proto";
 
 option go_package = "github.com/osmosis-labs/osmosis/v15/x/txfees/types";
 
-// UpdateFeeTokenProposal is a gov Content type for adding a new whitelisted fee
-// token. It must specify a denom along with gamm pool ID to use as a spot price
-// calculator. It can be used to add a new denom to the whitelist It can also be
-// used to update the Pool to associate with the denom. If Pool ID is set to 0,
-// it will remove the denom from the whitelisted set.
+// UpdateFeeTokenProposal is a gov Content type for adding new whitelisted fee
+// token(s). It must specify a denom along with gamm pool ID to use as a spot
+// price calculator. It can be used to add new denoms to the whitelist. It can
+// also be used to update the Pool to associate with the denom. If Pool ID is
+// set to 0, it will remove the denom from the whitelisted set.
 message UpdateFeeTokenProposal {
   option (gogoproto.equal) = true;
   option (gogoproto.goproto_getters) = false;
@@ -22,8 +22,8 @@ message UpdateFeeTokenProposal {
 
   string title = 1 [ (gogoproto.moretags) = "yaml:\"title\"" ];
   string description = 2 [ (gogoproto.moretags) = "yaml:\"description\"" ];
-  FeeToken feetoken = 3 [
-    (gogoproto.moretags) = "yaml:\"fee_token\"",
+  repeated FeeToken feetokens = 3 [
+    (gogoproto.moretags) = "yaml:\"fee_tokens\"",
     (gogoproto.nullable) = false
   ];
 }
\ No newline at end of file
diff --git a/x/concentrated-liquidity/types/codec.go b/x/concentrated-liquidity/types/codec.go
index 218156490..a764d088c 100644
--- a/x/concentrated-liquidity/types/codec.go
+++ b/x/concentrated-liquidity/types/codec.go
@@ -17,7 +17,7 @@ func RegisterCodec(cdc *codec.LegacyAmino) {
 	cdc.RegisterConcrete(&MsgCollectFees{}, "osmosis/cl-collect-fees", nil)
 	cdc.RegisterConcrete(&MsgCollectIncentives{}, "osmosis/cl-collect-incentives", nil)
 	cdc.RegisterConcrete(&MsgFungifyChargedPositions{}, "osmosis/cl-fungify-charged-positions", nil)
-	cdc.RegisterConcrete(&CreateConcentratedLiquidityPoolProposal{}, "osmosis/cretae-concentrated-liquidity-pool-proposal", nil)
+	cdc.RegisterConcrete(&CreateConcentratedLiquidityPoolProposal{}, "osmosis/create-concentrated-liquidity-pool-proposal", nil)
 	cdc.RegisterConcrete(&TickSpacingDecreaseProposal{}, "osmosis/cl-tick-spacing-dec-prop", nil)
 }
 
diff --git a/x/epochs/go.mod b/x/epochs/go.mod
index 88aad93ad..9d50015be 100644
--- a/x/epochs/go.mod
+++ b/x/epochs/go.mod
@@ -10,7 +10,7 @@ require (
 	github.com/grpc-ecosystem/grpc-gateway v1.16.0
 	github.com/osmosis-labs/osmosis/osmoutils v0.0.0-20230510161551-8bf252f26bae
 	github.com/spf13/cobra v1.7.0
-	github.com/stretchr/testify v1.8.2
+	github.com/stretchr/testify v1.8.3
 	github.com/tendermint/tendermint v0.34.26
 	golang.org/x/exp v0.0.0-20230131160201-f062dba9d201
 	google.golang.org/genproto v0.0.0-20230125152338-dcaf20b6aeaa
@@ -101,7 +101,7 @@ require (
 	github.com/rs/zerolog v1.27.0 // indirect
 	github.com/sasha-s/go-deadlock v0.3.1 // indirect
 	github.com/spf13/afero v1.9.3 // indirect
-	github.com/spf13/cast v1.5.0 // indirect
+	github.com/spf13/cast v1.5.1 // indirect
 	github.com/spf13/jwalterweatherman v1.1.0 // indirect
 	github.com/spf13/pflag v1.0.5 // indirect
 	github.com/spf13/viper v1.15.0 // indirect
@@ -131,8 +131,8 @@ require (
 
 // use cosmos-compatible protobufs
 replace (
-	// Our cosmos-sdk branch is:  https://github.com/osmosis-labs/cosmos-sdk, current branch: v16.x. Direct commit link: https://github.com/osmosis-labs/cosmos-sdk/commit/43c58d9061e3b8e0f06c3d9efef8c728800ab554
-	github.com/cosmos/cosmos-sdk => github.com/osmosis-labs/cosmos-sdk v0.45.1-0.20230326212251-7a2cf2993434
+	// Our cosmos-sdk branch is:  https://github.com/osmosis-labs/cosmos-sdk, current branch: v16.x. Direct commit link: https://github.com/osmosis-labs/cosmos-sdk/commit/193959b898ecdcae36b52f97927e6a0a4389e98c
+	github.com/cosmos/cosmos-sdk => github.com/osmosis-labs/cosmos-sdk v0.45.1-0.20230523200430-193959b898ec
 	github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1
 	github.com/tendermint/tendermint => github.com/informalsystems/tendermint v0.34.24
 )
diff --git a/x/epochs/go.sum b/x/epochs/go.sum
index f1ce59953..eddb6c24f 100644
--- a/x/epochs/go.sum
+++ b/x/epochs/go.sum
@@ -687,8 +687,7 @@ github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJ
 github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
 github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
 github.com/ory/dockertest v3.3.5+incompatible h1:iLLK6SQwIhcbrG783Dghaaa3WPzGc+4Emza6EbVUUGA=
-github.com/osmosis-labs/cosmos-sdk v0.45.1-0.20230326212251-7a2cf2993434 h1:RetElHdhDl6f00Tjj7ii2r+HX2aa/u+dhgwQb5hKv8Y=
-github.com/osmosis-labs/cosmos-sdk v0.45.1-0.20230326212251-7a2cf2993434/go.mod h1:ss3tUfPTwaa6NsoPZrCR7xOqLqCK0LwoNbc2Q8Zs5/Y=
+github.com/osmosis-labs/cosmos-sdk v0.45.1-0.20230523200430-193959b898ec h1:p7tmT1OljDKFAue6FuKqE9WlFUO7Z0hXcWKEPzFTKBE=
 github.com/osmosis-labs/osmosis/osmoutils v0.0.0-20230510161551-8bf252f26bae h1:I1Cy+GpTPWbVi0lBw9+bS1w42YfQjvXNK9bW4YbHhcs=
 github.com/osmosis-labs/osmosis/osmoutils v0.0.0-20230510161551-8bf252f26bae/go.mod h1:hk/o9/kmTSZmZqwXcSrPuwj/gpRMCqbE/d3vj6teL2A=
 github.com/otiai10/copy v1.7.0 h1:hVoPiN+t+7d2nzzwMiDHPSOogsWAStewq3TwU05+clE=
@@ -805,8 +804,7 @@ github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B
 github.com/spf13/afero v1.9.3 h1:41FoI0fD7OR7mGcKE/aOiLkGreyf8ifIOQmJANWogMk=
 github.com/spf13/afero v1.9.3/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y=
 github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
-github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w=
-github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU=
+github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA=
 github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
 github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
 github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I=
@@ -840,8 +838,7 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
 github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
 github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
-github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
-github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
+github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY=
 github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8=
 github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0=
 github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY=
diff --git a/x/ibc-hooks/go.mod b/x/ibc-hooks/go.mod
index fc081d7a4..b904b32a2 100644
--- a/x/ibc-hooks/go.mod
+++ b/x/ibc-hooks/go.mod
@@ -106,11 +106,11 @@ require (
 	github.com/rs/zerolog v1.27.0 // indirect
 	github.com/sasha-s/go-deadlock v0.3.1 // indirect
 	github.com/spf13/afero v1.9.3 // indirect
-	github.com/spf13/cast v1.5.0 // indirect
+	github.com/spf13/cast v1.5.1 // indirect
 	github.com/spf13/jwalterweatherman v1.1.0 // indirect
 	github.com/spf13/pflag v1.0.5 // indirect
 	github.com/spf13/viper v1.15.0 // indirect
-	github.com/stretchr/testify v1.8.2 // indirect
+	github.com/stretchr/testify v1.8.3 // indirect
 	github.com/subosito/gotenv v1.4.2 // indirect
 	github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect
 	github.com/tendermint/btcd v0.1.1 // indirect
@@ -143,8 +143,8 @@ replace (
 	github.com/CosmWasm/wasmd => github.com/osmosis-labs/wasmd v0.31.0-osmo-v16
 	// dragonberry
 	github.com/confio/ics23/go => github.com/cosmos/cosmos-sdk/ics23/go v0.8.0
-	// Our cosmos-sdk branch is:  https://github.com/osmosis-labs/cosmos-sdk, current branch: v16.x. Direct commit link: https://github.com/osmosis-labs/cosmos-sdk/commit/43c58d9061e3b8e0f06c3d9efef8c728800ab554
-	github.com/cosmos/cosmos-sdk => github.com/osmosis-labs/cosmos-sdk v0.45.1-0.20230326212251-7a2cf2993434
+	// Our cosmos-sdk branch is:  https://github.com/osmosis-labs/cosmos-sdk, current branch: v16.x. Direct commit link: https://github.com/osmosis-labs/cosmos-sdk/commit/193959b898ecdcae36b52f97927e6a0a4389e98c
+	github.com/cosmos/cosmos-sdk => github.com/osmosis-labs/cosmos-sdk v0.45.1-0.20230523200430-193959b898ec
 	// use cosmos-compatible protobufs
 	github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1
 	github.com/tendermint/tendermint => github.com/informalsystems/tendermint v0.34.24
diff --git a/x/ibc-hooks/go.sum b/x/ibc-hooks/go.sum
index aa14bc7bb..44e6fd3b2 100644
--- a/x/ibc-hooks/go.sum
+++ b/x/ibc-hooks/go.sum
@@ -701,8 +701,7 @@ github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJ
 github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
 github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
 github.com/ory/dockertest v3.3.5+incompatible h1:iLLK6SQwIhcbrG783Dghaaa3WPzGc+4Emza6EbVUUGA=
-github.com/osmosis-labs/cosmos-sdk v0.45.1-0.20230326212251-7a2cf2993434 h1:RetElHdhDl6f00Tjj7ii2r+HX2aa/u+dhgwQb5hKv8Y=
-github.com/osmosis-labs/cosmos-sdk v0.45.1-0.20230326212251-7a2cf2993434/go.mod h1:ss3tUfPTwaa6NsoPZrCR7xOqLqCK0LwoNbc2Q8Zs5/Y=
+github.com/osmosis-labs/cosmos-sdk v0.45.1-0.20230523200430-193959b898ec h1:p7tmT1OljDKFAue6FuKqE9WlFUO7Z0hXcWKEPzFTKBE=
 github.com/osmosis-labs/osmosis/osmoutils v0.0.0-20230510161551-8bf252f26bae h1:I1Cy+GpTPWbVi0lBw9+bS1w42YfQjvXNK9bW4YbHhcs=
 github.com/osmosis-labs/osmosis/osmoutils v0.0.0-20230510161551-8bf252f26bae/go.mod h1:hk/o9/kmTSZmZqwXcSrPuwj/gpRMCqbE/d3vj6teL2A=
 github.com/osmosis-labs/wasmd v0.31.0-osmo-v16 h1:X747cZYdnqc/+RV48iPVeGprpVb/fUWSaKGsZUWrdbg=
@@ -822,8 +821,7 @@ github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B
 github.com/spf13/afero v1.9.3 h1:41FoI0fD7OR7mGcKE/aOiLkGreyf8ifIOQmJANWogMk=
 github.com/spf13/afero v1.9.3/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y=
 github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
-github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w=
-github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU=
+github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA=
 github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
 github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
 github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I=
@@ -857,8 +855,7 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
 github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
 github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
-github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
-github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
+github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY=
 github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8=
 github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0=
 github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY=
diff --git a/x/mint/README.md b/x/mint/README.md
index f9ac0efc2..5c867e37d 100644
--- a/x/mint/README.md
+++ b/x/mint/README.md
@@ -23,7 +23,7 @@ The module uses time basis epochs supported by the `epochs` module.
 The `x/mint` module is designed to handle the regular printing of new
 tokens within a chain. The design taken within Osmosis is to
 
-- Mint new tokens once per epoch (default one week)
+- Mint new tokens once per epoch (default one day)
 - To have a "Reductioning factor" every period, which reduces the number of
   rewards per epoch. (default: period is 3 years, where a
   year is 52 epochs. The next period's rewards are 2/3 of the prior
diff --git a/x/poolmanager/client/cli/flags.go b/x/poolmanager/client/cli/flags.go
index e3275864c..1705eeee8 100644
--- a/x/poolmanager/client/cli/flags.go
+++ b/x/poolmanager/client/cli/flags.go
@@ -1,6 +1,10 @@
 package cli
 
-import flag "github.com/spf13/pflag"
+import (
+	flag "github.com/spf13/pflag"
+
+	"github.com/osmosis-labs/osmosis/v15/x/poolmanager/types"
+)
 
 const (
 	// Names of fields in pool json file.
@@ -21,6 +25,8 @@ const (
 	FlagSwapRoutePoolIds = "swap-route-pool-ids"
 	// Will be parsed to []string.
 	FlagSwapRouteDenoms = "swap-route-denoms"
+	// Will be parsed to string.
+	FlagRoutesFile = "routes-file"
 )
 
 type createBalancerPoolInputs struct {
@@ -47,6 +53,23 @@ type smoothWeightChangeParamsInputs struct {
 	TargetPoolWeights string `json:"target-pool-weights"`
 }
 
+type RoutesIn struct {
+	Route []SwapAmountInSplitRoute `json:"route"`
+}
+type RoutesOut struct {
+	Route []SwapAmountOutSplitRoute `json:"route"`
+}
+
+type SwapAmountInSplitRoute struct {
+	Pools         []types.SwapAmountInRoute `json:"swap_amount_in_route"`
+	TokenInAmount int64                     `json:"token_in_amount"`
+}
+
+type SwapAmountOutSplitRoute struct {
+	Pools          []types.SwapAmountOutRoute `json:"swap_amount_out_route"`
+	TokenOutAmount int64                      `json:"token_out_amount"`
+}
+
 func FlagSetMultihopSwapRoutes() *flag.FlagSet {
 	fs := flag.NewFlagSet("", flag.ContinueOnError)
 	fs.String(FlagSwapRoutePoolIds, "", "swap route pool id")
@@ -76,3 +99,10 @@ func FlagSetCreatePool() *flag.FlagSet {
 	fs.String(FlagPoolFile, "", "Pool json file path (if this path is given, other create pool flags should not be used)")
 	return fs
 }
+
+func FlagSetCreateRoutes() *flag.FlagSet {
+	fs := flag.NewFlagSet("", flag.ContinueOnError)
+
+	fs.String(FlagRoutesFile, "", "Routes json file path (if this path is given, other routes flags should not be used)")
+	return fs
+}
diff --git a/x/poolmanager/client/cli/tx.go b/x/poolmanager/client/cli/tx.go
index fd480976d..b1c9008ba 100644
--- a/x/poolmanager/client/cli/tx.go
+++ b/x/poolmanager/client/cli/tx.go
@@ -1,8 +1,10 @@
 package cli
 
 import (
+	"encoding/json"
 	"errors"
 	"fmt"
+	"os"
 	"strconv"
 	"strings"
 	"time"
@@ -27,6 +29,8 @@ func NewTxCmd() *cobra.Command {
 
 	osmocli.AddTxCmd(txCmd, NewSwapExactAmountInCmd)
 	osmocli.AddTxCmd(txCmd, NewSwapExactAmountOutCmd)
+	osmocli.AddTxCmd(txCmd, NewSplitRouteSwapExactAmountIn)
+	osmocli.AddTxCmd(txCmd, NewSplitRouteSwapExactAmountOut)
 
 	txCmd.AddCommand(
 		NewCreatePoolCmd(),
@@ -57,29 +61,154 @@ func NewSwapExactAmountOutCmd() (*osmocli.TxCliDesc, *types.MsgSwapExactAmountOu
 	}, &types.MsgSwapExactAmountOut{}
 }
 
-func NewBuildSwapExactAmountInMsg(clientCtx client.Context, tokenInStr, tokenOutMinAmtStr string, txf tx.Factory, fs *flag.FlagSet) (tx.Factory, sdk.Msg, error) {
-	routes, err := swapAmountInRoutes(fs)
+func NewSplitRouteSwapExactAmountIn() (*osmocli.TxCliDesc, *types.MsgSplitRouteSwapExactAmountIn) {
+	return &osmocli.TxCliDesc{
+		Use:   "split-route-swap-exact-amount-in [token-in-denom] [token-out-min-amount] [flags]",
+		Short: "split route swap exact amount in",
+		Example: `osmosisd tx poolmanager split-route-swap-exact-amount-in uosmo 1 --routes-file="./routes.json" --from val --keyring-backend test -b=block --chain-id=localosmosis --fees 10000uosmo
+		- routes.json
+		{
+			"Route": [
+			  {
+			  "swap_amount_in_route": [
+				{
+				"pool_id": 1,
+				"token_out_denom": "uion"
+				},
+				{
+				"pool_id": 2,
+				"token_out_denom": "uosmo"
+				}
+			  ],
+			  "token_in_amount": 1000
+			  },
+			  {
+			  "swap_amount_in_route": [
+				{
+				"pool_id": 3,
+				"token_out_denom": "bar"
+				},
+				{
+				"pool_id": 4,
+				"token_out_denom": "uosmo"
+				}
+			  ],
+			  "token_in_amount": 999
+			  }
+			]
+		}
+		`,
+		CustomFieldParsers: map[string]osmocli.CustomFieldParserFn{
+			"Routes": osmocli.FlagOnlyParser(NewMsgNewSplitRouteSwapExactAmountIn),
+		},
+		Flags: osmocli.FlagDesc{
+			RequiredFlags: []*flag.FlagSet{FlagSetCreateRoutes()},
+		},
+	}, &types.MsgSplitRouteSwapExactAmountIn{}
+}
+
+func NewSplitRouteSwapExactAmountOut() (*osmocli.TxCliDesc, *types.MsgSplitRouteSwapExactAmountOut) {
+	return &osmocli.TxCliDesc{
+		Use:   "split-route-swap-exact-amount-out [token-out-denom] [token-in-max-amount] [flags]",
+		Short: "split route swap exact amount out",
+		Example: `osmosisd tx poolmanager split-route-swap-exact-amount-out uosmo 1 --routes-file="./routes.json" --from val --keyring-backend test -b=block --chain-id=localosmosis --fees 10000uosmo
+		- routes.json
+		{
+			"route": [
+				{
+				"swap_amount_out_route": [
+					{
+					"pool_id": 1,
+					"token_in_denom": "uion"
+					},
+					{
+					"pool_id": 2,
+					"token_in_denom": "uosmo"
+					}
+				],
+				"token_out_amount": 1000
+				},
+				{
+				"swap_amount_out_route": [
+					{
+					"pool_id": 3,
+					"token_in_denom": "uion"
+					},
+					{
+					"pool_id": 4,
+					"token_in_denom": "uosmo"
+					}
+				],
+				"token_out_amount": 999
+				}
+			]
+			}
+		`,
+		CustomFieldParsers: map[string]osmocli.CustomFieldParserFn{
+			"Routes": osmocli.FlagOnlyParser(NewMsgNewSplitRouteSwapExactAmountOut),
+		},
+		Flags: osmocli.FlagDesc{
+			RequiredFlags: []*flag.FlagSet{FlagSetCreateRoutes()},
+		},
+	}, &types.MsgSplitRouteSwapExactAmountOut{}
+}
+
+func NewMsgNewSplitRouteSwapExactAmountOut(fs *flag.FlagSet) ([]types.SwapAmountOutSplitRoute, error) {
+	routesFile, _ := fs.GetString(FlagRoutesFile)
+	if routesFile == "" {
+		return nil, fmt.Errorf("must pass in a routes json using the --%s flag", FlagRoutesFile)
+	}
+
+	contents, err := os.ReadFile(routesFile)
 	if err != nil {
-		return txf, nil, err
+		return nil, err
 	}
 
-	tokenIn, err := sdk.ParseCoinNormalized(tokenInStr)
+	var splitRouteJSONdata RoutesOut
+	err = json.Unmarshal(contents, &splitRouteJSONdata)
 	if err != nil {
-		return txf, nil, err
+		return nil, err
 	}
 
-	tokenOutMinAmt, ok := sdk.NewIntFromString(tokenOutMinAmtStr)
-	if !ok {
-		return txf, nil, fmt.Errorf("invalid token out min amount, %s", tokenOutMinAmtStr)
+	var splitRouteProto []types.SwapAmountOutSplitRoute
+	for _, route := range splitRouteJSONdata.Route {
+		protoRoute := types.SwapAmountOutSplitRoute{
+			TokenOutAmount: sdk.NewInt(route.TokenOutAmount),
+		}
+		protoRoute.Pools = append(protoRoute.Pools, route.Pools...)
+		splitRouteProto = append(splitRouteProto, protoRoute)
 	}
-	msg := &types.MsgSwapExactAmountIn{
-		Sender:            clientCtx.GetFromAddress().String(),
-		Routes:            routes,
-		TokenIn:           tokenIn,
-		TokenOutMinAmount: tokenOutMinAmt,
+
+	return splitRouteProto, nil
+}
+
+func NewMsgNewSplitRouteSwapExactAmountIn(fs *flag.FlagSet) ([]types.SwapAmountInSplitRoute, error) {
+	routesFile, _ := fs.GetString(FlagRoutesFile)
+	if routesFile == "" {
+		return nil, fmt.Errorf("must pass in a routes json using the --%s flag", FlagRoutesFile)
 	}
 
-	return txf, msg, nil
+	contents, err := os.ReadFile(routesFile)
+	if err != nil {
+		return nil, err
+	}
+
+	var splitRouteJSONdata RoutesIn
+	err = json.Unmarshal(contents, &splitRouteJSONdata)
+	if err != nil {
+		return nil, err
+	}
+
+	var splitRouteProto []types.SwapAmountInSplitRoute
+	for _, route := range splitRouteJSONdata.Route {
+		protoRoute := types.SwapAmountInSplitRoute{
+			TokenInAmount: sdk.NewInt(route.TokenInAmount),
+		}
+		protoRoute.Pools = append(protoRoute.Pools, route.Pools...)
+		splitRouteProto = append(splitRouteProto, protoRoute)
+	}
+
+	return splitRouteProto, nil
 }
 
 func NewBuildSwapExactAmountOutMsg(clientCtx client.Context, args []string, fs *flag.FlagSet) (sdk.Msg, error) {
diff --git a/x/poolmanager/router.go b/x/poolmanager/router.go
index 008917c0b..d86fae920 100644
--- a/x/poolmanager/router.go
+++ b/x/poolmanager/router.go
@@ -103,7 +103,7 @@ func (k Keeper) RouteExactAmountIn(
 	return tokenOutAmount, nil
 }
 
-// SplitRouteExactAmountIn route the swap across multiple multihop paths
+// SplitRouteExactAmountIn routes the swap across multiple multihop paths
 // to get the desired token out. This is useful for achieving the most optimal execution. However, note that the responsibility
 // of determining the optimal split is left to the client. This method simply route the swap across the given route.
 // The route must end with the same token out and begin with the same token in.
@@ -121,11 +121,11 @@ func (k Keeper) RouteExactAmountIn(
 func (k Keeper) SplitRouteExactAmountIn(
 	ctx sdk.Context,
 	sender sdk.AccAddress,
-	route []types.SwapAmountInSplitRoute,
+	routes []types.SwapAmountInSplitRoute,
 	tokenInDenom string,
 	tokenOutMinAmount sdk.Int,
 ) (sdk.Int, error) {
-	if err := types.ValidateSwapAmountInSplitRoute(route); err != nil {
+	if err := types.ValidateSwapAmountInSplitRoute(routes); err != nil {
 		return sdk.Int{}, err
 	}
 
@@ -137,7 +137,7 @@ func (k Keeper) SplitRouteExactAmountIn(
 		totalOutAmount                 = sdk.ZeroInt()
 	)
 
-	for _, multihopRoute := range route {
+	for _, multihopRoute := range routes {
 		tokenOutAmount, err := k.RouteExactAmountIn(
 			ctx,
 			sender,
diff --git a/x/poolmanager/types/routes.go b/x/poolmanager/types/routes.go
index 3f80fc32d..ca29063db 100644
--- a/x/poolmanager/types/routes.go
+++ b/x/poolmanager/types/routes.go
@@ -185,7 +185,9 @@ func (routes SwapAmountOutRoutes) Length() int {
 	return len(routes)
 }
 
-// ValidateSwapAmountInSplitRoute validates a slice of SwapAmountInSplitRoute and returns an error if any of the following are true:
+// ValidateSwapAmountInSplitRoute validates a slice of SwapAmountInSplitRoute.
+//
+// returns an error if any of the following are true:
 // - the slice is empty
 // - any SwapAmountInRoute in the slice is invalid
 // - the last TokenOutDenom of any SwapAmountInRoute in the slice does not match the TokenOutDenom of the previous SwapAmountInRoute in the slice
diff --git a/x/txfees/client/cli/tx.go b/x/txfees/client/cli/tx.go
index 8c0c196b0..27d691705 100644
--- a/x/txfees/client/cli/tx.go
+++ b/x/txfees/client/cli/tx.go
@@ -1,14 +1,15 @@
 package cli
 
 import (
+	"errors"
 	"strconv"
+	"strings"
 
 	"github.com/cosmos/cosmos-sdk/client/tx"
 
 	"github.com/spf13/cobra"
 
 	"github.com/cosmos/cosmos-sdk/client"
-	"github.com/cosmos/cosmos-sdk/client/flags"
 	sdk "github.com/cosmos/cosmos-sdk/types"
 	"github.com/cosmos/cosmos-sdk/x/gov/client/cli"
 	govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
@@ -17,6 +18,8 @@ import (
 	"github.com/osmosis-labs/osmosis/v15/x/txfees/types"
 )
 
+const FlagFeeTokens = "fee-tokens"
+
 func NewTxCmd() *cobra.Command {
 	txCmd := osmocli.TxIndexCmd(types.ModuleName)
 	txCmd.AddCommand(
@@ -27,32 +30,22 @@ func NewTxCmd() *cobra.Command {
 
 func NewCmdSubmitUpdateFeeTokenProposal() *cobra.Command {
 	cmd := &cobra.Command{
-		Use:   "update-fee-token [denom] [poolId]",
-		Args:  cobra.ExactArgs(2),
-		Short: "Submit an update to a fee token to be usable for tx fees",
-		RunE: func(cmd *cobra.Command, args []string) error {
-			clientCtx, err := client.GetClientTxContext(cmd)
-			if err != nil {
-				return err
-			}
+		Use:     "update-fee-token [flags]",
+		Args:    cobra.ExactArgs(0),
+		Example: "update-fee-token --fee-tokens uosmo,1,uion,2,ufoo,0 --from val --chain-id osmosis-1",
+		Short:   "Submit a update fee token record proposal",
+		Long: strings.TrimSpace(`Submit a update fee token record proposal.
 
-			denom := args[0]
-			pool_id, err := strconv.ParseUint(args[1], 10, 64)
-			if err != nil {
-				return err
-			}
+Passing in denom,poolID pairs separated by commas would be parsed automatically to pairs of fee token records.
+Ex) uosmo,1,uion,2,ufoo,0 -> [Adds uosmo<>pool1, uion<>pool2, Removes ufoo as a fee token]
 
-			feeToken := types.FeeToken{
-				Denom:  denom,
-				PoolID: pool_id,
-			}
-
-			title, err := cmd.Flags().GetString(cli.FlagTitle)
+		`),
+		RunE: func(cmd *cobra.Command, args []string) error {
+			clientCtx, err := client.GetClientTxContext(cmd)
 			if err != nil {
 				return err
 			}
-
-			description, err := cmd.Flags().GetString(cli.FlagDescription)
+			content, err := parseFeeTokenRecordsArgsToContent(cmd)
 			if err != nil {
 				return err
 			}
@@ -68,9 +61,7 @@ func NewCmdSubmitUpdateFeeTokenProposal() *cobra.Command {
 				return err
 			}
 
-			content := types.NewUpdateFeeTokenProposal(title, description, feeToken)
-
-			msg, err := govtypes.NewMsgSubmitProposal(&content, deposit, from)
+			msg, err := govtypes.NewMsgSubmitProposal(content, deposit, from)
 			if err != nil {
 				return err
 			}
@@ -86,9 +77,66 @@ func NewCmdSubmitUpdateFeeTokenProposal() *cobra.Command {
 	cmd.Flags().String(cli.FlagTitle, "", "title of proposal")
 	cmd.Flags().String(cli.FlagDescription, "", "description of proposal")
 	cmd.Flags().String(cli.FlagDeposit, "", "deposit of proposal")
-	flags.AddTxFlagsToCmd(cmd)
-	_ = cmd.MarkFlagRequired(cli.FlagTitle)
-	_ = cmd.MarkFlagRequired(cli.FlagDescription)
+	cmd.Flags().Bool(cli.FlagIsExpedited, false, "If true, makes the proposal an expedited one")
+	cmd.Flags().String(cli.FlagProposal, "", "Proposal file path (if this path is given, other proposal flags are ignored)")
+	cmd.Flags().String(FlagFeeTokens, "", "The fee token records array")
 
 	return cmd
 }
+
+func parseFeeTokenRecords(cmd *cobra.Command) ([]types.FeeToken, error) {
+	feeTokensStr, err := cmd.Flags().GetString(FlagFeeTokens)
+	if err != nil {
+		return nil, err
+	}
+
+	feeTokens := strings.Split(feeTokensStr, ",")
+
+	if len(feeTokens)%2 != 0 {
+		return nil, errors.New("fee denom records should be a comma separated list of denom and poolId pairs")
+	}
+
+	feeTokenRecords := []types.FeeToken{}
+	i := 0
+	for i < len(feeTokens) {
+		denom := feeTokens[i]
+		poolId, err := strconv.Atoi(feeTokens[i+1])
+		if err != nil {
+			return nil, err
+		}
+
+		feeTokenRecords = append(feeTokenRecords, types.FeeToken{
+			Denom:  denom,
+			PoolID: uint64(poolId),
+		})
+
+		// increase counter by the next 2
+		i = i + 2
+	}
+
+	return feeTokenRecords, nil
+}
+
+func parseFeeTokenRecordsArgsToContent(cmd *cobra.Command) (govtypes.Content, error) {
+	title, err := cmd.Flags().GetString(cli.FlagTitle)
+	if err != nil {
+		return nil, err
+	}
+
+	description, err := cmd.Flags().GetString(cli.FlagDescription)
+	if err != nil {
+		return nil, err
+	}
+
+	feeTokenRecords, err := parseFeeTokenRecords(cmd)
+	if err != nil {
+		return nil, err
+	}
+
+	content := &types.UpdateFeeTokenProposal{
+		Title:       title,
+		Description: description,
+		Feetokens:   feeTokenRecords,
+	}
+	return content, nil
+}
diff --git a/x/txfees/keeper/gov.go b/x/txfees/keeper/gov.go
index 17b90f759..2d37ef13d 100644
--- a/x/txfees/keeper/gov.go
+++ b/x/txfees/keeper/gov.go
@@ -8,5 +8,10 @@ import (
 
 func (k Keeper) HandleUpdateFeeTokenProposal(ctx sdk.Context, p *types.UpdateFeeTokenProposal) error {
 	// setFeeToken internally calls ValidateFeeToken
-	return k.setFeeToken(ctx, p.Feetoken)
+	for _, feeToken := range p.Feetokens {
+		if err := k.setFeeToken(ctx, feeToken); err != nil {
+			return err
+		}
+	}
+	return nil
 }
diff --git a/x/txfees/types/gov.go b/x/txfees/types/gov.go
index 7670d454f..375307db5 100644
--- a/x/txfees/types/gov.go
+++ b/x/txfees/types/gov.go
@@ -19,11 +19,11 @@ func init() {
 
 var _ govtypes.Content = &UpdateFeeTokenProposal{}
 
-func NewUpdateFeeTokenProposal(title, description string, feeToken FeeToken) UpdateFeeTokenProposal {
+func NewUpdateFeeTokenProposal(title, description string, feeTokens []FeeToken) UpdateFeeTokenProposal {
 	return UpdateFeeTokenProposal{
 		Title:       title,
 		Description: description,
-		Feetoken:    feeToken,
+		Feetokens:   feeTokens,
 	}
 }
 
@@ -43,15 +43,25 @@ func (p *UpdateFeeTokenProposal) ValidateBasic() error {
 		return err
 	}
 
-	return sdk.ValidateDenom(p.Feetoken.Denom)
+	for _, feeToken := range p.Feetokens {
+		if err := sdk.ValidateDenom(feeToken.Denom); err != nil {
+			return err
+		}
+	}
+	return nil
 }
 
 func (p UpdateFeeTokenProposal) String() string {
+	recordsStr := ""
+	for _, feeToken := range p.Feetokens {
+		recordsStr = recordsStr + fmt.Sprintf("(Denom: %s, PoolID: %d) ", feeToken.Denom, feeToken.PoolID)
+	}
+
 	var b strings.Builder
 	b.WriteString(fmt.Sprintf(`Update Fee Token Proposal:
   Title:       %s
   Description: %s
   Records:     %s
-`, p.Title, p.Description, p.Feetoken.String()))
+`, p.Title, p.Description, recordsStr))
 	return b.String()
 }
diff --git a/x/txfees/types/gov.pb.go b/x/txfees/types/gov.pb.go
index 8ea089cf9..4ba518cbf 100644
--- a/x/txfees/types/gov.pb.go
+++ b/x/txfees/types/gov.pb.go
@@ -25,15 +25,15 @@ var _ = math.Inf
 // proto package needs to be updated.
 const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
 
-// UpdateFeeTokenProposal is a gov Content type for adding a new whitelisted fee
-// token. It must specify a denom along with gamm pool ID to use as a spot price
-// calculator. It can be used to add a new denom to the whitelist It can also be
-// used to update the Pool to associate with the denom. If Pool ID is set to 0,
-// it will remove the denom from the whitelisted set.
+// UpdateFeeTokenProposal is a gov Content type for adding new whitelisted fee
+// token(s). It must specify a denom along with gamm pool ID to use as a spot
+// price calculator. It can be used to add new denoms to the whitelist. It can
+// also be used to update the Pool to associate with the denom. If Pool ID is
+// set to 0, it will remove the denom from the whitelisted set.
 type UpdateFeeTokenProposal struct {
-	Title       string   `protobuf:"bytes,1,opt,name=title,proto3" json:"title,omitempty" yaml:"title"`
-	Description string   `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty" yaml:"description"`
-	Feetoken    FeeToken `protobuf:"bytes,3,opt,name=feetoken,proto3" json:"feetoken" yaml:"fee_token"`
+	Title       string     `protobuf:"bytes,1,opt,name=title,proto3" json:"title,omitempty" yaml:"title"`
+	Description string     `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty" yaml:"description"`
+	Feetokens   []FeeToken `protobuf:"bytes,3,rep,name=feetokens,proto3" json:"feetokens" yaml:"fee_tokens"`
 }
 
 func (m *UpdateFeeTokenProposal) Reset()      { *m = UpdateFeeTokenProposal{} }
@@ -75,30 +75,30 @@ func init() {
 func init() { proto.RegisterFile("osmosis/txfees/v1beta1/gov.proto", fileDescriptor_2c4a51bafc82863d) }
 
 var fileDescriptor_2c4a51bafc82863d = []byte{
-	// 362 bytes of a gzipped FileDescriptorProto
+	// 363 bytes of a gzipped FileDescriptorProto
 	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0xc8, 0x2f, 0xce, 0xcd,
 	0x2f, 0xce, 0x2c, 0xd6, 0x2f, 0xa9, 0x48, 0x4b, 0x4d, 0x2d, 0xd6, 0x2f, 0x33, 0x4c, 0x4a, 0x2d,
 	0x49, 0x34, 0xd4, 0x4f, 0xcf, 0x2f, 0xd3, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x83, 0xaa,
 	0xd0, 0x83, 0xa8, 0xd0, 0x83, 0xaa, 0x90, 0x12, 0x49, 0xcf, 0x4f, 0xcf, 0x07, 0x2b, 0xd1, 0x07,
 	0xb1, 0x20, 0xaa, 0xa5, 0x24, 0x93, 0xc1, 0xca, 0xe3, 0x21, 0x12, 0x10, 0x0e, 0x54, 0x4a, 0x30,
 	0x31, 0x37, 0x33, 0x2f, 0x5f, 0x1f, 0x4c, 0x42, 0x85, 0x54, 0x71, 0xd8, 0x9e, 0x96, 0x9a, 0x5a,
-	0x92, 0x9f, 0x9d, 0x9a, 0x07, 0x51, 0xa6, 0xb4, 0x90, 0x89, 0x4b, 0x2c, 0xb4, 0x20, 0x25, 0xb1,
+	0x92, 0x9f, 0x9d, 0x9a, 0x07, 0x51, 0xa6, 0xb4, 0x84, 0x89, 0x4b, 0x2c, 0xb4, 0x20, 0x25, 0xb1,
 	0x24, 0xd5, 0x2d, 0x35, 0x35, 0x04, 0x24, 0x11, 0x50, 0x94, 0x5f, 0x90, 0x5f, 0x9c, 0x98, 0x23,
 	0xa4, 0xc6, 0xc5, 0x5a, 0x92, 0x59, 0x92, 0x93, 0x2a, 0xc1, 0xa8, 0xc0, 0xa8, 0xc1, 0xe9, 0x24,
 	0xf0, 0xe9, 0x9e, 0x3c, 0x4f, 0x65, 0x62, 0x6e, 0x8e, 0x95, 0x12, 0x58, 0x58, 0x29, 0x08, 0x22,
 	0x2d, 0x64, 0xc1, 0xc5, 0x9d, 0x92, 0x5a, 0x9c, 0x5c, 0x94, 0x59, 0x50, 0x92, 0x99, 0x9f, 0x27,
 	0xc1, 0x04, 0x56, 0x2d, 0xf6, 0xe9, 0x9e, 0xbc, 0x10, 0x44, 0x35, 0x92, 0xa4, 0x52, 0x10, 0xb2,
-	0x52, 0xa1, 0x30, 0x2e, 0x0e, 0x98, 0x73, 0x24, 0x98, 0x15, 0x18, 0x35, 0xb8, 0x8d, 0x14, 0xf4,
-	0xb0, 0x07, 0x89, 0x1e, 0xcc, 0x75, 0x4e, 0x12, 0x27, 0xee, 0xc9, 0x33, 0x7c, 0xba, 0x27, 0x2f,
-	0x00, 0x31, 0x3c, 0x2d, 0x35, 0x35, 0x1e, 0x6c, 0x80, 0x52, 0x10, 0xdc, 0x2c, 0x2b, 0xdf, 0x8e,
-	0x05, 0xf2, 0x0c, 0x33, 0x16, 0xc8, 0x33, 0xbc, 0x58, 0x20, 0xcf, 0x78, 0x6a, 0x8b, 0xae, 0x14,
-	0x34, 0xb0, 0x40, 0x21, 0x0f, 0x33, 0xd0, 0x39, 0x3f, 0xaf, 0x24, 0x35, 0xaf, 0xa4, 0xeb, 0xf9,
-	0x06, 0x2d, 0x39, 0x58, 0x50, 0x61, 0x0f, 0x08, 0x27, 0x9f, 0x13, 0x8f, 0xe4, 0x18, 0x2f, 0x3c,
-	0x92, 0x63, 0x7c, 0xf0, 0x48, 0x8e, 0x71, 0xc2, 0x63, 0x39, 0x86, 0x0b, 0x8f, 0xe5, 0x18, 0x6e,
-	0x3c, 0x96, 0x63, 0x88, 0x32, 0x4a, 0xcf, 0x2c, 0xc9, 0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5,
-	0x87, 0x1a, 0xa2, 0x9b, 0x93, 0x98, 0x54, 0x0c, 0xe3, 0xe8, 0x97, 0x19, 0x9a, 0xea, 0x57, 0xc0,
-	0xa2, 0xa0, 0xa4, 0xb2, 0x20, 0xb5, 0x38, 0x89, 0x0d, 0x1c, 0xf0, 0xc6, 0x80, 0x00, 0x00, 0x00,
-	0xff, 0xff, 0xe2, 0xf0, 0xb4, 0x1a, 0x1f, 0x02, 0x00, 0x00,
+	0x52, 0xa1, 0x48, 0x2e, 0x4e, 0x98, 0x73, 0x8a, 0x25, 0x98, 0x15, 0x98, 0x35, 0xb8, 0x8d, 0x14,
+	0xf4, 0xb0, 0x87, 0x89, 0x1e, 0xcc, 0x79, 0x4e, 0x92, 0x27, 0xee, 0xc9, 0x33, 0x7c, 0xba, 0x27,
+	0x2f, 0x08, 0x31, 0x3d, 0x2d, 0x35, 0x35, 0x1e, 0x62, 0x82, 0x52, 0x10, 0xc2, 0x34, 0x2b, 0xdf,
+	0x8e, 0x05, 0xf2, 0x0c, 0x33, 0x16, 0xc8, 0x33, 0xbc, 0x58, 0x20, 0xcf, 0x78, 0x6a, 0x8b, 0xae,
+	0x14, 0x34, 0xbc, 0x40, 0x81, 0x0f, 0x33, 0xd2, 0x39, 0x3f, 0xaf, 0x24, 0x35, 0xaf, 0xa4, 0xeb,
+	0xf9, 0x06, 0x2d, 0x39, 0x58, 0x68, 0x61, 0x0f, 0x0b, 0x27, 0x9f, 0x13, 0x8f, 0xe4, 0x18, 0x2f,
+	0x3c, 0x92, 0x63, 0x7c, 0xf0, 0x48, 0x8e, 0x71, 0xc2, 0x63, 0x39, 0x86, 0x0b, 0x8f, 0xe5, 0x18,
+	0x6e, 0x3c, 0x96, 0x63, 0x88, 0x32, 0x4a, 0xcf, 0x2c, 0xc9, 0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf,
+	0xd5, 0x87, 0x1a, 0xa2, 0x9b, 0x93, 0x98, 0x54, 0x0c, 0xe3, 0xe8, 0x97, 0x19, 0x9a, 0xea, 0x57,
+	0xc0, 0x62, 0xa1, 0xa4, 0xb2, 0x20, 0xb5, 0x38, 0x89, 0x0d, 0x1c, 0xf6, 0xc6, 0x80, 0x00, 0x00,
+	0x00, 0xff, 0xff, 0xf3, 0xd9, 0x7e, 0x03, 0x22, 0x02, 0x00, 0x00,
 }
 
 func (this *UpdateFeeTokenProposal) Equal(that interface{}) bool {
@@ -126,9 +126,14 @@ func (this *UpdateFeeTokenProposal) Equal(that interface{}) bool {
 	if this.Description != that1.Description {
 		return false
 	}
-	if !this.Feetoken.Equal(&that1.Feetoken) {
+	if len(this.Feetokens) != len(that1.Feetokens) {
 		return false
 	}
+	for i := range this.Feetokens {
+		if !this.Feetokens[i].Equal(&that1.Feetokens[i]) {
+			return false
+		}
+	}
 	return true
 }
 func (m *UpdateFeeTokenProposal) Marshal() (dAtA []byte, err error) {
@@ -151,16 +156,20 @@ func (m *UpdateFeeTokenProposal) MarshalToSizedBuffer(dAtA []byte) (int, error)
 	_ = i
 	var l int
 	_ = l
-	{
-		size, err := m.Feetoken.MarshalToSizedBuffer(dAtA[:i])
-		if err != nil {
-			return 0, err
+	if len(m.Feetokens) > 0 {
+		for iNdEx := len(m.Feetokens) - 1; iNdEx >= 0; iNdEx-- {
+			{
+				size, err := m.Feetokens[iNdEx].MarshalToSizedBuffer(dAtA[:i])
+				if err != nil {
+					return 0, err
+				}
+				i -= size
+				i = encodeVarintGov(dAtA, i, uint64(size))
+			}
+			i--
+			dAtA[i] = 0x1a
 		}
-		i -= size
-		i = encodeVarintGov(dAtA, i, uint64(size))
 	}
-	i--
-	dAtA[i] = 0x1a
 	if len(m.Description) > 0 {
 		i -= len(m.Description)
 		copy(dAtA[i:], m.Description)
@@ -203,8 +212,12 @@ func (m *UpdateFeeTokenProposal) Size() (n int) {
 	if l > 0 {
 		n += 1 + l + sovGov(uint64(l))
 	}
-	l = m.Feetoken.Size()
-	n += 1 + l + sovGov(uint64(l))
+	if len(m.Feetokens) > 0 {
+		for _, e := range m.Feetokens {
+			l = e.Size()
+			n += 1 + l + sovGov(uint64(l))
+		}
+	}
 	return n
 }
 
@@ -309,7 +322,7 @@ func (m *UpdateFeeTokenProposal) Unmarshal(dAtA []byte) error {
 			iNdEx = postIndex
 		case 3:
 			if wireType != 2 {
-				return fmt.Errorf("proto: wrong wireType = %d for field Feetoken", wireType)
+				return fmt.Errorf("proto: wrong wireType = %d for field Feetokens", wireType)
 			}
 			var msglen int
 			for shift := uint(0); ; shift += 7 {
@@ -336,7 +349,8 @@ func (m *UpdateFeeTokenProposal) Unmarshal(dAtA []byte) error {
 			if postIndex > l {
 				return io.ErrUnexpectedEOF
 			}
-			if err := m.Feetoken.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+			m.Feetokens = append(m.Feetokens, FeeToken{})
+			if err := m.Feetokens[len(m.Feetokens)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
 				return err
 			}
 			iNdEx = postIndex


Test patch:
diff --git a/app/apptesting/test_suite.go b/app/apptesting/test_suite.go
index 12e971a44..2a0b00c66 100644
--- a/app/apptesting/test_suite.go
+++ b/app/apptesting/test_suite.go
@@ -58,6 +58,17 @@ var (
 // Setup sets up basic environment for suite (App, Ctx, and test accounts)
 func (s *KeeperTestHelper) Setup() {
 	s.App = app.Setup(false)
+	s.setupGeneral()
+}
+
+func (s *KeeperTestHelper) SetupWithLevelDb() func() {
+	app, cleanup := app.SetupTestingAppWithLevelDb(false)
+	s.App = app
+	s.setupGeneral()
+	return cleanup
+}
+
+func (s *KeeperTestHelper) setupGeneral() {
 	s.Ctx = s.App.BaseApp.NewContext(false, tmtypes.Header{Height: 1, ChainID: "osmosis-1", Time: time.Now().UTC()})
 	s.QueryHelper = &baseapp.QueryServiceTestHelper{
 		GRPCQueryRouter: s.App.GRPCQueryRouter(),
diff --git a/osmoutils/store_helper_test.go b/osmoutils/store_helper_test.go
index 21d2a134c..d659650f3 100644
--- a/osmoutils/store_helper_test.go
+++ b/osmoutils/store_helper_test.go
@@ -1274,8 +1274,7 @@ func (s *TestSuite) TestGetDec() {
 			},
 
 			expectedGetKeyValues: map[string]sdk.Dec{
-				keyA: sdk.OneDec(),
-				keyB: {}, // this one errors
+				keyB: {},
 			},
 
 			expectError: osmoutils.DecNotFoundError{Key: keyB},
@@ -1283,6 +1282,7 @@ func (s *TestSuite) TestGetDec() {
 	}
 
 	for name, tc := range tests {
+		tc := tc
 		s.Run(name, func() {
 			s.SetupTest()
 			// Setup
diff --git a/tests/cl-genesis-positions/go.mod b/tests/cl-genesis-positions/go.mod
index e778d3ee5..ed59a7afd 100644
--- a/tests/cl-genesis-positions/go.mod
+++ b/tests/cl-genesis-positions/go.mod
@@ -113,14 +113,14 @@ require (
 	github.com/rs/zerolog v1.27.0 // indirect
 	github.com/sasha-s/go-deadlock v0.3.1 // indirect
 	github.com/spf13/afero v1.9.3 // indirect
-	github.com/spf13/cast v1.5.0 // indirect
+	github.com/spf13/cast v1.5.1 // indirect
 	github.com/spf13/cobra v1.7.0 // indirect
 	github.com/spf13/jwalterweatherman v1.1.0 // indirect
 	github.com/spf13/pflag v1.0.5 // indirect
 	github.com/spf13/viper v1.15.0 // indirect
 	github.com/strangelove-ventures/async-icq/v4 v4.0.0-rc0 // indirect
 	github.com/strangelove-ventures/packet-forward-middleware/v4 v4.0.5 // indirect
-	github.com/stretchr/testify v1.8.2 // indirect
+	github.com/stretchr/testify v1.8.3 // indirect
 	github.com/subosito/gotenv v1.4.2 // indirect
 	github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect
 	github.com/tendermint/btcd v0.1.1 // indirect
@@ -155,8 +155,8 @@ replace (
 	github.com/CosmWasm/wasmd => github.com/osmosis-labs/wasmd v0.31.0-osmo-v16
 	// dragonberry
 	github.com/confio/ics23/go => github.com/cosmos/cosmos-sdk/ics23/go v0.8.0
-	// Our cosmos-sdk branch is:  https://github.com/osmosis-labs/cosmos-sdk, current branch: v16.x. Direct commit link: https://github.com/osmosis-labs/cosmos-sdk/commit/43c58d9061e3b8e0f06c3d9efef8c728800ab554
-	github.com/cosmos/cosmos-sdk => github.com/osmosis-labs/cosmos-sdk v0.45.1-0.20230326212251-7a2cf2993434
+	// Our cosmos-sdk branch is:  https://github.com/osmosis-labs/cosmos-sdk, current branch: v16.x. Direct commit link: https://github.com/osmosis-labs/cosmos-sdk/commit/193959b898ecdcae36b52f97927e6a0a4389e98c
+	github.com/cosmos/cosmos-sdk => github.com/osmosis-labs/cosmos-sdk v0.45.1-0.20230523200430-193959b898ec
 
 	// N.B. v0.19.5 contains a breaking change to the IAVL API
 	github.com/cosmos/iavl v0.19.5 => github.com/cosmos/iavl v0.19.4
diff --git a/tests/cl-genesis-positions/go.sum b/tests/cl-genesis-positions/go.sum
index 250dff861..c8ac2a17c 100644
--- a/tests/cl-genesis-positions/go.sum
+++ b/tests/cl-genesis-positions/go.sum
@@ -691,8 +691,7 @@ github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJ
 github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
 github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
 github.com/ory/dockertest v3.3.5+incompatible h1:iLLK6SQwIhcbrG783Dghaaa3WPzGc+4Emza6EbVUUGA=
-github.com/osmosis-labs/cosmos-sdk v0.45.1-0.20230326212251-7a2cf2993434 h1:RetElHdhDl6f00Tjj7ii2r+HX2aa/u+dhgwQb5hKv8Y=
-github.com/osmosis-labs/cosmos-sdk v0.45.1-0.20230326212251-7a2cf2993434/go.mod h1:ss3tUfPTwaa6NsoPZrCR7xOqLqCK0LwoNbc2Q8Zs5/Y=
+github.com/osmosis-labs/cosmos-sdk v0.45.1-0.20230523200430-193959b898ec h1:p7tmT1OljDKFAue6FuKqE9WlFUO7Z0hXcWKEPzFTKBE=
 github.com/osmosis-labs/osmosis/osmomath v0.0.3-dev.0.20230503232557-ba905586c111 h1:1ahWbf9iF9sxDOjxrHWFaBGLE0nWFdpiX1pqObUaJO8=
 github.com/osmosis-labs/osmosis/osmomath v0.0.3-dev.0.20230503232557-ba905586c111/go.mod h1:a7lhiXRpn8QJ21OhFpaEnUNErTSIafaYpp02q6uI/Dk=
 github.com/osmosis-labs/osmosis/osmoutils v0.0.0-20230511015306-615fa4fcbe56 h1:27yWLC0uXSatRy8aRn0yinHU+K31bkjBRmNnQUDO0Ks=
@@ -822,8 +821,7 @@ github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B
 github.com/spf13/afero v1.9.3 h1:41FoI0fD7OR7mGcKE/aOiLkGreyf8ifIOQmJANWogMk=
 github.com/spf13/afero v1.9.3/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y=
 github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
-github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w=
-github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU=
+github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA=
 github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
 github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
 github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I=
@@ -861,8 +859,7 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
 github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
 github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
-github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
-github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
+github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY=
 github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8=
 github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0=
 github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY=
diff --git a/tests/cl-go-client/go.mod b/tests/cl-go-client/go.mod
index 67222456b..50eb2a59d 100644
--- a/tests/cl-go-client/go.mod
+++ b/tests/cl-go-client/go.mod
@@ -103,12 +103,12 @@ require (
 	github.com/rs/zerolog v1.27.0 // indirect
 	github.com/sasha-s/go-deadlock v0.3.1 // indirect
 	github.com/spf13/afero v1.9.3 // indirect
-	github.com/spf13/cast v1.5.0 // indirect
+	github.com/spf13/cast v1.5.1 // indirect
 	github.com/spf13/cobra v1.7.0 // indirect
 	github.com/spf13/jwalterweatherman v1.1.0 // indirect
 	github.com/spf13/pflag v1.0.5 // indirect
 	github.com/spf13/viper v1.15.0 // indirect
-	github.com/stretchr/testify v1.8.2 // indirect
+	github.com/stretchr/testify v1.8.3 // indirect
 	github.com/subosito/gotenv v1.4.2 // indirect
 	github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect
 	github.com/tendermint/btcd v0.1.1 // indirect
@@ -144,8 +144,8 @@ replace (
 	github.com/CosmWasm/wasmd => github.com/osmosis-labs/wasmd v0.31.0-osmo-v16
 	// dragonberry
 	github.com/confio/ics23/go => github.com/cosmos/cosmos-sdk/ics23/go v0.8.0
-	// Our cosmos-sdk branch is:  https://github.com/osmosis-labs/cosmos-sdk, current branch: v16.x. Direct commit link: https://github.com/osmosis-labs/cosmos-sdk/commit/43c58d9061e3b8e0f06c3d9efef8c728800ab554
-	github.com/cosmos/cosmos-sdk => github.com/osmosis-labs/cosmos-sdk v0.45.1-0.20230326212251-7a2cf2993434
+	// Our cosmos-sdk branch is:  https://github.com/osmosis-labs/cosmos-sdk, current branch: v16.x. Direct commit link: https://github.com/osmosis-labs/cosmos-sdk/commit/193959b898ecdcae36b52f97927e6a0a4389e98c
+	github.com/cosmos/cosmos-sdk => github.com/osmosis-labs/cosmos-sdk v0.45.1-0.20230523200430-193959b898ec
 	// use cosmos-compatible protobufs
 	github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1
 
diff --git a/tests/cl-go-client/go.sum b/tests/cl-go-client/go.sum
index 7bdf957d8..76cb48c77 100644
--- a/tests/cl-go-client/go.sum
+++ b/tests/cl-go-client/go.sum
@@ -241,7 +241,7 @@ github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8
 github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
 github.com/dnaeon/go-vcr v1.1.0/go.mod h1:M7tiix8f0r6mKKJ3Yq/kqU1OYf3MnfmBWVbPx/yU9ko=
 github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ=
-github.com/docker/distribution v2.8.1+incompatible h1:Q50tZOPR6T/hjNsyc9g8/syEs6bk8XXApsHjKukMl68=
+github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8=
 github.com/docker/docker v1.4.2-0.20180625184442-8e610b2b55bf/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
 github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
 github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
@@ -684,8 +684,7 @@ github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJ
 github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
 github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
 github.com/ory/dockertest v3.3.5+incompatible h1:iLLK6SQwIhcbrG783Dghaaa3WPzGc+4Emza6EbVUUGA=
-github.com/osmosis-labs/cosmos-sdk v0.45.1-0.20230326212251-7a2cf2993434 h1:RetElHdhDl6f00Tjj7ii2r+HX2aa/u+dhgwQb5hKv8Y=
-github.com/osmosis-labs/cosmos-sdk v0.45.1-0.20230326212251-7a2cf2993434/go.mod h1:ss3tUfPTwaa6NsoPZrCR7xOqLqCK0LwoNbc2Q8Zs5/Y=
+github.com/osmosis-labs/cosmos-sdk v0.45.1-0.20230523200430-193959b898ec h1:p7tmT1OljDKFAue6FuKqE9WlFUO7Z0hXcWKEPzFTKBE=
 github.com/osmosis-labs/osmosis/osmomath v0.0.3-dev.0.20230516205127-c213fddde069 h1:ZgDrTJ2GCH4CJGbV6rudw4O9rPMAuwWoLVZnG6cUr+A=
 github.com/osmosis-labs/osmosis/osmoutils v0.0.0-20230516205127-c213fddde069 h1:9C/n+Nx5rre/AHPMlPsQrk1isgydrCNB68aqer86ygE=
 github.com/osmosis-labs/osmosis/x/epochs v0.0.0-20230328024000-175ec88e4304 h1:RIrWLzIiZN5Xd2JOfSOtGZaf6V3qEQYg6EaDTAkMnCo=
@@ -808,8 +807,7 @@ github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B
 github.com/spf13/afero v1.9.3 h1:41FoI0fD7OR7mGcKE/aOiLkGreyf8ifIOQmJANWogMk=
 github.com/spf13/afero v1.9.3/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y=
 github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
-github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w=
-github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU=
+github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA=
 github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
 github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
 github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I=
@@ -845,8 +843,7 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
 github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
 github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
-github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
-github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
+github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY=
 github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8=
 github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0=
 github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY=
diff --git a/x/concentrated-liquidity/bench_test.go b/x/concentrated-liquidity/bench_test.go
index 1451cebfc..c71b05b2f 100644
--- a/x/concentrated-liquidity/bench_test.go
+++ b/x/concentrated-liquidity/bench_test.go
@@ -11,6 +11,8 @@ import (
 	"github.com/stretchr/testify/require"
 
 	"github.com/osmosis-labs/osmosis/v15/app/apptesting"
+	cl "github.com/osmosis-labs/osmosis/v15/x/concentrated-liquidity"
+	clmath "github.com/osmosis-labs/osmosis/v15/x/concentrated-liquidity/math"
 	clmodel "github.com/osmosis-labs/osmosis/v15/x/concentrated-liquidity/model"
 	"github.com/osmosis-labs/osmosis/v15/x/concentrated-liquidity/types"
 )
@@ -30,68 +32,51 @@ func (s BenchTestSuite) createPosition(accountIndex int, poolId uint64, coin0, c
 	}
 }
 
-func BenchmarkSwapExactAmountIn(b *testing.B) {
+func noError(b *testing.B, err error) {
+	require.NoError(b, err)
+}
+
+func runBenchmark(b *testing.B, testFunc func(b *testing.B, s *BenchTestSuite, pool types.ConcentratedPoolExtension, largeSwapInCoin sdk.Coin, currentTick int64)) {
 	// Notice we stop the timer to skip setup code.
 	b.StopTimer()
 
-	// We cannot use s.Require().NoError() becuase the suite context
-	// is defined on the testing.T and not testing.B
-	noError := func(err error) {
-		require.NoError(b, err)
-	}
-
 	const (
-		numberOfPositions = 10000
-
-		// max amount of each token deposited per position.
-		maxAmountDeposited = int64(1_000_000_000_000)
-
-		// amount swapped in.
-		amountIn = "9999999999999999999"
-
-		// flag controlling whether to create additional numberOfPositions full
-		// range positions for deeper liquidity.
+		numberOfPositions              = 10000
+		maxAmountDeposited             = int64(1_000_000_000_000)
+		amountIn                       = "9999999999999999999"
 		shouldCreateFullRangePositions = true
-
-		// flag controlling whether to create positions concentrated around current tick to mimic
-		// realistic scenario and deeper liquidity.
-		// if true,
-		// creates numberOfPositions positions within 10 ticks of the current tick.
-		// creates numberOfPositions positions within 100 ticks of the current tick.
-		shouldConcentrate = true
-
-		// tickSpacing is the spacing between ticks.
-		tickSpacing = 1
+		shouldConcentrate              = true
+		tickSpacing                    = 1
 	)
 
 	var (
-		// denoms of the pool.
-		denom0 = DefaultCoin0.Denom
-		denom1 = DefaultCoin1.Denom
-
-		// denom of the token to swap in.
-		denomIn = denom0
-
+		denom0               = DefaultCoin0.Denom
+		denom1               = DefaultCoin1.Denom
+		denomIn              = denom0
 		numberOfPositionsInt = sdk.NewInt(numberOfPositions)
 		maxAmountOfEachToken = sdk.NewInt(maxAmountDeposited).Mul(numberOfPositionsInt)
-
-		// Seed controlling determinism of the randomized positions.
-		seed = int64(1)
+		seed                 = int64(1)
 	)
+
 	rand.Seed(seed)
 
 	for i := 0; i < b.N; i++ {
 		s := BenchTestSuite{}
-		s.Setup()
+		cleanup := s.SetupWithLevelDb()
 
-		// Fund all accounts with max amounts they would need to consume.
 		for _, acc := range s.TestAccs {
-			simapp.FundAccount(s.App.BankKeeper, s.Ctx, acc, sdk.NewCoins(sdk.NewCoin(denom0, maxAmountOfEachToken), sdk.NewCoin(denom1, maxAmountOfEachToken), sdk.NewCoin("uosmo", maxAmountOfEachToken)))
+			simapp.FundAccount(s.App.BankKeeper, s.Ctx, acc, sdk.NewCoins(
+				sdk.NewCoin(denom0, maxAmountOfEachToken),
+				sdk.NewCoin(denom1, maxAmountOfEachToken),
+				sdk.NewCoin("uosmo", maxAmountOfEachToken),
+			))
 		}
 
 		// Create a pool
-		poolId, err := s.App.PoolManagerKeeper.CreatePool(s.Ctx, clmodel.NewMsgCreateConcentratedPool(s.TestAccs[0], denom0, denom1, tickSpacing, sdk.MustNewDecFromStr("0.001")))
-		noError(err)
+		poolId, err := s.App.PoolManagerKeeper.CreatePool(s.Ctx, clmodel.NewMsgCreateConcentratedPool(
+			s.TestAccs[0], denom0, denom1, tickSpacing, sdk.MustNewDecFromStr("0.001"),
+		))
+		noError(b, err)
 
 		clKeeper := s.App.ConcentratedLiquidityKeeper
 
@@ -100,89 +85,89 @@ func BenchmarkSwapExactAmountIn(b *testing.B) {
 		tokenDesired1 := sdk.NewCoin(denom1, sdk.NewInt(100))
 		tokensDesired := sdk.NewCoins(tokenDesired0, tokenDesired1)
 		_, _, _, _, _, _, _, err = clKeeper.CreatePosition(s.Ctx, poolId, s.TestAccs[0], tokensDesired, sdk.ZeroInt(), sdk.ZeroInt(), types.MinTick, types.MaxTick)
+		noError(b, err)
 
 		pool, err := clKeeper.GetPoolById(s.Ctx, poolId)
-		noError(err)
+		noError(b, err)
 
 		// Zero by default, can configure by setting a specific position.
 		currentTick := pool.GetCurrentTick()
 
 		// Setup numberOfPositions positions at random ranges
-		for i := 0; i < numberOfPositions; i++ {
-
-			var (
-				lowerTick int64
-				upperTick int64
-			)
-
-			if denomIn == denom0 {
-				// Decreasing price so want to be below current tick
-
-				// minTick <= lowerTick <= currentTick
-				lowerTick = rand.Int63n(currentTick-types.MinTick+1) + types.MinTick
-				// lowerTick <= upperTick <= currentTick
-				upperTick = currentTick - rand.Int63n(int64(math.Abs(float64(currentTick-lowerTick))))
-			} else {
-				// Increasing price so want to be above current tick
-
-				// currentTick <= lowerTick <= maxTick
-				lowerTick := rand.Int63n(types.MaxTick-currentTick+1) + currentTick
-				// lowerTick <= upperTick <= maxTick
-				upperTick = types.MaxTick - rand.Int63n(int64(math.Abs(float64(types.MaxTick-lowerTick))))
-			}
-			// Normalize lowerTick to be a multiple of tickSpacing
-			lowerTick = lowerTick + (tickSpacing - lowerTick%tickSpacing)
-			// Normalize upperTick to be a multiple of tickSpacing
-			upperTick = upperTick - upperTick%tickSpacing
+		setupPositions := func() {
+			for i := 0; i < numberOfPositions; i++ {
+				var (
+					lowerTick int64
+					upperTick int64
+				)
+
+				if denomIn == denom0 {
+					// Decreasing price so want to be below current tick
+					// minTick <= lowerTick <= currentTick
+					lowerTick = rand.Int63n(currentTick-types.MinTick+1) + types.MinTick
+					// lowerTick <= upperTick <= currentTick
+					upperTick = currentTick - rand.Int63n(int64(math.Abs(float64(currentTick-lowerTick))))
+				} else {
+					// Increasing price so want to be above current tick
+					// currentTick <= lowerTick <= maxTick
+					lowerTick = rand.Int63n(types.MaxTick-currentTick+1) + currentTick
+					// lowerTick <= upperTick <= maxTick
+					upperTick = types.MaxTick - rand.Int63n(int64(math.Abs(float64(types.MaxTick-lowerTick))))
+				}
 
-			tokenDesired0 := sdk.NewCoin(denom0, sdk.NewInt(rand.Int63n(maxAmountDeposited)))
-			tokenDesired1 := sdk.NewCoin(denom1, sdk.NewInt(rand.Int63n(maxAmountDeposited)))
+				// Normalize lowerTick to be a multiple of tickSpacing
+				lowerTick = lowerTick + (tickSpacing - lowerTick%tickSpacing)
+				// Normalize upperTick to be a multiple of tickSpacing
+				upperTick = upperTick - upperTick%tickSpacing
 
-			accountIndex := rand.Intn(len(s.TestAccs))
+				priceLowerTick, priceUpperTick, _, _, err := clmath.TicksToSqrtPrice(lowerTick, upperTick)
+				noError(b, err)
 
-			s.createPosition(accountIndex, poolId, tokenDesired0, tokenDesired1, lowerTick, upperTick)
+				lowerTick, upperTick, err = cl.RoundTickToCanonicalPriceTick(
+					lowerTick, upperTick, priceLowerTick, priceUpperTick, tickSpacing,
+				)
+				if err != nil {
+					continue
+				}
+
+				tokenDesired0 := sdk.NewCoin(denom0, sdk.NewInt(rand.Int63n(maxAmountDeposited)))
+				tokenDesired1 := sdk.NewCoin(denom1, sdk.NewInt(rand.Int63n(maxAmountDeposited)))
+
+				accountIndex := rand.Intn(len(s.TestAccs))
+				s.createPosition(accountIndex, poolId, tokenDesired0, tokenDesired1, lowerTick, upperTick)
+			}
 		}
 
 		// Setup numberOfPositions full range positions for deeper liquidity.
-		if shouldCreateFullRangePositions {
+		setupFullRangePositions := func() {
 			for i := 0; i < numberOfPositions; i++ {
 				lowerTick := types.MinTick
 				upperTick := types.MaxTick
-
 				maxAmountDepositedFullRange := sdk.NewInt(maxAmountDeposited).MulRaw(5)
 				tokenDesired0 := sdk.NewCoin(denom0, maxAmountDepositedFullRange)
 				tokenDesired1 := sdk.NewCoin(denom1, maxAmountDepositedFullRange)
 				tokensDesired := sdk.NewCoins(tokenDesired0, tokenDesired1)
-
 				accountIndex := rand.Intn(len(s.TestAccs))
-
 				account := s.TestAccs[accountIndex]
-
 				simapp.FundAccount(s.App.BankKeeper, s.Ctx, account, tokensDesired)
-
 				s.createPosition(accountIndex, poolId, tokenDesired0, tokenDesired1, lowerTick, upperTick)
 			}
 		}
 
 		// Setup numberOfPositions * 2 positions at random ranges around the current tick for deeper
 		// liquidity.
-		if shouldConcentrate {
+		setupConcentratedPositions := func() {
 			// Within 10 ticks of the current
 			if tickSpacing <= 10 {
 				for i := 0; i < numberOfPositions; i++ {
 					lowerTick := currentTick - 10
 					upperTick := currentTick + 10
-
 					tokenDesired0 := sdk.NewCoin(denom0, sdk.NewInt(maxAmountDeposited).MulRaw(5))
 					tokenDesired1 := sdk.NewCoin(denom1, sdk.NewInt(maxAmountDeposited).MulRaw(5))
 					tokensDesired := sdk.NewCoins(tokenDesired0, tokenDesired1)
-
 					accountIndex := rand.Intn(len(s.TestAccs))
-
 					account := s.TestAccs[accountIndex]
-
 					simapp.FundAccount(s.App.BankKeeper, s.Ctx, account, tokensDesired)
-
 					s.createPosition(accountIndex, poolId, tokenDesired0, tokenDesired1, lowerTick, upperTick)
 				}
 			}
@@ -191,48 +176,83 @@ func BenchmarkSwapExactAmountIn(b *testing.B) {
 			for i := 0; i < numberOfPositions; i++ {
 				lowerTick := currentTick - 100
 				upperTick := currentTick + 100
-				// Normalize lowerTick to be a multiple of tickSpacing
 				lowerTick = lowerTick + (tickSpacing - lowerTick%tickSpacing)
-				// Normalize upperTick to be a multiple of tickSpacing
 				upperTick = upperTick - upperTick%tickSpacing
-
 				tokenDesired0 := sdk.NewCoin(denom0, sdk.NewInt(maxAmountDeposited).MulRaw(5))
 				tokenDesired1 := sdk.NewCoin(denom1, sdk.NewInt(maxAmountDeposited).MulRaw(5))
 				tokensDesired := sdk.NewCoins(tokenDesired0, tokenDesired1)
-
 				accountIndex := rand.Intn(len(s.TestAccs))
-
 				account := s.TestAccs[accountIndex]
-
 				simapp.FundAccount(s.App.BankKeeper, s.Ctx, account, tokensDesired)
-
 				s.createPosition(accountIndex, poolId, tokenDesired0, tokenDesired1, lowerTick, upperTick)
 			}
 		}
 
+		setupPositions()
+		if shouldCreateFullRangePositions {
+			setupFullRangePositions()
+		}
+		if shouldConcentrate {
+			setupConcentratedPositions()
+		}
+
 		swapAmountIn := sdk.MustNewDecFromStr(amountIn).TruncateInt()
 		largeSwapInCoin := sdk.NewCoin(denomIn, swapAmountIn)
+		s.Commit()
+
+		testFunc(b, &s, pool, largeSwapInCoin, currentTick)
+		cleanup()
+	}
+}
+
+func BenchmarkSwapExactAmountIn(b *testing.B) {
+	runBenchmark(b, func(b *testing.B, s *BenchTestSuite, pool types.ConcentratedPoolExtension, largeSwapInCoin sdk.Coin, currentTick int64) {
+		clKeeper := s.App.ConcentratedLiquidityKeeper
 
 		liquidityNet, err := clKeeper.GetTickLiquidityNetInDirection(s.Ctx, pool.GetId(), largeSwapInCoin.Denom, sdk.NewInt(currentTick), sdk.Int{})
-		noError(err)
+		noError(b, err)
+		simapp.FundAccount(s.App.BankKeeper, s.Ctx, s.TestAccs[0], sdk.NewCoins(largeSwapInCoin))
 
-		fmt.Println("num_ticks_traversed", len(liquidityNet))
-		fmt.Println("current_tick", currentTick)
+		b.StartTimer()
 
-		// Commit the block so that position updates are propagated to IAVL.
-		s.Commit()
+		// System under test
+		_, err = clKeeper.SwapExactAmountIn(s.Ctx, s.TestAccs[0], pool, largeSwapInCoin, DefaultCoin1.Denom, sdk.NewInt(1), pool.GetSpreadFactor(s.Ctx))
+		b.StopTimer()
+		noError(b, err)
 
-		// Fund swap amount.
-		simapp.FundAccount(s.App.BankKeeper, s.Ctx, s.TestAccs[0], sdk.NewCoins(largeSwapInCoin))
+		fmt.Println("current_tick", currentTick)
+		fmt.Println("num_ticks_traversed", len(liquidityNet))
+	})
+}
+
+func BenchmarkGetTickLiquidityNetInDirection(b *testing.B) {
+	runBenchmark(b, func(b *testing.B, s *BenchTestSuite, pool types.ConcentratedPoolExtension, largeSwapInCoin sdk.Coin, currentTick int64) {
+		clKeeper := s.App.ConcentratedLiquidityKeeper
 
-		// Notice that we start the timer as this is the system under test
 		b.StartTimer()
 
 		// System under test
-		_, err = clKeeper.SwapExactAmountIn(s.Ctx, s.TestAccs[0], pool, largeSwapInCoin, denom1, sdk.NewInt(1), pool.GetSpreadFactor(s.Ctx))
-		noError(err)
+		liquidityNet, err := clKeeper.GetTickLiquidityNetInDirection(s.Ctx, pool.GetId(), largeSwapInCoin.Denom, sdk.NewInt(currentTick), sdk.Int{})
+		b.StopTimer()
+		noError(b, err)
 
-		// Notice that we stop the timer again in case there are multiple iterations.
+		fmt.Println("current_tick", currentTick)
+		fmt.Println("num_ticks_traversed", len(liquidityNet))
+	})
+}
+
+func BenchmarkGetTickLiquidityForFullRange(b *testing.B) {
+	runBenchmark(b, func(b *testing.B, s *BenchTestSuite, pool types.ConcentratedPoolExtension, largeSwapInCoin sdk.Coin, currentTick int64) {
+		clKeeper := s.App.ConcentratedLiquidityKeeper
+
+		b.StartTimer()
+
+		// System under test
+		liquidityNet, err := clKeeper.GetTickLiquidityForFullRange(s.Ctx, pool.GetId())
 		b.StopTimer()
-	}
+		noError(b, err)
+
+		fmt.Println("current_tick", currentTick)
+		fmt.Println("num_ticks_traversed", len(liquidityNet))
+	})
 }
diff --git a/x/concentrated-liquidity/fees_test.go b/x/concentrated-liquidity/fees_test.go
index ffa0ea1a3..a66300467 100644
--- a/x/concentrated-liquidity/fees_test.go
+++ b/x/concentrated-liquidity/fees_test.go
@@ -131,6 +131,7 @@ func (s *KeeperTestSuite) TestInitOrUpdatePositionFeeAccumulator() {
 	}
 
 	clKeeper := s.App.ConcentratedLiquidityKeeper
+	secondPosition := withPositionId(withLowerTick(defaultPositionFields, DefaultLowerTick+1), DefaultPositionId+1)
 
 	type initFeeAccumTest struct {
 		name           string
@@ -152,7 +153,7 @@ func (s *KeeperTestSuite) TestInitOrUpdatePositionFeeAccumulator() {
 		},
 		{
 			name:              "second position",
-			positionFields:    withPositionId(withLowerTick(defaultPositionFields, DefaultLowerTick+1), DefaultPositionId+1),
+			positionFields:    secondPosition,
 			expectedLiquidity: defaultPositionFields.liquidity,
 		},
 		{
@@ -167,7 +168,7 @@ func (s *KeeperTestSuite) TestInitOrUpdatePositionFeeAccumulator() {
 		},
 		{
 			name:              "adding to second position",
-			positionFields:    withPositionId(withLowerTick(defaultPositionFields, DefaultLowerTick+1), DefaultPositionId+1),
+			positionFields:    secondPosition,
 			expectedLiquidity: defaultPositionFields.liquidity.MulInt64(2),
 		},
 		{
diff --git a/x/concentrated-liquidity/incentives_test.go b/x/concentrated-liquidity/incentives_test.go
index 81ccff609..0cbbb8cfd 100644
--- a/x/concentrated-liquidity/incentives_test.go
+++ b/x/concentrated-liquidity/incentives_test.go
@@ -1168,14 +1168,12 @@ func (s *KeeperTestSuite) TestGetInitialUptimeGrowthOppositeDirectionOfLastTrave
 	}
 }
 
-func (s *KeeperTestSuite) TestGetUptimeGrowthInsideRange() {
-	defaultPoolId := uint64(1)
+// Test uptime growth inside and outside range.
+func (s *KeeperTestSuite) TestGetUptimeGrowthRange() {
 	defaultInitialLiquidity := sdk.OneDec()
 	uptimeHelper := getExpectedUptimes()
 
-	type uptimeGrowthOutsideTest struct {
-		poolSetup bool
-
+	type uptimeGrowthTest struct {
 		lowerTick                    int64
 		upperTick                    int64
 		currentTick                  int64
@@ -1183,15 +1181,13 @@ func (s *KeeperTestSuite) TestGetUptimeGrowthInsideRange() {
 		upperTickUptimeGrowthOutside []sdk.DecCoins
 		globalUptimeGrowth           []sdk.DecCoins
 
-		expectedUptimeGrowthInside []sdk.DecCoins
-		expectedError              bool
+		expectedUptimeGrowthInside  []sdk.DecCoins
+		expectedUptimeGrowthOutside []sdk.DecCoins
 	}
 
-	tests := map[string]uptimeGrowthOutsideTest{
+	tests := map[string]uptimeGrowthTest{
 		// current tick above range
-
 		"current tick > upper tick, nonzero uptime growth inside": {
-			poolSetup:                    true,
 			lowerTick:                    0,
 			upperTick:                    1,
 			currentTick:                  2,
@@ -1201,10 +1197,10 @@ func (s *KeeperTestSuite) TestGetUptimeGrowthInsideRange() {
 
 			// Since current tick is above range, we expect upper - lower
 			expectedUptimeGrowthInside: uptimeHelper.hundredTokensMultiDenom,
-			expectedError:              false,
+			// Since current tick is above range, we expect global - (upper - lower)
+			expectedUptimeGrowthOutside: uptimeHelper.twoHundredTokensMultiDenom,
 		},
 		"current tick > upper tick, nonzero uptime growth inside (wider range)": {
-			poolSetup:                    true,
 			lowerTick:                    12444,
 			upperTick:                    15013,
 			currentTick:                  50320,
@@ -1214,10 +1210,10 @@ func (s *KeeperTestSuite) TestGetUptimeGrowthInsideRange() {
 
 			// Since current tick is above range, we expect upper - lower
 			expectedUptimeGrowthInside: uptimeHelper.hundredTokensMultiDenom,
-			expectedError:              false,
+			// Since current tick is above range, we expect global - (upper - lower)
+			expectedUptimeGrowthOutside: uptimeHelper.twoHundredTokensMultiDenom,
 		},
 		"current tick > upper tick, zero uptime growth inside (nonempty trackers)": {
-			poolSetup:                    true,
 			lowerTick:                    0,
 			upperTick:                    1,
 			currentTick:                  2,
@@ -1227,10 +1223,10 @@ func (s *KeeperTestSuite) TestGetUptimeGrowthInsideRange() {
 
 			// Since current tick is above range, we expect upper - lower
 			expectedUptimeGrowthInside: uptimeHelper.emptyExpectedAccumValues,
-			expectedError:              false,
+			// Since the range is empty, we expect growth outside to be equal to global
+			expectedUptimeGrowthOutside: uptimeHelper.threeHundredTokensMultiDenom,
 		},
 		"current tick > upper tick, zero uptime growth inside (empty trackers)": {
-			poolSetup:                    true,
 			lowerTick:                    0,
 			upperTick:                    1,
 			currentTick:                  2,
@@ -1240,10 +1236,10 @@ func (s *KeeperTestSuite) TestGetUptimeGrowthInsideRange() {
 
 			// Since current tick is above range, we expect upper - lower
 			expectedUptimeGrowthInside: uptimeHelper.emptyExpectedAccumValues,
-			expectedError:              false,
+			// Since the range is empty, we expect growth outside to be equal to global
+			expectedUptimeGrowthOutside: uptimeHelper.emptyExpectedAccumValues,
 		},
 		"current tick > upper tick, zero uptime growth inside with extraneous uptime growth": {
-			poolSetup:                    true,
 			lowerTick:                    0,
 			upperTick:                    1,
 			currentTick:                  2,
@@ -1253,13 +1249,13 @@ func (s *KeeperTestSuite) TestGetUptimeGrowthInsideRange() {
 
 			// Since current tick is above range, we expect upper - lower
 			expectedUptimeGrowthInside: uptimeHelper.emptyExpectedAccumValues,
-			expectedError:              false,
+			// Since the range is empty, we expect growth outside to be equal to global
+			expectedUptimeGrowthOutside: uptimeHelper.twoHundredTokensMultiDenom,
 		},
 
 		// current tick within range
 
 		"upper tick > current tick > lower tick, nonzero uptime growth inside": {
-			poolSetup:                    true,
 			lowerTick:                    0,
 			upperTick:                    2,
 			currentTick:                  1,
@@ -1269,10 +1265,10 @@ func (s *KeeperTestSuite) TestGetUptimeGrowthInsideRange() {
 
 			// Since current tick is within range, we expect global - upper - lower
 			expectedUptimeGrowthInside: uptimeHelper.hundredTokensMultiDenom,
-			expectedError:              false,
+			// Since current tick is within range, we expect global - (global - upper - lower)
+			expectedUptimeGrowthOutside: uptimeHelper.twoHundredTokensMultiDenom,
 		},
 		"upper tick > current tick > lower tick, nonzero uptime growth inside (wider range)": {
-			poolSetup:                    true,
 			lowerTick:                    -19753,
 			upperTick:                    8921,
 			currentTick:                  -97,
@@ -1282,10 +1278,10 @@ func (s *KeeperTestSuite) TestGetUptimeGrowthInsideRange() {
 
 			// Since current tick is within range, we expect global - upper - lower
 			expectedUptimeGrowthInside: uptimeHelper.hundredTokensMultiDenom,
-			expectedError:              false,
+			// Since current tick is within range, we expect global - (global - upper - lower)
+			expectedUptimeGrowthOutside: uptimeHelper.twoHundredTokensMultiDenom,
 		},
 		"upper tick > current tick > lower tick, zero uptime growth inside (nonempty trackers)": {
-			poolSetup:                    true,
 			lowerTick:                    0,
 			upperTick:                    2,
 			currentTick:                  1,
@@ -1295,10 +1291,10 @@ func (s *KeeperTestSuite) TestGetUptimeGrowthInsideRange() {
 
 			// Since current tick is within range, we expect global - upper - lower
 			expectedUptimeGrowthInside: uptimeHelper.emptyExpectedAccumValues,
-			expectedError:              false,
+			// Since the range is empty, we expect growth outside to be equal to global
+			expectedUptimeGrowthOutside: uptimeHelper.twoHundredTokensMultiDenom,
 		},
 		"upper tick > current tick > lower tick, zero uptime growth inside (empty trackers)": {
-			poolSetup:                    true,
 			lowerTick:                    0,
 			upperTick:                    2,
 			currentTick:                  1,
@@ -1308,13 +1304,13 @@ func (s *KeeperTestSuite) TestGetUptimeGrowthInsideRange() {
 
 			// Since current tick is within range, we expect global - upper - lower
 			expectedUptimeGrowthInside: uptimeHelper.emptyExpectedAccumValues,
-			expectedError:              false,
+			// Since the range is empty, we expect growth outside to be equal to global
+			expectedUptimeGrowthOutside: uptimeHelper.emptyExpectedAccumValues,
 		},
 
 		// current tick below range
 
 		"current tick < lower tick, nonzero uptime growth inside": {
-			poolSetup:                    true,
 			lowerTick:                    0,
 			upperTick:                    1,
 			currentTick:                  -1,
@@ -1324,10 +1320,10 @@ func (s *KeeperTestSuite) TestGetUptimeGrowthInsideRange() {
 
 			// Since current tick is below range, we expect lower - upper
 			expectedUptimeGrowthInside: uptimeHelper.hundredTokensMultiDenom,
-			expectedError:              false,
+			// Since current tick is below range, we expect global - (lower - upper)
+			expectedUptimeGrowthOutside: uptimeHelper.twoHundredTokensMultiDenom,
 		},
 		"current tick < lower tick, nonzero uptime growth inside (wider range)": {
-			poolSetup:                    true,
 			lowerTick:                    328,
 			upperTick:                    726,
 			currentTick:                  189,
@@ -1337,10 +1333,10 @@ func (s *KeeperTestSuite) TestGetUptimeGrowthInsideRange() {
 
 			// Since current tick is below range, we expect lower - upper
 			expectedUptimeGrowthInside: uptimeHelper.hundredTokensMultiDenom,
-			expectedError:              false,
+			// Since current tick is below range, we expect global - (lower - upper)
+			expectedUptimeGrowthOutside: uptimeHelper.twoHundredTokensMultiDenom,
 		},
 		"current tick < lower tick, zero uptime growth inside (nonempty trackers)": {
-			poolSetup:                    true,
 			lowerTick:                    0,
 			upperTick:                    1,
 			currentTick:                  -1,
@@ -1350,10 +1346,10 @@ func (s *KeeperTestSuite) TestGetUptimeGrowthInsideRange() {
 
 			// Since current tick is below range, we expect lower - upper
 			expectedUptimeGrowthInside: uptimeHelper.emptyExpectedAccumValues,
-			expectedError:              false,
+			// Since the range is empty, we expect growth outside to be equal to global
+			expectedUptimeGrowthOutside: uptimeHelper.threeHundredTokensMultiDenom,
 		},
 		"current tick < lower tick, zero uptime growth inside (empty trackers)": {
-			poolSetup:                    true,
 			lowerTick:                    0,
 			upperTick:                    1,
 			currentTick:                  -1,
@@ -1363,13 +1359,13 @@ func (s *KeeperTestSuite) TestGetUptimeGrowthInsideRange() {
 
 			// Since current tick is below range, we expect lower - upper
 			expectedUptimeGrowthInside: uptimeHelper.emptyExpectedAccumValues,
-			expectedError:              false,
+			// Since the range is empty, we expect growth outside to be equal to global
+			expectedUptimeGrowthOutside: uptimeHelper.emptyExpectedAccumValues,
 		},
 
 		// current tick on range boundary
 
 		"current tick = lower tick, nonzero uptime growth inside": {
-			poolSetup:                    true,
 			lowerTick:                    0,
 			upperTick:                    1,
 			currentTick:                  0,
@@ -1380,10 +1376,11 @@ func (s *KeeperTestSuite) TestGetUptimeGrowthInsideRange() {
 			// Since we treat the range as [lower, upper) (i.e. inclusive of lower tick, exclusive of upper),
 			// this case is equivalent to the current tick being within the range (global - upper - lower)
 			expectedUptimeGrowthInside: uptimeHelper.hundredTokensMultiDenom,
-			expectedError:              false,
+			// Since we treat the range as [lower, upper) (i.e. inclusive of lower tick, exclusive of upper),
+			// this case is equivalent to the current tick being within the range (global - (global - upper - lower))
+			expectedUptimeGrowthOutside: uptimeHelper.threeHundredTokensMultiDenom,
 		},
 		"current tick = lower tick, zero uptime growth inside (nonempty trackers)": {
-			poolSetup:                    true,
 			lowerTick:                    0,
 			upperTick:                    1,
 			currentTick:                  0,
@@ -1394,10 +1391,10 @@ func (s *KeeperTestSuite) TestGetUptimeGrowthInsideRange() {
 			// Since we treat the range as [lower, upper) (i.e. inclusive of lower tick, exclusive of upper),
 			// this case is equivalent to the current tick being within the range (global - upper - lower)
 			expectedUptimeGrowthInside: uptimeHelper.emptyExpectedAccumValues,
-			expectedError:              false,
+			// Since the range is empty, we expect growth outside to be equal to global
+			expectedUptimeGrowthOutside: uptimeHelper.twoHundredTokensMultiDenom,
 		},
 		"current tick = lower tick, zero uptime growth inside (empty trackers)": {
-			poolSetup:                    true,
 			lowerTick:                    0,
 			upperTick:                    1,
 			currentTick:                  0,
@@ -1408,10 +1405,10 @@ func (s *KeeperTestSuite) TestGetUptimeGrowthInsideRange() {
 			// Since we treat the range as [lower, upper) (i.e. inclusive of lower tick, exclusive of upper),
 			// this case is equivalent to the current tick being within the range (global - upper - lower)
 			expectedUptimeGrowthInside: uptimeHelper.emptyExpectedAccumValues,
-			expectedError:              false,
+			// Since the range is empty, we expect growth outside to be equal to global
+			expectedUptimeGrowthOutside: uptimeHelper.emptyExpectedAccumValues,
 		},
 		"current tick = upper tick, nonzero uptime growth inside": {
-			poolSetup:                    true,
 			lowerTick:                    0,
 			upperTick:                    1,
 			currentTick:                  1,
@@ -1422,10 +1419,11 @@ func (s *KeeperTestSuite) TestGetUptimeGrowthInsideRange() {
 			// Since we treat the range as [lower, upper) (i.e. inclusive of lower tick, exclusive of upper),
 			// this case is equivalent to the current tick being above the range (upper - lower)
 			expectedUptimeGrowthInside: uptimeHelper.hundredTokensMultiDenom,
-			expectedError:              false,
+			// Since we treat the range as [lower, upper) (i.e. inclusive of lower tick, exclusive of upper),
+			// this case is equivalent to the current tick being above the range (global - (upper - lower))
+			expectedUptimeGrowthOutside: uptimeHelper.threeHundredTokensMultiDenom,
 		},
 		"current tick = upper tick, zero uptime growth inside (nonempty trackers)": {
-			poolSetup:                    true,
 			lowerTick:                    0,
 			upperTick:                    1,
 			currentTick:                  1,
@@ -1436,10 +1434,10 @@ func (s *KeeperTestSuite) TestGetUptimeGrowthInsideRange() {
 			// Since we treat the range as [lower, upper) (i.e. inclusive of lower tick, exclusive of upper),
 			// this case is equivalent to the current tick being above the range (upper - lower)
 			expectedUptimeGrowthInside: uptimeHelper.emptyExpectedAccumValues,
-			expectedError:              false,
+			// Since the range is empty, we expect growth outside to be equal to global
+			expectedUptimeGrowthOutside: uptimeHelper.twoHundredTokensMultiDenom,
 		},
 		"current tick = upper tick, zero uptime growth inside (empty trackers)": {
-			poolSetup:                    true,
 			lowerTick:                    0,
 			upperTick:                    1,
 			currentTick:                  1,
@@ -1450,339 +1448,8 @@ func (s *KeeperTestSuite) TestGetUptimeGrowthInsideRange() {
 			// Since we treat the range as [lower, upper) (i.e. inclusive of lower tick, exclusive of upper),
 			// this case is equivalent to the current tick being above the range (upper - lower)
 			expectedUptimeGrowthInside: uptimeHelper.emptyExpectedAccumValues,
-			expectedError:              false,
-		},
-
-		// error catching
-
-		"error: pool has not been setup": {
-			poolSetup:     false,
-			expectedError: true,
-		},
-	}
-
-	for name, tc := range tests {
-		s.Run(name, func() {
-			s.SetupTest()
-
-			// if pool set up true, set up default pool
-			var pool types.ConcentratedPoolExtension
-			if tc.poolSetup {
-				pool = s.PrepareConcentratedPool()
-				currentTick := pool.GetCurrentTick()
-
-				// Update global uptime accums
-				err := addToUptimeAccums(s.Ctx, pool.GetId(), s.App.ConcentratedLiquidityKeeper, tc.globalUptimeGrowth)
-				s.Require().NoError(err)
-
-				// Update tick-level uptime trackers
-				s.initializeTick(s.Ctx, currentTick, tc.lowerTick, defaultInitialLiquidity, cl.EmptyCoins, wrapUptimeTrackers(tc.lowerTickUptimeGrowthOutside), true)
-				s.initializeTick(s.Ctx, currentTick, tc.upperTick, defaultInitialLiquidity, cl.EmptyCoins, wrapUptimeTrackers(tc.upperTickUptimeGrowthOutside), false)
-				pool.SetCurrentTick(tc.currentTick)
-				err = s.App.ConcentratedLiquidityKeeper.SetPool(s.Ctx, pool)
-				s.Require().NoError(err)
-			}
-
-			// system under test
-			uptimeGrowthInside, err := s.App.ConcentratedLiquidityKeeper.GetUptimeGrowthInsideRange(s.Ctx, defaultPoolId, tc.lowerTick, tc.upperTick)
-			if tc.expectedError {
-				s.Require().Error(err)
-			} else {
-				s.Require().NoError(err)
-
-				// check if returned uptime growth inside has correct value
-				s.Require().Equal(tc.expectedUptimeGrowthInside, uptimeGrowthInside)
-			}
-		})
-	}
-}
-
-func (s *KeeperTestSuite) TestGetUptimeGrowthOutsideRange() {
-	defaultPoolId := uint64(1)
-	defaultInitialLiquidity := sdk.OneDec()
-	uptimeHelper := getExpectedUptimes()
-
-	type uptimeGrowthOutsideTest struct {
-		poolSetup bool
-
-		lowerTick                    int64
-		upperTick                    int64
-		currentTick                  int64
-		lowerTickUptimeGrowthOutside []sdk.DecCoins
-		upperTickUptimeGrowthOutside []sdk.DecCoins
-		globalUptimeGrowth           []sdk.DecCoins
-
-		expectedUptimeGrowthOutside []sdk.DecCoins
-		expectedError               bool
-	}
-
-	tests := map[string]uptimeGrowthOutsideTest{
-		// current tick above range
-
-		"current tick > upper tick, nonzero uptime growth inside": {
-			poolSetup:                    true,
-			lowerTick:                    0,
-			upperTick:                    1,
-			currentTick:                  2,
-			lowerTickUptimeGrowthOutside: uptimeHelper.hundredTokensMultiDenom,
-			upperTickUptimeGrowthOutside: uptimeHelper.twoHundredTokensMultiDenom,
-			globalUptimeGrowth:           uptimeHelper.threeHundredTokensMultiDenom,
-
-			// Since current tick is above range, we expect global - (upper - lower)
-			expectedUptimeGrowthOutside: uptimeHelper.twoHundredTokensMultiDenom,
-			expectedError:               false,
-		},
-		"current tick > upper tick, nonzero uptime growth inside (wider range)": {
-			poolSetup:                    true,
-			lowerTick:                    12444,
-			upperTick:                    15013,
-			currentTick:                  50320,
-			lowerTickUptimeGrowthOutside: uptimeHelper.hundredTokensMultiDenom,
-			upperTickUptimeGrowthOutside: uptimeHelper.twoHundredTokensMultiDenom,
-			globalUptimeGrowth:           uptimeHelper.threeHundredTokensMultiDenom,
-
-			// Since current tick is above range, we expect global - (upper - lower)
-			expectedUptimeGrowthOutside: uptimeHelper.twoHundredTokensMultiDenom,
-			expectedError:               false,
-		},
-		"current tick > upper tick, zero uptime growth inside (nonempty trackers)": {
-			poolSetup:                    true,
-			lowerTick:                    0,
-			upperTick:                    1,
-			currentTick:                  2,
-			lowerTickUptimeGrowthOutside: uptimeHelper.hundredTokensMultiDenom,
-			upperTickUptimeGrowthOutside: uptimeHelper.hundredTokensMultiDenom,
-			globalUptimeGrowth:           uptimeHelper.threeHundredTokensMultiDenom,
-
-			// Since the range is empty, we expect growth outside to be equal to global
-			expectedUptimeGrowthOutside: uptimeHelper.threeHundredTokensMultiDenom,
-			expectedError:               false,
-		},
-		"current tick > upper tick, zero uptime growth inside (empty trackers)": {
-			poolSetup:                    true,
-			lowerTick:                    0,
-			upperTick:                    1,
-			currentTick:                  2,
-			lowerTickUptimeGrowthOutside: uptimeHelper.emptyExpectedAccumValues,
-			upperTickUptimeGrowthOutside: uptimeHelper.emptyExpectedAccumValues,
-			globalUptimeGrowth:           uptimeHelper.emptyExpectedAccumValues,
-
-			// Since the range is empty, we expect growth outside to be equal to global
-			expectedUptimeGrowthOutside: uptimeHelper.emptyExpectedAccumValues,
-			expectedError:               false,
-		},
-		"current tick > upper tick, zero uptime growth inside with extraneous uptime growth": {
-			poolSetup:                    true,
-			lowerTick:                    0,
-			upperTick:                    1,
-			currentTick:                  2,
-			lowerTickUptimeGrowthOutside: uptimeHelper.hundredTokensMultiDenom,
-			upperTickUptimeGrowthOutside: uptimeHelper.hundredTokensMultiDenom,
-			globalUptimeGrowth:           uptimeHelper.twoHundredTokensMultiDenom,
-
-			// Since the range is empty, we expect growth outside to be equal to global
-			expectedUptimeGrowthOutside: uptimeHelper.twoHundredTokensMultiDenom,
-			expectedError:               false,
-		},
-
-		// current tick within range
-
-		"upper tick > current tick > lower tick, nonzero uptime growth inside": {
-			poolSetup:                    true,
-			lowerTick:                    0,
-			upperTick:                    2,
-			currentTick:                  1,
-			lowerTickUptimeGrowthOutside: uptimeHelper.hundredTokensMultiDenom,
-			upperTickUptimeGrowthOutside: uptimeHelper.hundredTokensMultiDenom,
-			globalUptimeGrowth:           uptimeHelper.threeHundredTokensMultiDenom,
-
-			// Since current tick is within range, we expect global - (global - upper - lower)
-			expectedUptimeGrowthOutside: uptimeHelper.twoHundredTokensMultiDenom,
-			expectedError:               false,
-		},
-		"upper tick > current tick > lower tick, nonzero uptime growth inside (wider range)": {
-			poolSetup:                    true,
-			lowerTick:                    -19753,
-			upperTick:                    8921,
-			currentTick:                  -97,
-			lowerTickUptimeGrowthOutside: uptimeHelper.hundredTokensMultiDenom,
-			upperTickUptimeGrowthOutside: uptimeHelper.hundredTokensMultiDenom,
-			globalUptimeGrowth:           uptimeHelper.twoHundredTokensMultiDenom,
-
-			// Since current tick is within range, we expect global - (global - upper - lower)
-			expectedUptimeGrowthOutside: uptimeHelper.twoHundredTokensMultiDenom,
-			expectedError:               false,
-		},
-		"upper tick > current tick > lower tick, zero uptime growth inside (nonempty trackers)": {
-			poolSetup:                    true,
-			lowerTick:                    0,
-			upperTick:                    2,
-			currentTick:                  1,
-			lowerTickUptimeGrowthOutside: uptimeHelper.hundredTokensMultiDenom,
-			upperTickUptimeGrowthOutside: uptimeHelper.hundredTokensMultiDenom,
-			globalUptimeGrowth:           uptimeHelper.twoHundredTokensMultiDenom,
-
-			// Since the range is empty, we expect growth outside to be equal to global
-			expectedUptimeGrowthOutside: uptimeHelper.twoHundredTokensMultiDenom,
-			expectedError:               false,
-		},
-		"upper tick > current tick > lower tick, zero uptime growth inside (empty trackers)": {
-			poolSetup:                    true,
-			lowerTick:                    0,
-			upperTick:                    2,
-			currentTick:                  1,
-			lowerTickUptimeGrowthOutside: uptimeHelper.emptyExpectedAccumValues,
-			upperTickUptimeGrowthOutside: uptimeHelper.emptyExpectedAccumValues,
-			globalUptimeGrowth:           uptimeHelper.emptyExpectedAccumValues,
-
-			// Since the range is empty, we expect growth outside to be equal to global
-			expectedUptimeGrowthOutside: uptimeHelper.emptyExpectedAccumValues,
-			expectedError:               false,
-		},
-
-		// current tick below range
-
-		"current tick < lower tick, nonzero uptime growth inside": {
-			poolSetup:                    true,
-			lowerTick:                    0,
-			upperTick:                    1,
-			currentTick:                  -1,
-			lowerTickUptimeGrowthOutside: uptimeHelper.twoHundredTokensMultiDenom,
-			upperTickUptimeGrowthOutside: uptimeHelper.hundredTokensMultiDenom,
-			globalUptimeGrowth:           uptimeHelper.threeHundredTokensMultiDenom,
-
-			// Since current tick is below range, we expect global - (lower - upper)
-			expectedUptimeGrowthOutside: uptimeHelper.twoHundredTokensMultiDenom,
-			expectedError:               false,
-		},
-		"current tick < lower tick, nonzero uptime growth inside (wider range)": {
-			poolSetup:                    true,
-			lowerTick:                    328,
-			upperTick:                    726,
-			currentTick:                  189,
-			lowerTickUptimeGrowthOutside: uptimeHelper.twoHundredTokensMultiDenom,
-			upperTickUptimeGrowthOutside: uptimeHelper.hundredTokensMultiDenom,
-			globalUptimeGrowth:           uptimeHelper.threeHundredTokensMultiDenom,
-
-			// Since current tick is below range, we expect global - (lower - upper)
-			expectedUptimeGrowthOutside: uptimeHelper.twoHundredTokensMultiDenom,
-			expectedError:               false,
-		},
-		"current tick < lower tick, zero uptime growth inside (nonempty trackers)": {
-			poolSetup:                    true,
-			lowerTick:                    0,
-			upperTick:                    1,
-			currentTick:                  -1,
-			lowerTickUptimeGrowthOutside: uptimeHelper.hundredTokensMultiDenom,
-			upperTickUptimeGrowthOutside: uptimeHelper.hundredTokensMultiDenom,
-			globalUptimeGrowth:           uptimeHelper.threeHundredTokensMultiDenom,
-
-			// Since the range is empty, we expect growth outside to be equal to global
-			expectedUptimeGrowthOutside: uptimeHelper.threeHundredTokensMultiDenom,
-			expectedError:               false,
-		},
-		"current tick < lower tick, zero uptime growth inside (empty trackers)": {
-			poolSetup:                    true,
-			lowerTick:                    0,
-			upperTick:                    1,
-			currentTick:                  -1,
-			lowerTickUptimeGrowthOutside: uptimeHelper.emptyExpectedAccumValues,
-			upperTickUptimeGrowthOutside: uptimeHelper.emptyExpectedAccumValues,
-			globalUptimeGrowth:           uptimeHelper.emptyExpectedAccumValues,
-
 			// Since the range is empty, we expect growth outside to be equal to global
 			expectedUptimeGrowthOutside: uptimeHelper.emptyExpectedAccumValues,
-			expectedError:               false,
-		},
-
-		// current tick on range boundary
-
-		"current tick = lower tick, nonzero uptime growth inside": {
-			poolSetup:                    true,
-			lowerTick:                    0,
-			upperTick:                    1,
-			currentTick:                  0,
-			lowerTickUptimeGrowthOutside: uptimeHelper.twoHundredTokensMultiDenom,
-			upperTickUptimeGrowthOutside: uptimeHelper.hundredTokensMultiDenom,
-			globalUptimeGrowth:           uptimeHelper.fourHundredTokensMultiDenom,
-
-			// Since we treat the range as [lower, upper) (i.e. inclusive of lower tick, exclusive of upper),
-			// this case is equivalent to the current tick being within the range (global - (global - upper - lower))
-			expectedUptimeGrowthOutside: uptimeHelper.threeHundredTokensMultiDenom,
-			expectedError:               false,
-		},
-		"current tick = lower tick, zero uptime growth inside (nonempty trackers)": {
-			poolSetup:                    true,
-			lowerTick:                    0,
-			upperTick:                    1,
-			currentTick:                  0,
-			lowerTickUptimeGrowthOutside: uptimeHelper.hundredTokensMultiDenom,
-			upperTickUptimeGrowthOutside: uptimeHelper.hundredTokensMultiDenom,
-			globalUptimeGrowth:           uptimeHelper.twoHundredTokensMultiDenom,
-
-			// Since the range is empty, we expect growth outside to be equal to global
-			expectedUptimeGrowthOutside: uptimeHelper.twoHundredTokensMultiDenom,
-			expectedError:               false,
-		},
-		"current tick = lower tick, zero uptime growth inside (empty trackers)": {
-			poolSetup:                    true,
-			lowerTick:                    0,
-			upperTick:                    1,
-			currentTick:                  0,
-			lowerTickUptimeGrowthOutside: uptimeHelper.emptyExpectedAccumValues,
-			upperTickUptimeGrowthOutside: uptimeHelper.emptyExpectedAccumValues,
-			globalUptimeGrowth:           uptimeHelper.emptyExpectedAccumValues,
-
-			// Since the range is empty, we expect growth outside to be equal to global
-			expectedUptimeGrowthOutside: uptimeHelper.emptyExpectedAccumValues,
-			expectedError:               false,
-		},
-		"current tick = upper tick, nonzero uptime growth inside": {
-			poolSetup:                    true,
-			lowerTick:                    0,
-			upperTick:                    1,
-			currentTick:                  1,
-			lowerTickUptimeGrowthOutside: uptimeHelper.hundredTokensMultiDenom,
-			upperTickUptimeGrowthOutside: uptimeHelper.twoHundredTokensMultiDenom,
-			globalUptimeGrowth:           uptimeHelper.fourHundredTokensMultiDenom,
-
-			// Since we treat the range as [lower, upper) (i.e. inclusive of lower tick, exclusive of upper),
-			// this case is equivalent to the current tick being above the range (global - (upper - lower))
-			expectedUptimeGrowthOutside: uptimeHelper.threeHundredTokensMultiDenom,
-			expectedError:               false,
-		},
-		"current tick = upper tick, zero uptime growth inside (nonempty trackers)": {
-			poolSetup:                    true,
-			lowerTick:                    0,
-			upperTick:                    1,
-			currentTick:                  1,
-			lowerTickUptimeGrowthOutside: uptimeHelper.hundredTokensMultiDenom,
-			upperTickUptimeGrowthOutside: uptimeHelper.hundredTokensMultiDenom,
-			globalUptimeGrowth:           uptimeHelper.twoHundredTokensMultiDenom,
-
-			// Since the range is empty, we expect growth outside to be equal to global
-			expectedUptimeGrowthOutside: uptimeHelper.twoHundredTokensMultiDenom,
-			expectedError:               false,
-		},
-		"current tick = upper tick, zero uptime growth inside (empty trackers)": {
-			poolSetup:                    true,
-			lowerTick:                    0,
-			upperTick:                    1,
-			currentTick:                  1,
-			lowerTickUptimeGrowthOutside: uptimeHelper.emptyExpectedAccumValues,
-			upperTickUptimeGrowthOutside: uptimeHelper.emptyExpectedAccumValues,
-			globalUptimeGrowth:           uptimeHelper.emptyExpectedAccumValues,
-
-			// Since the range is empty, we expect growth outside to be equal to global
-			expectedUptimeGrowthOutside: uptimeHelper.emptyExpectedAccumValues,
-			expectedError:               false,
-		},
-
-		// error catching
-
-		"error: pool has not been setup": {
-			poolSetup:     false,
-			expectedError: true,
 		},
 	}
 
@@ -1790,38 +1457,43 @@ func (s *KeeperTestSuite) TestGetUptimeGrowthOutsideRange() {
 		s.Run(name, func() {
 			s.SetupTest()
 
-			// if pool set up true, set up default pool
-			var pool types.ConcentratedPoolExtension
-			if tc.poolSetup {
-				pool = s.PrepareConcentratedPool()
-				currentTick := pool.GetCurrentTick()
+			pool := s.PrepareConcentratedPool()
+			currentTick := pool.GetCurrentTick()
 
-				// Update global uptime accums
-				err := addToUptimeAccums(s.Ctx, pool.GetId(), s.App.ConcentratedLiquidityKeeper, tc.globalUptimeGrowth)
-				s.Require().NoError(err)
+			// Update global uptime accums
+			err := addToUptimeAccums(s.Ctx, pool.GetId(), s.App.ConcentratedLiquidityKeeper, tc.globalUptimeGrowth)
+			s.Require().NoError(err)
 
-				// Update tick-level uptime trackers
-				s.initializeTick(s.Ctx, currentTick, tc.lowerTick, defaultInitialLiquidity, cl.EmptyCoins, wrapUptimeTrackers(tc.lowerTickUptimeGrowthOutside), true)
-				s.initializeTick(s.Ctx, currentTick, tc.upperTick, defaultInitialLiquidity, cl.EmptyCoins, wrapUptimeTrackers(tc.upperTickUptimeGrowthOutside), false)
-				pool.SetCurrentTick(tc.currentTick)
-				err = s.App.ConcentratedLiquidityKeeper.SetPool(s.Ctx, pool)
-				s.Require().NoError(err)
-			}
+			// Update tick-level uptime trackers
+			s.initializeTick(s.Ctx, currentTick, tc.lowerTick, defaultInitialLiquidity, cl.EmptyCoins, wrapUptimeTrackers(tc.lowerTickUptimeGrowthOutside), true)
+			s.initializeTick(s.Ctx, currentTick, tc.upperTick, defaultInitialLiquidity, cl.EmptyCoins, wrapUptimeTrackers(tc.upperTickUptimeGrowthOutside), false)
+			pool.SetCurrentTick(tc.currentTick)
+			err = s.App.ConcentratedLiquidityKeeper.SetPool(s.Ctx, pool)
+			s.Require().NoError(err)
 
 			// system under test
-			uptimeGrowthOutside, err := s.App.ConcentratedLiquidityKeeper.GetUptimeGrowthOutsideRange(s.Ctx, defaultPoolId, tc.lowerTick, tc.upperTick)
-			if tc.expectedError {
-				s.Require().Error(err)
-			} else {
-				s.Require().NoError(err)
+			uptimeGrowthInside, err := s.App.ConcentratedLiquidityKeeper.GetUptimeGrowthInsideRange(s.Ctx, pool.GetId(), tc.lowerTick, tc.upperTick)
+			s.Require().NoError(err)
 
-				// check if returned uptime growth inside has correct value
-				s.Require().Equal(tc.expectedUptimeGrowthOutside, uptimeGrowthOutside)
-			}
+			// check if returned uptime growth inside has correct value
+			s.Require().Equal(tc.expectedUptimeGrowthInside, uptimeGrowthInside)
+
+			uptimeGrowthOutside, err := s.App.ConcentratedLiquidityKeeper.GetUptimeGrowthOutsideRange(s.Ctx, pool.GetId(), tc.lowerTick, tc.upperTick)
+			s.Require().NoError(err)
+
+			// check if returned uptime growth inside has correct value
+			s.Require().Equal(tc.expectedUptimeGrowthOutside, uptimeGrowthOutside)
 		})
 	}
 }
 
+func (s *KeeperTestSuite) TestGetUptimeGrowthErrors() {
+	_, err := s.App.ConcentratedLiquidityKeeper.GetUptimeGrowthInsideRange(s.Ctx, defaultPoolId, 0, 0)
+	s.Require().Error(err)
+	_, err = s.App.ConcentratedLiquidityKeeper.GetUptimeGrowthOutsideRange(s.Ctx, defaultPoolId, 0, 0)
+	s.Require().Error(err)
+}
+
 func (s *KeeperTestSuite) TestInitOrUpdatePositionUptimeAccumulators() {
 	uptimeHelper := getExpectedUptimes()
 	type tick struct {
@@ -2077,13 +1749,24 @@ func (s *KeeperTestSuite) TestQueryAndCollectIncentives() {
 		positionId  uint64
 	}
 
+	default0To2PosParam := positionParameters{
+		owner:       ownerWithValidPosition,
+		lowerTick:   0,
+		upperTick:   2,
+		liquidity:   DefaultLiquidityAmt,
+		joinTime:    defaultJoinTime,
+		positionId:  DefaultPositionId,
+		collectTime: defaultJoinTime.Add(100),
+	}
+	default1To2PosParam := default0To2PosParam
+	default1To2PosParam.lowerTick = 1
+
 	tests := map[string]struct {
 		// setup parameters
 		existingAccumLiquidity   []sdk.Dec
 		addedUptimeGrowthInside  []sdk.DecCoins
 		addedUptimeGrowthOutside []sdk.DecCoins
 		currentTick              int64
-		isInvalidPoolIdGiven     bool
 		numPositions             int
 
 		// inputs parameters
@@ -2098,16 +1781,8 @@ func (s *KeeperTestSuite) TestQueryAndCollectIncentives() {
 		// ---Cases for lowerTick < currentTick < upperTick---
 
 		"(lower < curr < upper) no uptime growth inside or outside range, 1D time in position": {
-			currentTick: 1,
-			positionParams: positionParameters{
-				owner:       ownerWithValidPosition,
-				lowerTick:   0,
-				upperTick:   2,
-				liquidity:   DefaultLiquidityAmt,
-				joinTime:    defaultJoinTime,
-				positionId:  DefaultPositionId,
-				collectTime: defaultJoinTime.Add(100),
-			},
+			currentTick:                 1,
+			positionParams:              default0To2PosParam,
 			numPositions:                1,
 			timeInPosition:              oneDay,
 			expectedIncentivesClaimed:   sdk.Coins(nil),
@@ -2116,17 +1791,9 @@ func (s *KeeperTestSuite) TestQueryAndCollectIncentives() {
 		"(lower < curr < upper) uptime growth outside range but not inside, 1D time in position": {
 			currentTick:              1,
 			addedUptimeGrowthOutside: uptimeHelper.hundredTokensMultiDenom,
-			positionParams: positionParameters{
-				owner:       ownerWithValidPosition,
-				lowerTick:   0,
-				upperTick:   2,
-				liquidity:   DefaultLiquidityAmt,
-				joinTime:    defaultJoinTime,
-				positionId:  DefaultPositionId,
-				collectTime: defaultJoinTime.Add(100),
-			},
-			numPositions:   1,
-			timeInPosition: oneDay,
+			positionParams:           default0To2PosParam,
+			numPositions:             1,
+			timeInPosition:           oneDay,
 			// Since there was no growth inside the range, we expect no incentives to be claimed
 			expectedIncentivesClaimed:   sdk.Coins(nil),
 			expectedForfeitedIncentives: sdk.Coins(nil),
@@ -2134,17 +1801,9 @@ func (s *KeeperTestSuite) TestQueryAndCollectIncentives() {
 		"(lower < curr < upper) uptime growth inside range but not outside, 1D time in position": {
 			currentTick:             1,
 			addedUptimeGrowthInside: uptimeHelper.hundredTokensMultiDenom,
-			positionParams: positionParameters{
-				owner:       ownerWithValidPosition,
-				lowerTick:   0,
-				upperTick:   2,
-				liquidity:   DefaultLiquidityAmt,
-				joinTime:    defaultJoinTime,
-				positionId:  DefaultPositionId,
-				collectTime: defaultJoinTime.Add(100),
-			},
-			numPositions:   1,
-			timeInPosition: oneDay,
+			positionParams:          default0To2PosParam,
+			numPositions:            1,
+			timeInPosition:          oneDay,
 			// Since there is no other existing liquidity, we expect all of the growth inside to accrue to be claimed for the
 			// uptimes the position qualifies for.
 			expectedIncentivesClaimed:   expectedIncentivesFromUptimeGrowth(uptimeHelper.hundredTokensMultiDenom, DefaultLiquidityAmt, oneDay, defaultMultiplier),
@@ -2154,33 +1813,17 @@ func (s *KeeperTestSuite) TestQueryAndCollectIncentives() {
 			currentTick:              1,
 			addedUptimeGrowthInside:  uptimeHelper.hundredTokensMultiDenom,
 			addedUptimeGrowthOutside: uptimeHelper.hundredTokensMultiDenom,
-			positionParams: positionParameters{
-				owner:       ownerWithValidPosition,
-				lowerTick:   0,
-				upperTick:   2,
-				liquidity:   DefaultLiquidityAmt,
-				joinTime:    defaultJoinTime,
-				positionId:  DefaultPositionId,
-				collectTime: defaultJoinTime.Add(100),
-			},
-			numPositions:   1,
-			timeInPosition: oneDay,
+			positionParams:           default0To2PosParam,
+			numPositions:             1,
+			timeInPosition:           oneDay,
 			// Since there is no other existing liquidity, we expect all of the growth inside to accrue to be claimed for the
 			// uptimes the position qualifies for. At the same time, growth outside does not affect the current position's incentive rewards.
 			expectedIncentivesClaimed:   expectedIncentivesFromUptimeGrowth(uptimeHelper.hundredTokensMultiDenom, DefaultLiquidityAmt, oneDay, defaultMultiplier),
 			expectedForfeitedIncentives: expectedIncentivesFromUptimeGrowth(uptimeHelper.hundredTokensMultiDenom, DefaultLiquidityAmt, oneWeek, defaultMultiplier).Sub(expectedIncentivesFromUptimeGrowth(uptimeHelper.hundredTokensMultiDenom, DefaultLiquidityAmt, oneDay, defaultMultiplier)),
 		},
 		"(lower < curr < upper) no uptime growth inside or outside range, 1W time in position": {
-			currentTick: 1,
-			positionParams: positionParameters{
-				owner:       ownerWithValidPosition,
-				lowerTick:   0,
-				upperTick:   2,
-				liquidity:   DefaultLiquidityAmt,
-				joinTime:    defaultJoinTime,
-				positionId:  DefaultPositionId,
-				collectTime: defaultJoinTime.Add(100),
-			},
+			currentTick:                 1,
+			positionParams:              default0To2PosParam,
 			numPositions:                1,
 			timeInPosition:              oneWeek,
 			expectedIncentivesClaimed:   sdk.Coins(nil),
@@ -2189,17 +1832,9 @@ func (s *KeeperTestSuite) TestQueryAndCollectIncentives() {
 		"(lower < curr < upper) uptime growth outside range but not inside, 1W time in position": {
 			currentTick:              1,
 			addedUptimeGrowthOutside: uptimeHelper.hundredTokensMultiDenom,
-			positionParams: positionParameters{
-				owner:       ownerWithValidPosition,
-				lowerTick:   0,
-				upperTick:   2,
-				liquidity:   DefaultLiquidityAmt,
-				joinTime:    defaultJoinTime,
-				positionId:  DefaultPositionId,
-				collectTime: defaultJoinTime.Add(100),
-			},
-			numPositions:   1,
-			timeInPosition: oneWeek,
+			positionParams:           default0To2PosParam,
+			numPositions:             1,
+			timeInPosition:           oneWeek,
 			// Since there was no growth inside the range, we expect no incentives to be claimed
 			expectedIncentivesClaimed:   sdk.Coins(nil),
 			expectedForfeitedIncentives: sdk.Coins(nil),
@@ -2207,17 +1842,9 @@ func (s *KeeperTestSuite) TestQueryAndCollectIncentives() {
 		"(lower < curr < upper) uptime growth inside range but not outside, 1W time in position": {
 			currentTick:             1,
 			addedUptimeGrowthInside: uptimeHelper.hundredTokensMultiDenom,
-			positionParams: positionParameters{
-				owner:       ownerWithValidPosition,
-				lowerTick:   0,
-				upperTick:   2,
-				liquidity:   DefaultLiquidityAmt,
-				joinTime:    defaultJoinTime,
-				positionId:  DefaultPositionId,
-				collectTime: defaultJoinTime.Add(100),
-			},
-			numPositions:   1,
-			timeInPosition: oneWeek,
+			positionParams:          default0To2PosParam,
+			numPositions:            1,
+			timeInPosition:          oneWeek,
 			// Since there is no other existing liquidity, we expect all of the growth inside to accrue to be claimed for the
 			// uptimes the position qualifies for.
 			expectedIncentivesClaimed:   expectedIncentivesFromUptimeGrowth(uptimeHelper.hundredTokensMultiDenom, DefaultLiquidityAmt, oneWeek, defaultMultiplier),
@@ -2227,85 +1854,45 @@ func (s *KeeperTestSuite) TestQueryAndCollectIncentives() {
 			currentTick:              1,
 			addedUptimeGrowthInside:  uptimeHelper.hundredTokensMultiDenom,
 			addedUptimeGrowthOutside: uptimeHelper.hundredTokensMultiDenom,
-			positionParams: positionParameters{
-				owner:       ownerWithValidPosition,
-				lowerTick:   0,
-				upperTick:   2,
-				liquidity:   DefaultLiquidityAmt,
-				joinTime:    defaultJoinTime,
-				positionId:  DefaultPositionId,
-				collectTime: defaultJoinTime.Add(100),
-			},
-			numPositions:   1,
-			timeInPosition: oneWeek,
+			positionParams:           default0To2PosParam,
+			numPositions:             1,
+			timeInPosition:           oneWeek,
 			// Since there is no other existing liquidity, we expect all of the growth inside to accrue to be claimed for the
 			// uptimes the position qualifies for. At the same time, growth outside does not affect the current position's incentive rewards.
 			expectedIncentivesClaimed:   expectedIncentivesFromUptimeGrowth(uptimeHelper.hundredTokensMultiDenom, DefaultLiquidityAmt, oneWeek, defaultMultiplier),
 			expectedForfeitedIncentives: sdk.Coins(nil),
 		},
 		"(lower < curr < upper) no uptime growth inside or outside range, no time in position": {
-			currentTick: 1,
-			positionParams: positionParameters{
-				owner:       ownerWithValidPosition,
-				lowerTick:   0,
-				upperTick:   2,
-				liquidity:   DefaultLiquidityAmt,
-				joinTime:    defaultJoinTime,
-				positionId:  DefaultPositionId,
-				collectTime: defaultJoinTime.Add(100),
-			},
+			currentTick:                 1,
+			positionParams:              default0To2PosParam,
 			numPositions:                1,
 			timeInPosition:              0,
 			expectedIncentivesClaimed:   sdk.Coins(nil),
 			expectedForfeitedIncentives: sdk.Coins(nil),
 		},
 		"(lower < curr < upper) uptime growth outside range but not inside, no time in position": {
-			currentTick:              1,
-			addedUptimeGrowthOutside: uptimeHelper.hundredTokensMultiDenom,
-			positionParams: positionParameters{
-				owner:       ownerWithValidPosition,
-				lowerTick:   0,
-				upperTick:   2,
-				liquidity:   DefaultLiquidityAmt,
-				joinTime:    defaultJoinTime,
-				positionId:  DefaultPositionId,
-				collectTime: defaultJoinTime.Add(100),
-			},
+			currentTick:                 1,
+			addedUptimeGrowthOutside:    uptimeHelper.hundredTokensMultiDenom,
+			positionParams:              default0To2PosParam,
 			numPositions:                1,
 			timeInPosition:              0,
 			expectedIncentivesClaimed:   sdk.Coins(nil),
 			expectedForfeitedIncentives: sdk.Coins(nil),
 		},
 		"(lower < curr < upper) uptime growth inside range but not outside, no time in position": {
-			currentTick:             1,
-			addedUptimeGrowthInside: uptimeHelper.hundredTokensMultiDenom,
-			positionParams: positionParameters{
-				owner:       ownerWithValidPosition,
-				lowerTick:   0,
-				upperTick:   2,
-				liquidity:   DefaultLiquidityAmt,
-				joinTime:    defaultJoinTime,
-				positionId:  DefaultPositionId,
-				collectTime: defaultJoinTime.Add(100),
-			},
+			currentTick:                 1,
+			addedUptimeGrowthInside:     uptimeHelper.hundredTokensMultiDenom,
+			positionParams:              default0To2PosParam,
 			numPositions:                1,
 			timeInPosition:              0,
 			expectedIncentivesClaimed:   sdk.Coins(nil),
 			expectedForfeitedIncentives: expectedIncentivesFromUptimeGrowth(uptimeHelper.hundredTokensMultiDenom, DefaultLiquidityAmt, oneWeek, defaultMultiplier),
 		},
 		"(lower < curr < upper) uptime growth both inside and outside range, no time in position": {
-			currentTick:              1,
-			addedUptimeGrowthInside:  uptimeHelper.hundredTokensMultiDenom,
-			addedUptimeGrowthOutside: uptimeHelper.hundredTokensMultiDenom,
-			positionParams: positionParameters{
-				owner:       ownerWithValidPosition,
-				lowerTick:   0,
-				upperTick:   2,
-				liquidity:   DefaultLiquidityAmt,
-				joinTime:    defaultJoinTime,
-				positionId:  DefaultPositionId,
-				collectTime: defaultJoinTime.Add(100),
-			},
+			currentTick:                 1,
+			addedUptimeGrowthInside:     uptimeHelper.hundredTokensMultiDenom,
+			addedUptimeGrowthOutside:    uptimeHelper.hundredTokensMultiDenom,
+			positionParams:              default0To2PosParam,
 			numPositions:                1,
 			timeInPosition:              0,
 			expectedIncentivesClaimed:   sdk.Coins(nil),
@@ -2315,16 +1902,8 @@ func (s *KeeperTestSuite) TestQueryAndCollectIncentives() {
 		// ---Cases for currentTick < lowerTick < upperTick---
 
 		"(curr < lower < upper) no uptime growth inside or outside range, 1D time in position": {
-			currentTick: 0,
-			positionParams: positionParameters{
-				owner:       ownerWithValidPosition,
-				lowerTick:   1,
-				upperTick:   2,
-				liquidity:   DefaultLiquidityAmt,
-				joinTime:    defaultJoinTime,
-				positionId:  DefaultPositionId,
-				collectTime: defaultJoinTime.Add(100),
-			},
+			currentTick:                 0,
+			positionParams:              default1To2PosParam,
 			numPositions:                1,
 			timeInPosition:              oneDay,
 			expectedIncentivesClaimed:   sdk.Coins(nil),
@@ -2333,17 +1912,9 @@ func (s *KeeperTestSuite) TestQueryAndCollectIncentives() {
 		"(curr < lower < upper) uptime growth outside range but not inside, 1D time in position": {
 			currentTick:              0,
 			addedUptimeGrowthOutside: uptimeHelper.hundredTokensMultiDenom,
-			positionParams: positionParameters{
-				owner:       ownerWithValidPosition,
-				lowerTick:   1,
-				upperTick:   2,
-				liquidity:   DefaultLiquidityAmt,
-				joinTime:    defaultJoinTime,
-				positionId:  DefaultPositionId,
-				collectTime: defaultJoinTime.Add(100),
-			},
-			numPositions:   1,
-			timeInPosition: oneDay,
+			positionParams:           default1To2PosParam,
+			numPositions:             1,
+			timeInPosition:           oneDay,
 			// Since there was no growth inside the range, we expect no incentives to be claimed
 			expectedIncentivesClaimed:   sdk.Coins(nil),
 			expectedForfeitedIncentives: sdk.Coins(nil),
@@ -2351,17 +1922,9 @@ func (s *KeeperTestSuite) TestQueryAndCollectIncentives() {
 		"(curr < lower < upper) uptime growth inside range but not outside, 1D time in position": {
 			currentTick:             0,
 			addedUptimeGrowthInside: uptimeHelper.hundredTokensMultiDenom,
-			positionParams: positionParameters{
-				owner:       ownerWithValidPosition,
-				lowerTick:   1,
-				upperTick:   2,
-				liquidity:   DefaultLiquidityAmt,
-				joinTime:    defaultJoinTime,
-				positionId:  DefaultPositionId,
-				collectTime: defaultJoinTime.Add(100),
-			},
-			numPositions:   1,
-			timeInPosition: oneDay,
+			positionParams:          default1To2PosParam,
+			numPositions:            1,
+			timeInPosition:          oneDay,
 			// Since there is no other existing liquidity, we expect all of the growth inside to accrue to be claimed for the
 			// uptimes the position qualifies for.
 			expectedIncentivesClaimed:   expectedIncentivesFromUptimeGrowth(uptimeHelper.hundredTokensMultiDenom, DefaultLiquidityAmt, oneDay, defaultMultiplier),
@@ -2371,33 +1934,17 @@ func (s *KeeperTestSuite) TestQueryAndCollectIncentives() {
 			currentTick:              0,
 			addedUptimeGrowthInside:  uptimeHelper.hundredTokensMultiDenom,
 			addedUptimeGrowthOutside: uptimeHelper.hundredTokensMultiDenom,
-			positionParams: positionParameters{
-				owner:       ownerWithValidPosition,
-				lowerTick:   1,
-				upperTick:   2,
-				liquidity:   DefaultLiquidityAmt,
-				joinTime:    defaultJoinTime,
-				positionId:  DefaultPositionId,
-				collectTime: defaultJoinTime.Add(100),
-			},
-			numPositions:   1,
-			timeInPosition: oneDay,
+			positionParams:           default1To2PosParam,
+			numPositions:             1,
+			timeInPosition:           oneDay,
 			// Since there is no other existing liquidity, we expect all of the growth inside to accrue to be claimed for the
 			// uptimes the position qualifies for. At the same time, growth outside does not affect the current position's incentive rewards.
 			expectedIncentivesClaimed:   expectedIncentivesFromUptimeGrowth(uptimeHelper.hundredTokensMultiDenom, DefaultLiquidityAmt, oneDay, defaultMultiplier),
 			expectedForfeitedIncentives: expectedIncentivesFromUptimeGrowth(uptimeHelper.hundredTokensMultiDenom, DefaultLiquidityAmt, oneWeek, defaultMultiplier).Sub(expectedIncentivesFromUptimeGrowth(uptimeHelper.hundredTokensMultiDenom, DefaultLiquidityAmt, oneDay, defaultMultiplier)),
 		},
 		"(curr < lower < upper) no uptime growth inside or outside range, 1W time in position": {
-			currentTick: 0,
-			positionParams: positionParameters{
-				owner:       ownerWithValidPosition,
-				lowerTick:   1,
-				upperTick:   2,
-				liquidity:   DefaultLiquidityAmt,
-				joinTime:    defaultJoinTime,
-				positionId:  DefaultPositionId,
-				collectTime: defaultJoinTime.Add(100),
-			},
+			currentTick:                 0,
+			positionParams:              default1To2PosParam,
 			numPositions:                1,
 			timeInPosition:              oneWeek,
 			expectedIncentivesClaimed:   sdk.Coins(nil),
@@ -2406,17 +1953,9 @@ func (s *KeeperTestSuite) TestQueryAndCollectIncentives() {
 		"(curr < lower < upper) uptime growth outside range but not inside, 1W time in position": {
 			currentTick:              0,
 			addedUptimeGrowthOutside: uptimeHelper.hundredTokensMultiDenom,
-			positionParams: positionParameters{
-				owner:       ownerWithValidPosition,
-				lowerTick:   1,
-				upperTick:   2,
-				liquidity:   DefaultLiquidityAmt,
-				joinTime:    defaultJoinTime,
-				positionId:  DefaultPositionId,
-				collectTime: defaultJoinTime.Add(100),
-			},
-			numPositions:   1,
-			timeInPosition: oneWeek,
+			positionParams:           default1To2PosParam,
+			numPositions:             1,
+			timeInPosition:           oneWeek,
 			// Since there was no growth inside the range, we expect no incentives to be claimed
 			expectedIncentivesClaimed:   sdk.Coins(nil),
 			expectedForfeitedIncentives: sdk.Coins(nil),
@@ -2424,17 +1963,9 @@ func (s *KeeperTestSuite) TestQueryAndCollectIncentives() {
 		"(curr < lower < upper) uptime growth inside range but not outside, 1W time in position": {
 			currentTick:             0,
 			addedUptimeGrowthInside: uptimeHelper.hundredTokensMultiDenom,
-			positionParams: positionParameters{
-				owner:       ownerWithValidPosition,
-				lowerTick:   1,
-				upperTick:   2,
-				liquidity:   DefaultLiquidityAmt,
-				joinTime:    defaultJoinTime,
-				positionId:  DefaultPositionId,
-				collectTime: defaultJoinTime.Add(100),
-			},
-			numPositions:   1,
-			timeInPosition: oneWeek,
+			positionParams:          default1To2PosParam,
+			numPositions:            1,
+			timeInPosition:          oneWeek,
 			// Since there is no other existing liquidity, we expect all of the growth inside to accrue to be claimed for the
 			// uptimes the position qualifies for.
 			expectedIncentivesClaimed:   expectedIncentivesFromUptimeGrowth(uptimeHelper.hundredTokensMultiDenom, DefaultLiquidityAmt, oneWeek, defaultMultiplier),
@@ -2444,85 +1975,45 @@ func (s *KeeperTestSuite) TestQueryAndCollectIncentives() {
 			currentTick:              0,
 			addedUptimeGrowthInside:  uptimeHelper.hundredTokensMultiDenom,
 			addedUptimeGrowthOutside: uptimeHelper.hundredTokensMultiDenom,
-			positionParams: positionParameters{
-				owner:       ownerWithValidPosition,
-				lowerTick:   1,
-				upperTick:   2,
-				liquidity:   DefaultLiquidityAmt,
-				joinTime:    defaultJoinTime,
-				positionId:  DefaultPositionId,
-				collectTime: defaultJoinTime.Add(100),
-			},
-			numPositions:   1,
-			timeInPosition: oneWeek,
+			positionParams:           default1To2PosParam,
+			numPositions:             1,
+			timeInPosition:           oneWeek,
 			// Since there is no other existing liquidity, we expect all of the growth inside to accrue to be claimed for the
 			// uptimes the position qualifies for. At the same time, growth outside does not affect the current position's incentive rewards.
 			expectedIncentivesClaimed:   expectedIncentivesFromUptimeGrowth(uptimeHelper.hundredTokensMultiDenom, DefaultLiquidityAmt, oneWeek, defaultMultiplier),
 			expectedForfeitedIncentives: sdk.Coins(nil),
 		},
 		"(curr < lower < upper) no uptime growth inside or outside range, no time in position": {
-			currentTick: 0,
-			positionParams: positionParameters{
-				owner:       ownerWithValidPosition,
-				lowerTick:   1,
-				upperTick:   2,
-				liquidity:   DefaultLiquidityAmt,
-				joinTime:    defaultJoinTime,
-				positionId:  DefaultPositionId,
-				collectTime: defaultJoinTime.Add(100),
-			},
+			currentTick:                 0,
+			positionParams:              default1To2PosParam,
 			numPositions:                1,
 			timeInPosition:              0,
 			expectedIncentivesClaimed:   sdk.Coins(nil),
 			expectedForfeitedIncentives: sdk.Coins(nil),
 		},
 		"(curr < lower < upper) uptime growth outside range but not inside, no time in position": {
-			currentTick:              0,
-			addedUptimeGrowthOutside: uptimeHelper.hundredTokensMultiDenom,
-			positionParams: positionParameters{
-				owner:       ownerWithValidPosition,
-				lowerTick:   1,
-				upperTick:   2,
-				liquidity:   DefaultLiquidityAmt,
-				joinTime:    defaultJoinTime,
-				positionId:  DefaultPositionId,
-				collectTime: defaultJoinTime.Add(100),
-			},
+			currentTick:                 0,
+			addedUptimeGrowthOutside:    uptimeHelper.hundredTokensMultiDenom,
+			positionParams:              default1To2PosParam,
 			numPositions:                1,
 			timeInPosition:              0,
 			expectedIncentivesClaimed:   sdk.Coins(nil),
 			expectedForfeitedIncentives: sdk.Coins(nil),
 		},
 		"(curr < lower < upper) uptime growth inside range but not outside, no time in position": {
-			currentTick:             0,
-			addedUptimeGrowthInside: uptimeHelper.hundredTokensMultiDenom,
-			positionParams: positionParameters{
-				owner:       ownerWithValidPosition,
-				lowerTick:   1,
-				upperTick:   2,
-				liquidity:   DefaultLiquidityAmt,
-				joinTime:    defaultJoinTime,
-				positionId:  DefaultPositionId,
-				collectTime: defaultJoinTime.Add(100),
-			},
+			currentTick:                 0,
+			addedUptimeGrowthInside:     uptimeHelper.hundredTokensMultiDenom,
+			positionParams:              default1To2PosParam,
 			numPositions:                1,
 			timeInPosition:              0,
 			expectedIncentivesClaimed:   sdk.Coins(nil),
 			expectedForfeitedIncentives: expectedIncentivesFromUptimeGrowth(uptimeHelper.hundredTokensMultiDenom, DefaultLiquidityAmt, oneWeek, defaultMultiplier),
 		},
 		"(curr < lower < upper) uptime growth both inside and outside range, no time in position": {
-			currentTick:              0,
-			addedUptimeGrowthInside:  uptimeHelper.hundredTokensMultiDenom,
-			addedUptimeGrowthOutside: uptimeHelper.hundredTokensMultiDenom,
-			positionParams: positionParameters{
-				owner:       ownerWithValidPosition,
-				lowerTick:   1,
-				upperTick:   2,
-				liquidity:   DefaultLiquidityAmt,
-				joinTime:    defaultJoinTime,
-				positionId:  DefaultPositionId,
-				collectTime: defaultJoinTime.Add(100),
-			},
+			currentTick:                 0,
+			addedUptimeGrowthInside:     uptimeHelper.hundredTokensMultiDenom,
+			addedUptimeGrowthOutside:    uptimeHelper.hundredTokensMultiDenom,
+			positionParams:              default1To2PosParam,
 			numPositions:                1,
 			timeInPosition:              0,
 			expectedIncentivesClaimed:   sdk.Coins(nil),
@@ -2532,16 +2023,8 @@ func (s *KeeperTestSuite) TestQueryAndCollectIncentives() {
 		// ---Cases for lowerTick < upperTick < currentTick---
 
 		"(lower < upper < curr) no uptime growth inside or outside range, 1D time in position": {
-			currentTick: 3,
-			positionParams: positionParameters{
-				owner:       ownerWithValidPosition,
-				lowerTick:   1,
-				upperTick:   2,
-				liquidity:   DefaultLiquidityAmt,
-				joinTime:    defaultJoinTime,
-				positionId:  DefaultPositionId,
-				collectTime: defaultJoinTime.Add(100),
-			},
+			currentTick:                 3,
+			positionParams:              default1To2PosParam,
 			numPositions:                1,
 			timeInPosition:              oneDay,
 			expectedIncentivesClaimed:   sdk.Coins(nil),
@@ -2550,17 +2033,9 @@ func (s *KeeperTestSuite) TestQueryAndCollectIncentives() {
 		"(lower < upper < curr) uptime growth outside range but not inside, 1D time in position": {
 			currentTick:              3,
 			addedUptimeGrowthOutside: uptimeHelper.hundredTokensMultiDenom,
-			positionParams: positionParameters{
-				owner:       ownerWithValidPosition,
-				lowerTick:   1,
-				upperTick:   2,
-				liquidity:   DefaultLiquidityAmt,
-				joinTime:    defaultJoinTime,
-				positionId:  DefaultPositionId,
-				collectTime: defaultJoinTime.Add(100),
-			},
-			numPositions:   1,
-			timeInPosition: oneDay,
+			positionParams:           default1To2PosParam,
+			numPositions:             1,
+			timeInPosition:           oneDay,
 			// Since there was no growth inside the range, we expect no incentives to be claimed
 			expectedIncentivesClaimed:   sdk.Coins(nil),
 			expectedForfeitedIncentives: sdk.Coins(nil),
@@ -2568,17 +2043,9 @@ func (s *KeeperTestSuite) TestQueryAndCollectIncentives() {
 		"(lower < upper < curr) uptime growth inside range but not outside, 1D time in position": {
 			currentTick:             3,
 			addedUptimeGrowthInside: uptimeHelper.hundredTokensMultiDenom,
-			positionParams: positionParameters{
-				owner:       ownerWithValidPosition,
-				lowerTick:   1,
-				upperTick:   2,
-				liquidity:   DefaultLiquidityAmt,
-				joinTime:    defaultJoinTime,
-				positionId:  DefaultPositionId,
-				collectTime: defaultJoinTime.Add(100),
-			},
-			numPositions:   1,
-			timeInPosition: oneDay,
+			positionParams:          default1To2PosParam,
+			numPositions:            1,
+			timeInPosition:          oneDay,
 			// Since there is no other existing liquidity, we expect all of the growth inside to accrue to be claimed for the
 			// uptimes the position qualifies for.
 			expectedIncentivesClaimed:   expectedIncentivesFromUptimeGrowth(uptimeHelper.hundredTokensMultiDenom, DefaultLiquidityAmt, oneDay, defaultMultiplier),
@@ -2588,33 +2055,17 @@ func (s *KeeperTestSuite) TestQueryAndCollectIncentives() {
 			currentTick:              3,
 			addedUptimeGrowthInside:  uptimeHelper.hundredTokensMultiDenom,
 			addedUptimeGrowthOutside: uptimeHelper.hundredTokensMultiDenom,
-			positionParams: positionParameters{
-				owner:       ownerWithValidPosition,
-				lowerTick:   1,
-				upperTick:   2,
-				liquidity:   DefaultLiquidityAmt,
-				joinTime:    defaultJoinTime,
-				positionId:  DefaultPositionId,
-				collectTime: defaultJoinTime.Add(100),
-			},
-			numPositions:   1,
-			timeInPosition: oneDay,
+			positionParams:           default1To2PosParam,
+			numPositions:             1,
+			timeInPosition:           oneDay,
 			// Since there is no other existing liquidity, we expect all of the growth inside to accrue to be claimed for the
 			// uptimes the position qualifies for. At the same time, growth outside does not affect the current position's incentive rewards.
 			expectedIncentivesClaimed:   expectedIncentivesFromUptimeGrowth(uptimeHelper.hundredTokensMultiDenom, DefaultLiquidityAmt, oneDay, defaultMultiplier),
 			expectedForfeitedIncentives: expectedIncentivesFromUptimeGrowth(uptimeHelper.hundredTokensMultiDenom, DefaultLiquidityAmt, oneWeek, defaultMultiplier).Sub(expectedIncentivesFromUptimeGrowth(uptimeHelper.hundredTokensMultiDenom, DefaultLiquidityAmt, oneDay, defaultMultiplier)),
 		},
 		"(lower < upper < curr) no uptime growth inside or outside range, 1W time in position": {
-			currentTick: 3,
-			positionParams: positionParameters{
-				owner:       ownerWithValidPosition,
-				lowerTick:   1,
-				upperTick:   2,
-				liquidity:   DefaultLiquidityAmt,
-				joinTime:    defaultJoinTime,
-				positionId:  DefaultPositionId,
-				collectTime: defaultJoinTime.Add(100),
-			},
+			currentTick:                 3,
+			positionParams:              default1To2PosParam,
 			numPositions:                1,
 			timeInPosition:              oneWeek,
 			expectedIncentivesClaimed:   sdk.Coins(nil),
@@ -2623,17 +2074,9 @@ func (s *KeeperTestSuite) TestQueryAndCollectIncentives() {
 		"(lower < upper < curr) uptime growth outside range but not inside, 1W time in position": {
 			currentTick:              3,
 			addedUptimeGrowthOutside: uptimeHelper.hundredTokensMultiDenom,
-			positionParams: positionParameters{
-				owner:       ownerWithValidPosition,
-				lowerTick:   1,
-				upperTick:   2,
-				liquidity:   DefaultLiquidityAmt,
-				joinTime:    defaultJoinTime,
-				positionId:  DefaultPositionId,
-				collectTime: defaultJoinTime.Add(100),
-			},
-			numPositions:   1,
-			timeInPosition: oneWeek,
+			positionParams:           default1To2PosParam,
+			numPositions:             1,
+			timeInPosition:           oneWeek,
 			// Since there was no growth inside the range, we expect no incentives to be claimed
 			expectedIncentivesClaimed:   sdk.Coins(nil),
 			expectedForfeitedIncentives: sdk.Coins(nil),
@@ -2641,17 +2084,9 @@ func (s *KeeperTestSuite) TestQueryAndCollectIncentives() {
 		"(lower < upper < curr) uptime growth inside range but not outside, 1W time in position": {
 			currentTick:             3,
 			addedUptimeGrowthInside: uptimeHelper.hundredTokensMultiDenom,
-			positionParams: positionParameters{
-				owner:       ownerWithValidPosition,
-				lowerTick:   1,
-				upperTick:   2,
-				liquidity:   DefaultLiquidityAmt,
-				joinTime:    defaultJoinTime,
-				positionId:  DefaultPositionId,
-				collectTime: defaultJoinTime.Add(100),
-			},
-			numPositions:   1,
-			timeInPosition: oneWeek,
+			positionParams:          default1To2PosParam,
+			numPositions:            1,
+			timeInPosition:          oneWeek,
 			// Since there is no other existing liquidity, we expect all of the growth inside to accrue to be claimed for the
 			// uptimes the position qualifies for.
 			expectedIncentivesClaimed:   expectedIncentivesFromUptimeGrowth(uptimeHelper.hundredTokensMultiDenom, DefaultLiquidityAmt, oneWeek, defaultMultiplier),
@@ -2661,85 +2096,45 @@ func (s *KeeperTestSuite) TestQueryAndCollectIncentives() {
 			currentTick:              3,
 			addedUptimeGrowthInside:  uptimeHelper.hundredTokensMultiDenom,
 			addedUptimeGrowthOutside: uptimeHelper.hundredTokensMultiDenom,
-			positionParams: positionParameters{
-				owner:       ownerWithValidPosition,
-				lowerTick:   1,
-				upperTick:   2,
-				liquidity:   DefaultLiquidityAmt,
-				joinTime:    defaultJoinTime,
-				positionId:  DefaultPositionId,
-				collectTime: defaultJoinTime.Add(100),
-			},
-			numPositions:   1,
-			timeInPosition: oneWeek,
+			positionParams:           default1To2PosParam,
+			numPositions:             1,
+			timeInPosition:           oneWeek,
 			// Since there is no other existing liquidity, we expect all of the growth inside to accrue to be claimed for the
 			// uptimes the position qualifies for.
 			expectedIncentivesClaimed:   expectedIncentivesFromUptimeGrowth(uptimeHelper.hundredTokensMultiDenom, DefaultLiquidityAmt, oneWeek, defaultMultiplier),
 			expectedForfeitedIncentives: sdk.Coins(nil),
 		},
 		"(lower < upper < curr) no uptime growth inside or outside range, no time in position": {
-			currentTick: 3,
-			positionParams: positionParameters{
-				owner:       ownerWithValidPosition,
-				lowerTick:   1,
-				upperTick:   2,
-				liquidity:   DefaultLiquidityAmt,
-				joinTime:    defaultJoinTime,
-				positionId:  DefaultPositionId,
-				collectTime: defaultJoinTime.Add(100),
-			},
+			currentTick:                 3,
+			positionParams:              default1To2PosParam,
 			numPositions:                1,
 			timeInPosition:              0,
 			expectedIncentivesClaimed:   sdk.Coins(nil),
 			expectedForfeitedIncentives: sdk.Coins(nil),
 		},
 		"(lower < upper < curr) uptime growth outside range but not inside, no time in position": {
-			currentTick:              3,
-			addedUptimeGrowthOutside: uptimeHelper.hundredTokensMultiDenom,
-			positionParams: positionParameters{
-				owner:       ownerWithValidPosition,
-				lowerTick:   1,
-				upperTick:   2,
-				liquidity:   DefaultLiquidityAmt,
-				joinTime:    defaultJoinTime,
-				positionId:  DefaultPositionId,
-				collectTime: defaultJoinTime.Add(100),
-			},
+			currentTick:                 3,
+			addedUptimeGrowthOutside:    uptimeHelper.hundredTokensMultiDenom,
+			positionParams:              default1To2PosParam,
 			numPositions:                1,
 			timeInPosition:              0,
 			expectedIncentivesClaimed:   sdk.Coins(nil),
 			expectedForfeitedIncentives: sdk.Coins(nil),
 		},
 		"(lower < upper < curr) uptime growth inside range but not outside, no time in position": {
-			currentTick:             3,
-			addedUptimeGrowthInside: uptimeHelper.hundredTokensMultiDenom,
-			positionParams: positionParameters{
-				owner:       ownerWithValidPosition,
-				lowerTick:   1,
-				upperTick:   2,
-				liquidity:   DefaultLiquidityAmt,
-				joinTime:    defaultJoinTime,
-				positionId:  DefaultPositionId,
-				collectTime: defaultJoinTime.Add(100),
-			},
+			currentTick:                 3,
+			addedUptimeGrowthInside:     uptimeHelper.hundredTokensMultiDenom,
+			positionParams:              default1To2PosParam,
 			numPositions:                1,
 			timeInPosition:              0,
 			expectedIncentivesClaimed:   sdk.Coins(nil),
 			expectedForfeitedIncentives: expectedIncentivesFromUptimeGrowth(uptimeHelper.hundredTokensMultiDenom, DefaultLiquidityAmt, oneWeek, defaultMultiplier),
 		},
 		"(lower < upper < curr) uptime growth both inside and outside range, no time in position": {
-			currentTick:              3,
-			addedUptimeGrowthInside:  uptimeHelper.hundredTokensMultiDenom,
-			addedUptimeGrowthOutside: uptimeHelper.hundredTokensMultiDenom,
-			positionParams: positionParameters{
-				owner:       ownerWithValidPosition,
-				lowerTick:   1,
-				upperTick:   2,
-				liquidity:   DefaultLiquidityAmt,
-				joinTime:    defaultJoinTime,
-				positionId:  DefaultPositionId,
-				collectTime: defaultJoinTime.Add(100),
-			},
+			currentTick:                 3,
+			addedUptimeGrowthInside:     uptimeHelper.hundredTokensMultiDenom,
+			addedUptimeGrowthOutside:    uptimeHelper.hundredTokensMultiDenom,
+			positionParams:              default1To2PosParam,
 			numPositions:                1,
 			timeInPosition:              0,
 			expectedIncentivesClaimed:   sdk.Coins(nil),
@@ -2752,17 +2147,9 @@ func (s *KeeperTestSuite) TestQueryAndCollectIncentives() {
 			currentTick:              0,
 			addedUptimeGrowthInside:  uptimeHelper.hundredTokensMultiDenom,
 			addedUptimeGrowthOutside: uptimeHelper.hundredTokensMultiDenom,
-			positionParams: positionParameters{
-				owner:       ownerWithValidPosition,
-				lowerTick:   0,
-				upperTick:   2,
-				liquidity:   DefaultLiquidityAmt,
-				joinTime:    defaultJoinTime,
-				positionId:  DefaultPositionId,
-				collectTime: defaultJoinTime.Add(100),
-			},
-			numPositions:   1,
-			timeInPosition: oneDay,
+			positionParams:           default0To2PosParam,
+			numPositions:             1,
+			timeInPosition:           oneDay,
 			// We expect this case to behave like (lower < curr < upper)
 			expectedIncentivesClaimed:   expectedIncentivesFromUptimeGrowth(uptimeHelper.hundredTokensMultiDenom, DefaultLiquidityAmt, oneDay, defaultMultiplier),
 			expectedForfeitedIncentives: expectedIncentivesFromUptimeGrowth(uptimeHelper.hundredTokensMultiDenom, DefaultLiquidityAmt, oneWeek, defaultMultiplier).Sub(expectedIncentivesFromUptimeGrowth(uptimeHelper.hundredTokensMultiDenom, DefaultLiquidityAmt, oneDay, defaultMultiplier)),
@@ -2771,17 +2158,9 @@ func (s *KeeperTestSuite) TestQueryAndCollectIncentives() {
 			currentTick:              2,
 			addedUptimeGrowthInside:  uptimeHelper.hundredTokensMultiDenom,
 			addedUptimeGrowthOutside: uptimeHelper.hundredTokensMultiDenom,
-			positionParams: positionParameters{
-				owner:       ownerWithValidPosition,
-				lowerTick:   1,
-				upperTick:   2,
-				liquidity:   DefaultLiquidityAmt,
-				joinTime:    defaultJoinTime,
-				positionId:  DefaultPositionId,
-				collectTime: defaultJoinTime.Add(100),
-			},
-			numPositions:   1,
-			timeInPosition: oneDay,
+			positionParams:           default1To2PosParam,
+			numPositions:             1,
+			timeInPosition:           oneDay,
 			// We expect this case to behave like (lower < upper < curr)
 			expectedIncentivesClaimed:   expectedIncentivesFromUptimeGrowth(uptimeHelper.hundredTokensMultiDenom, DefaultLiquidityAmt, oneDay, defaultMultiplier),
 			expectedForfeitedIncentives: expectedIncentivesFromUptimeGrowth(uptimeHelper.hundredTokensMultiDenom, DefaultLiquidityAmt, oneWeek, defaultMultiplier).Sub(expectedIncentivesFromUptimeGrowth(uptimeHelper.hundredTokensMultiDenom, DefaultLiquidityAmt, oneDay, defaultMultiplier)),
@@ -2797,17 +2176,9 @@ func (s *KeeperTestSuite) TestQueryAndCollectIncentives() {
 			},
 			addedUptimeGrowthInside:  uptimeHelper.hundredTokensMultiDenom,
 			addedUptimeGrowthOutside: uptimeHelper.hundredTokensMultiDenom,
-			positionParams: positionParameters{
-				owner:       ownerWithValidPosition,
-				lowerTick:   0,
-				upperTick:   2,
-				liquidity:   DefaultLiquidityAmt,
-				joinTime:    defaultJoinTime,
-				positionId:  DefaultPositionId,
-				collectTime: defaultJoinTime.Add(100),
-			},
-			numPositions:   1,
-			timeInPosition: oneDay,
+			positionParams:           default0To2PosParam,
+			numPositions:             1,
+			timeInPosition:           oneDay,
 			// Since there is no other existing liquidity, we expect all of the growth inside to accrue to be claimed for the
 			// uptimes the position qualifies for.
 			expectedIncentivesClaimed:   expectedIncentivesFromUptimeGrowth(uptimeHelper.hundredTokensMultiDenom, DefaultLiquidityAmt, oneDay, defaultMultiplier),
@@ -2824,17 +2195,9 @@ func (s *KeeperTestSuite) TestQueryAndCollectIncentives() {
 			},
 			addedUptimeGrowthInside:  uptimeHelper.hundredTokensMultiDenom,
 			addedUptimeGrowthOutside: uptimeHelper.hundredTokensMultiDenom,
-			positionParams: positionParameters{
-				owner:       ownerWithValidPosition,
-				lowerTick:   0,
-				upperTick:   2,
-				liquidity:   DefaultLiquidityAmt,
-				joinTime:    defaultJoinTime,
-				positionId:  DefaultPositionId,
-				collectTime: defaultJoinTime.Add(100),
-			},
-			numPositions:   3,
-			timeInPosition: oneDay,
+			positionParams:           default0To2PosParam,
+			numPositions:             3,
+			timeInPosition:           oneDay,
 			// Since we introduced positionIDs, despite these position having the same range and pool, only
 			// the position ID being claimed will be considered for the claim.
 			expectedIncentivesClaimed:   expectedIncentivesFromUptimeGrowth(uptimeHelper.hundredTokensMultiDenom, DefaultLiquidityAmt, oneDay, defaultMultiplier),
@@ -2906,12 +2269,6 @@ func (s *KeeperTestSuite) TestQueryAndCollectIncentives() {
 			incentivesBalanceBeforeCollect := s.App.BankKeeper.GetAllBalances(ctx, validPool.GetIncentivesAddress())
 			ownerBalancerBeforeCollect := s.App.BankKeeper.GetAllBalances(ctx, ownerWithValidPosition)
 
-			// Set up invalid pool ID for error-catching case(s)
-			sutPoolId := validPoolId
-			if tc.isInvalidPoolIdGiven {
-				sutPoolId = sutPoolId + 1 //nolint:staticcheck,ineffassign
-			}
-
 			// System under test
 			incentivesClaimedQuery, incentivesForfeitedQuery, err := clKeeper.GetClaimableIncentives(ctx, DefaultPositionId)
 
@@ -2975,7 +2332,7 @@ func (s *KeeperTestSuite) TestCreateIncentive() {
 		senderBalance      sdk.Coins
 		recordToSet        types.IncentiveRecord
 		existingRecords    []types.IncentiveRecord
-		minimumGasConsumed uint64
+		minimumGasConsumed uint64 // default 0
 		authorizedUptimes  []time.Duration
 
 		expectedError error
@@ -2990,9 +2347,8 @@ func (s *KeeperTestSuite) TestCreateIncentive() {
 					incentiveRecordOne.IncentiveRecordBody.RemainingAmount.Ceil().RoundInt(),
 				),
 			),
-			recordToSet:        incentiveRecordOne,
-			minimumGasConsumed: uint64(0),
-			authorizedUptimes:  types.SupportedUptimes,
+			recordToSet:       incentiveRecordOne,
+			authorizedUptimes: types.SupportedUptimes,
 		},
 		"record with different denom, emission rate, and min uptime": {
 			poolId: defaultPoolId,
@@ -3003,9 +2359,8 @@ func (s *KeeperTestSuite) TestCreateIncentive() {
 					incentiveRecordTwo.IncentiveRecordBody.RemainingAmount.Ceil().RoundInt(),
 				),
 			),
-			recordToSet:        incentiveRecordTwo,
-			minimumGasConsumed: uint64(0),
-			authorizedUptimes:  types.SupportedUptimes,
+			recordToSet:       incentiveRecordTwo,
+			authorizedUptimes: types.SupportedUptimes,
 		},
 		"record with different start time": {
 			poolId: defaultPoolId,
@@ -3016,9 +2371,8 @@ func (s *KeeperTestSuite) TestCreateIncentive() {
 					incentiveRecordOne.IncentiveRecordBody.RemainingAmount.Ceil().RoundInt(),
 				),
 			),
-			recordToSet:        withStartTime(incentiveRecordOne, defaultStartTime.Add(time.Hour)),
-			minimumGasConsumed: uint64(0),
-			authorizedUptimes:  types.SupportedUptimes,
+			recordToSet:       withStartTime(incentiveRecordOne, defaultStartTime.Add(time.Hour)),
+			authorizedUptimes: types.SupportedUptimes,
 		},
 		"record with different incentive amount": {
 			poolId: defaultPoolId,
@@ -3029,9 +2383,8 @@ func (s *KeeperTestSuite) TestCreateIncentive() {
 					sdk.NewInt(8),
 				),
 			),
-			recordToSet:        withAmount(incentiveRecordOne, sdk.NewDec(8)),
-			minimumGasConsumed: uint64(0),
-			authorizedUptimes:  types.SupportedUptimes,
+			recordToSet:       withAmount(incentiveRecordOne, sdk.NewDec(8)),
+			authorizedUptimes: types.SupportedUptimes,
 		},
 		"existing incentive records on different uptime accumulators": {
 			poolId: defaultPoolId,
@@ -3080,8 +2433,7 @@ func (s *KeeperTestSuite) TestCreateIncentive() {
 					incentiveRecordOne.IncentiveRecordBody.RemainingAmount.Ceil().RoundInt(),
 				),
 			),
-			recordToSet:        incentiveRecordOne,
-			minimumGasConsumed: uint64(0),
+			recordToSet: incentiveRecordOne,
 		},
 
 		// Error catching
@@ -3796,10 +3148,14 @@ func (s *KeeperTestSuite) TestPrepareBalancerPoolAsFullRange() {
 	}
 	defaultConcentratedAssets := sdk.NewCoins(sdk.NewCoin("foo", sdk.NewInt(100)), sdk.NewCoin("bar", sdk.NewInt(100)))
 	defaultBalancerPoolParams := balancer.PoolParams{SwapFee: sdk.NewDec(0), ExitFee: sdk.NewDec(0)}
-	tests := map[string]struct {
+
+	type testcase struct {
+		// defaults to defaultConcentratedAssets
 		existingConcentratedLiquidity sdk.Coins
-		balancerPoolAssets            []balancer.PoolAsset
-		portionOfSharesBonded         sdk.Dec
+		// defaults to defaultBalancerAssets
+		balancerPoolAssets []balancer.PoolAsset
+		// defaults sdk.OneDec()
+		portionOfSharesBonded sdk.Dec
 
 		noCanonicalBalancerPool      bool
 		noBalancerPoolWithID         bool
@@ -3808,45 +3164,53 @@ func (s *KeeperTestSuite) TestPrepareBalancerPoolAsFullRange() {
 		invalidBalancerPoolLiquidity bool
 
 		expectedError error
-	}{
+	}
+	initTestCase := func(tc testcase) testcase {
+		if tc.existingConcentratedLiquidity.Empty() {
+			tc.existingConcentratedLiquidity = defaultConcentratedAssets
+		}
+		if len(tc.balancerPoolAssets) == 0 {
+			tc.balancerPoolAssets = defaultBalancerAssets
+		}
+		if (tc.portionOfSharesBonded == sdk.Dec{}) {
+			tc.portionOfSharesBonded = sdk.NewDec(1)
+		}
+		return tc
+	}
+
+	tests := map[string]testcase{
 		"happy path: balancer and CL pool at same spot price": {
 			// 100 existing shares and 100 shares added from balancer
+			// no other test will show defaults.
 			existingConcentratedLiquidity: defaultConcentratedAssets,
 			balancerPoolAssets:            defaultBalancerAssets,
 			portionOfSharesBonded:         sdk.NewDec(1),
 		},
 		"same spot price, different total share amount": {
 			// 100 existing shares and 200 shares added from balancer
-			existingConcentratedLiquidity: defaultConcentratedAssets,
 			balancerPoolAssets: []balancer.PoolAsset{
 				{Weight: sdk.NewInt(1), Token: sdk.NewCoin("foo", sdk.NewInt(200))},
 				{Weight: sdk.NewInt(1), Token: sdk.NewCoin("bar", sdk.NewInt(200))},
 			},
-			portionOfSharesBonded: sdk.NewDec(1),
 		},
 		"different spot price between balancer and CL pools (excess asset0)": {
 			// 100 existing shares and 100 shares added from balancer. We expect only the even portion of
 			// the Balancer pool to be joined, with the remaining 50foo not qualifying.
-			existingConcentratedLiquidity: defaultConcentratedAssets,
 			balancerPoolAssets: []balancer.PoolAsset{
 				{Weight: sdk.NewInt(1), Token: sdk.NewCoin("foo", sdk.NewInt(150))},
 				{Weight: sdk.NewInt(1), Token: sdk.NewCoin("bar", sdk.NewInt(100))},
 			},
-			portionOfSharesBonded: sdk.NewDec(1),
 		},
 		"different spot price between balancer and CL pools (excess asset1)": {
 			// 100 existing shares and 100 shares added from balancer. We expect only the even portion of
 			// the Balancer pool to be joined, with the remaining 50bar not qualifying.
-			existingConcentratedLiquidity: defaultConcentratedAssets,
 			balancerPoolAssets: []balancer.PoolAsset{
 				{Weight: sdk.NewInt(1), Token: sdk.NewCoin("foo", sdk.NewInt(100))},
 				{Weight: sdk.NewInt(1), Token: sdk.NewCoin("bar", sdk.NewInt(150))},
 			},
-			portionOfSharesBonded: sdk.NewDec(1),
 		},
 		"same spot price, different total share amount, only half bonded": {
 			// 100 existing shares and 200 shares added from balancer
-			existingConcentratedLiquidity: defaultConcentratedAssets,
 			balancerPoolAssets: []balancer.PoolAsset{
 				{Weight: sdk.NewInt(1), Token: sdk.NewCoin("foo", sdk.NewInt(200))},
 				{Weight: sdk.NewInt(1), Token: sdk.NewCoin("bar", sdk.NewInt(200))},
@@ -3856,7 +3220,6 @@ func (s *KeeperTestSuite) TestPrepareBalancerPoolAsFullRange() {
 		"different spot price between balancer and CL pools (excess asset1), only partially bonded": {
 			// 100 existing shares and 100 shares added from balancer. We expect only the even portion of
 			// the Balancer pool to be joined, with the remaining 50bar not qualifying.
-			existingConcentratedLiquidity: defaultConcentratedAssets,
 			balancerPoolAssets: []balancer.PoolAsset{
 				{Weight: sdk.NewInt(1), Token: sdk.NewCoin("foo", sdk.NewInt(100))},
 				{Weight: sdk.NewInt(1), Token: sdk.NewCoin("bar", sdk.NewInt(150))},
@@ -3865,10 +3228,6 @@ func (s *KeeperTestSuite) TestPrepareBalancerPoolAsFullRange() {
 		},
 		"no canonical balancer pool": {
 			// 100 existing shares and 100 shares added from balancer
-			existingConcentratedLiquidity: defaultConcentratedAssets,
-			balancerPoolAssets:            defaultBalancerAssets,
-			portionOfSharesBonded:         sdk.NewDec(1),
-
 			// Note that we expect this to fail quietly, as most CL pools will not have linked Balancer pools
 			noCanonicalBalancerPool: true,
 		},
@@ -3877,77 +3236,46 @@ func (s *KeeperTestSuite) TestPrepareBalancerPoolAsFullRange() {
 
 		"canonical balancer pool ID exists but pool itself is not found": {
 			// 100 existing shares and 100 shares added from balancer
-			existingConcentratedLiquidity: defaultConcentratedAssets,
-			balancerPoolAssets:            defaultBalancerAssets,
-			portionOfSharesBonded:         sdk.NewDec(1),
-			noBalancerPoolWithID:          true,
-
-			expectedError: gammtypes.PoolDoesNotExistError{PoolId: invalidPoolId},
-		},
-		"canonical balancer pool has invalid first denom": {
-			// 100 existing shares and 100 shares added from balancer
-			existingConcentratedLiquidity: defaultConcentratedAssets,
-			balancerPoolAssets: []balancer.PoolAsset{
-				{Weight: sdk.NewInt(1), Token: sdk.NewCoin("invalid", sdk.NewInt(100))},
-				{Weight: sdk.NewInt(1), Token: sdk.NewCoin("bar", sdk.NewInt(100))},
-			},
-			portionOfSharesBonded:        sdk.NewDec(1),
-			invalidBalancerPoolLiquidity: true,
-
-			expectedError: types.ErrInvalidBalancerPoolLiquidityError{ClPoolId: 1, BalancerPoolId: 2, BalancerPoolLiquidity: sdk.NewCoins(sdk.NewCoin("invalid", sdk.NewInt(100)), sdk.NewCoin("bar", sdk.NewInt(100)))},
-		},
-		"canonical balancer pool has invalid second denom": {
-			// 100 existing shares and 100 shares added from balancer
-			existingConcentratedLiquidity: defaultConcentratedAssets,
-			balancerPoolAssets: []balancer.PoolAsset{
-				{Weight: sdk.NewInt(1), Token: sdk.NewCoin("foo", sdk.NewInt(100))},
-				{Weight: sdk.NewInt(1), Token: sdk.NewCoin("invalid", sdk.NewInt(100))},
-			},
-			portionOfSharesBonded:        sdk.NewDec(1),
-			invalidBalancerPoolLiquidity: true,
-
-			expectedError: types.ErrInvalidBalancerPoolLiquidityError{ClPoolId: 1, BalancerPoolId: 2, BalancerPoolLiquidity: sdk.NewCoins(sdk.NewCoin("foo", sdk.NewInt(100)), sdk.NewCoin("invalid", sdk.NewInt(100)))},
-		},
-		"canonical balancer pool has invalid both denoms": {
-			// 100 existing shares and 100 shares added from balancer
-			existingConcentratedLiquidity: defaultConcentratedAssets,
-			balancerPoolAssets: []balancer.PoolAsset{
-				{Weight: sdk.NewInt(1), Token: sdk.NewCoin("invalid1", sdk.NewInt(100))},
-				{Weight: sdk.NewInt(1), Token: sdk.NewCoin("invalid2", sdk.NewInt(100))},
-			},
-			portionOfSharesBonded:        sdk.NewDec(1),
-			invalidBalancerPoolLiquidity: true,
-
-			expectedError: types.ErrInvalidBalancerPoolLiquidityError{ClPoolId: 1, BalancerPoolId: 2, BalancerPoolLiquidity: sdk.NewCoins(sdk.NewCoin("invalid1", sdk.NewInt(100)), sdk.NewCoin("invalid2", sdk.NewInt(100)))},
+			noBalancerPoolWithID: true,
+			expectedError:        gammtypes.PoolDoesNotExistError{PoolId: invalidPoolId},
 		},
 		"canonical balancer pool has invalid number of assets": {
 			// 100 existing shares and 100 shares added from balancer
-			existingConcentratedLiquidity: defaultConcentratedAssets,
 			balancerPoolAssets: []balancer.PoolAsset{
 				{Weight: sdk.NewInt(1), Token: sdk.NewCoin("foo", sdk.NewInt(100))},
 				{Weight: sdk.NewInt(1), Token: sdk.NewCoin("bar", sdk.NewInt(100))},
 				{Weight: sdk.NewInt(1), Token: sdk.NewCoin("baz", sdk.NewInt(100))},
 			},
-			portionOfSharesBonded:        sdk.NewDec(1),
 			invalidBalancerPoolLiquidity: true,
-
-			expectedError: types.ErrInvalidBalancerPoolLiquidityError{ClPoolId: 1, BalancerPoolId: 2, BalancerPoolLiquidity: sdk.NewCoins(sdk.NewCoin("foo", sdk.NewInt(100)), sdk.NewCoin("bar", sdk.NewInt(100)), sdk.NewCoin("baz", sdk.NewInt(100)))},
+			expectedError:                types.ErrInvalidBalancerPoolLiquidityError{ClPoolId: 1, BalancerPoolId: 2, BalancerPoolLiquidity: sdk.NewCoins(sdk.NewCoin("foo", sdk.NewInt(100)), sdk.NewCoin("bar", sdk.NewInt(100)), sdk.NewCoin("baz", sdk.NewInt(100)))},
 		},
 		"invalid concentrated pool ID": {
 			// 100 existing shares and 100 shares added from balancer
-			existingConcentratedLiquidity: defaultConcentratedAssets,
-			balancerPoolAssets:            defaultBalancerAssets,
-			portionOfSharesBonded:         sdk.NewDec(1),
-			invalidConcentratedPoolID:     true,
-
-			expectedError: types.PoolNotFoundError{PoolId: invalidPoolId + 1},
-		},
+			invalidConcentratedPoolID: true,
+			expectedError:             types.PoolNotFoundError{PoolId: invalidPoolId + 1},
+		},
+	}
+	// create invalid denom test cases. Either denom1, denom2 or both are invalid
+	denomSelector := [][]string{{"foo", "invalid1"}, {"bar", "invalid2"}}
+	for i := 0; i < 2; i++ {
+		pa1 := balancer.PoolAsset{Weight: sdk.NewInt(1), Token: sdk.NewCoin(denomSelector[0][i], sdk.NewInt(100))}
+		for j := 1 - i; j < 2; j++ {
+			pa2 := balancer.PoolAsset{Weight: sdk.NewInt(1), Token: sdk.NewCoin(denomSelector[1][j], sdk.NewInt(100))}
+			testname := fmt.Sprintf("canonical balancer pool; denom1_invalid=%v; denom2_invalid=%v", i == 1, j == 1)
+			tests[testname] = testcase{
+				balancerPoolAssets:           []balancer.PoolAsset{pa1, pa2},
+				invalidBalancerPoolLiquidity: true,
+				expectedError:                types.ErrInvalidBalancerPoolLiquidityError{ClPoolId: 1, BalancerPoolId: 2, BalancerPoolLiquidity: sdk.NewCoins(pa1.Token, pa2.Token)},
+			}
+		}
 	}
+
 	for name, tc := range tests {
 		s.Run(name, func() {
 			// --- Setup test env ---
-
 			s.SetupTest()
+			tc = initTestCase(tc)
+
 			clPool := s.PrepareCustomConcentratedPool(s.TestAccs[0], tc.existingConcentratedLiquidity[0].Denom, tc.existingConcentratedLiquidity[1].Denom, DefaultTickSpacing, sdk.ZeroDec())
 
 			// Set up an existing full range position. Note that the second return value is the position ID, not an error.
diff --git a/x/concentrated-liquidity/lp_test.go b/x/concentrated-liquidity/lp_test.go
index e1ea4c448..0143a1891 100644
--- a/x/concentrated-liquidity/lp_test.go
+++ b/x/concentrated-liquidity/lp_test.go
@@ -73,6 +73,11 @@ var (
 		expectedFeeGrowthOutsideUpper: cl.EmptyCoins,
 	}
 
+	errToleranceOneRoundDown = osmomath.ErrTolerance{
+		AdditiveTolerance: sdk.OneDec(),
+		RoundingDir:       osmomath.RoundDown,
+	}
+
 	roundingError = sdk.OneInt()
 
 	positionCases = map[string]lpTest{
@@ -387,6 +392,32 @@ func (s *KeeperTestSuite) TestCreatePosition() {
 	}
 }
 
+type lockState int
+
+const (
+	nolock lockState = iota
+	locked
+	unlocking
+	unlocked
+)
+
+func (s *KeeperTestSuite) createPositionWithLockState(ls lockState, poolId uint64, owner sdk.AccAddress, providedCoins sdk.Coins, dur time.Duration) (uint64, sdk.Dec) {
+	var liquidityCreated sdk.Dec
+	var positionId uint64
+	var err error
+	if ls == locked {
+		positionId, _, _, liquidityCreated, _, _, err = s.clk.CreateFullRangePositionLocked(s.Ctx, poolId, owner, providedCoins, dur)
+	} else if ls == unlocking {
+		positionId, _, _, liquidityCreated, _, _, err = s.clk.CreateFullRangePositionUnlocking(s.Ctx, poolId, owner, providedCoins, dur+time.Hour)
+	} else if ls == unlocked {
+		positionId, _, _, liquidityCreated, _, _, err = s.clk.CreateFullRangePositionUnlocking(s.Ctx, poolId, owner, providedCoins, dur-time.Hour)
+	} else {
+		positionId, _, _, liquidityCreated, _, _, _, err = s.clk.CreatePosition(s.Ctx, poolId, owner, providedCoins, sdk.ZeroInt(), sdk.ZeroInt(), DefaultLowerTick, DefaultUpperTick)
+	}
+	s.Require().NoError(err)
+	return positionId, liquidityCreated
+}
+
 func (s *KeeperTestSuite) TestWithdrawPosition() {
 	defaultTimeElapsed := time.Hour * 24
 	uptimeHelper := getExpectedUptimes()
@@ -402,9 +433,7 @@ func (s *KeeperTestSuite) TestWithdrawPosition() {
 		sutConfigOverwrite      *lpTest
 		createPositionOverwrite bool
 		timeElapsed             time.Duration
-		createLockLocked        bool
-		createLockUnlocking     bool
-		createLockUnlocked      bool
+		createLockState         lockState
 		withdrawWithNonOwner    bool
 	}{
 		"base case: withdraw full liquidity amount": {
@@ -425,8 +454,8 @@ func (s *KeeperTestSuite) TestWithdrawPosition() {
 				liquidityAmount:  FullRangeLiquidityAmt,
 				underlyingLockId: 1,
 			},
-			createLockUnlocked: true,
-			timeElapsed:        defaultTimeElapsed,
+			createLockState: unlocked,
+			timeElapsed:     defaultTimeElapsed,
 		},
 		"error: withdraw full liquidity amount but still locked": {
 			setupConfig: baseCase,
@@ -435,8 +464,8 @@ func (s *KeeperTestSuite) TestWithdrawPosition() {
 				underlyingLockId: 1,
 				expectedError:    types.LockNotMatureError{PositionId: 1, LockId: 1},
 			},
-			createLockLocked: true,
-			timeElapsed:      defaultTimeElapsed,
+			createLockState: locked,
+			timeElapsed:     defaultTimeElapsed,
 		},
 		"error: withdraw full liquidity amount but still unlocking": {
 			setupConfig: baseCase,
@@ -445,8 +474,8 @@ func (s *KeeperTestSuite) TestWithdrawPosition() {
 				underlyingLockId: 1,
 				expectedError:    types.LockNotMatureError{PositionId: 1, LockId: 1},
 			},
-			createLockUnlocking: true,
-			timeElapsed:         defaultTimeElapsed,
+			createLockState: unlocking,
+			timeElapsed:     defaultTimeElapsed,
 		},
 		"withdraw partial liquidity amount": {
 			setupConfig: baseCase,
@@ -512,34 +541,19 @@ func (s *KeeperTestSuite) TestWithdrawPosition() {
 				concentratedLiquidityKeeper = s.App.ConcentratedLiquidityKeeper
 				liquidityCreated            = sdk.ZeroDec()
 				owner                       = s.TestAccs[0]
-				tc                          = tc
 				config                      = *tc.setupConfig
-				sutConfigOverwrite          = *tc.sutConfigOverwrite
 				err                         error
 			)
 
 			// If specific configs are provided in the test case, overwrite the config with those values.
-			mergeConfigs(&config, &sutConfigOverwrite)
+			mergeConfigs(&config, tc.sutConfigOverwrite)
 
 			// If a setupConfig is provided, use it to create a pool and position.
 			pool := s.PrepareConcentratedPool()
 			fundCoins := config.tokensProvided
 			s.FundAcc(owner, fundCoins)
 
-			// Create a position from the parameters in the test case.
-			if tc.createLockLocked {
-				_, _, _, liquidityCreated, _, _, err = concentratedLiquidityKeeper.CreateFullRangePositionLocked(s.Ctx, pool.GetId(), owner, fundCoins, tc.timeElapsed)
-				s.Require().NoError(err)
-			} else if tc.createLockUnlocking {
-				_, _, _, liquidityCreated, _, _, err = concentratedLiquidityKeeper.CreateFullRangePositionUnlocking(s.Ctx, pool.GetId(), owner, fundCoins, tc.timeElapsed+time.Hour)
-				s.Require().NoError(err)
-			} else if tc.createLockUnlocked {
-				_, _, _, liquidityCreated, _, _, err = concentratedLiquidityKeeper.CreateFullRangePositionUnlocking(s.Ctx, pool.GetId(), owner, fundCoins, tc.timeElapsed-time.Hour)
-				s.Require().NoError(err)
-			} else {
-				_, _, _, liquidityCreated, _, _, _, err = concentratedLiquidityKeeper.CreatePosition(s.Ctx, pool.GetId(), owner, config.tokensProvided, sdk.ZeroInt(), sdk.ZeroInt(), DefaultLowerTick, DefaultUpperTick)
-				s.Require().NoError(err)
-			}
+			_, liquidityCreated = s.createPositionWithLockState(tc.createLockState, pool.GetId(), owner, fundCoins, tc.timeElapsed)
 
 			// Set mock listener to make sure that is is called when desired.
 			// It must be set after test position creation so that we do not record the call
@@ -688,7 +702,7 @@ func (s *KeeperTestSuite) TestWithdrawPosition() {
 				s.Require().Nil(positionIdBytes)
 
 				// ensure that the lock is still there if there was lock that was existing before the withdraw process
-				if tc.createLockLocked || tc.createLockUnlocked || tc.createLockUnlocking {
+				if tc.createLockState != nolock {
 					_, err = s.App.LockupKeeper.GetLockByID(s.Ctx, 1)
 					s.Require().NoError(err)
 				}
@@ -745,9 +759,7 @@ func (s *KeeperTestSuite) TestAddToPosition() {
 		sutConfigOverwrite      *lpTest
 		timeElapsed             time.Duration
 		createPositionOverwrite bool
-		createLockLocked        bool
-		createLockUnlocking     bool
-		createLockUnlocked      bool
+		createLockState         lockState
 		lastPositionInPool      bool
 		senderNotOwner          bool
 
@@ -836,7 +848,7 @@ func (s *KeeperTestSuite) TestAddToPosition() {
 			amount0ToAdd: amount0PerfectRatio,
 			amount1ToAdd: amount1PerfectRatio,
 
-			createLockUnlocked: true,
+			createLockState: unlocked,
 		},
 		"error: attempt to add to a position with underlying lock that is still locked": {
 			// setup parameters for creating a pool and position.
@@ -857,7 +869,7 @@ func (s *KeeperTestSuite) TestAddToPosition() {
 			amount0ToAdd: amount0PerfectRatio,
 			amount1ToAdd: amount1PerfectRatio,
 
-			createLockLocked: true,
+			createLockState: locked,
 		},
 		"error: attempt to add negative amounts for both assets to position": {
 			// setup parameters for creating a pool and position.
@@ -930,7 +942,7 @@ func (s *KeeperTestSuite) TestAddToPosition() {
 			amount0ToAdd: amount0PerfectRatio,
 			amount1ToAdd: amount1PerfectRatio,
 
-			createLockUnlocking: true,
+			createLockState: unlocking,
 		},
 		"error: no position created": {
 			// setup parameters for creation a pool and position.
@@ -1018,39 +1030,28 @@ func (s *KeeperTestSuite) TestAddToPosition() {
 			var (
 				concentratedLiquidityKeeper = s.App.ConcentratedLiquidityKeeper
 				owner                       = s.TestAccs[0]
-				tc                          = tc
 				config                      = *tc.setupConfig
-				sutConfigOverwrite          = *tc.sutConfigOverwrite
 				err                         error
 			)
 
 			// If specific configs are provided in the test case, overwrite the config with those values.
-			mergeConfigs(&config, &sutConfigOverwrite)
+			mergeConfigs(&config, tc.sutConfigOverwrite)
 
 			// If a setupConfig is provided, use it to create a pool and position.
 			pool := s.PrepareConcentratedPool()
-			fundCoins := config.tokensProvided
+			fundCoins, lockCoins := config.tokensProvided, config.tokensProvided
 			// Fund tokens that is used to create initial position
 			if tc.amount0ToAdd.IsPositive() && tc.amount1ToAdd.IsPositive() {
 				fundCoins = fundCoins.Add(sdk.NewCoins(sdk.NewCoin(ETH, tc.amount0ToAdd), sdk.NewCoin(USDC, tc.amount1ToAdd))...)
+				if tc.createLockState != nolock {
+					lockCoins = fundCoins
+				}
 			}
 			s.FundAcc(owner, fundCoins)
 
 			// Create a position from the parameters in the test case.
-			var positionId uint64
-			if tc.createLockLocked {
-				positionId, _, _, _, _, _, err = concentratedLiquidityKeeper.CreateFullRangePositionLocked(s.Ctx, pool.GetId(), owner, fundCoins, tc.timeElapsed)
-				s.Require().NoError(err)
-			} else if tc.createLockUnlocking {
-				positionId, _, _, _, _, _, err = concentratedLiquidityKeeper.CreateFullRangePositionUnlocking(s.Ctx, pool.GetId(), owner, fundCoins, tc.timeElapsed+time.Hour)
-				s.Require().NoError(err)
-			} else if tc.createLockUnlocked {
-				positionId, _, _, _, _, _, err = concentratedLiquidityKeeper.CreateFullRangePositionUnlocking(s.Ctx, pool.GetId(), owner, fundCoins, tc.timeElapsed-time.Hour)
-				s.Require().NoError(err)
-			} else {
-				positionId, _, _, _, _, _, _, err = concentratedLiquidityKeeper.CreatePosition(s.Ctx, pool.GetId(), owner, config.tokensProvided, sdk.ZeroInt(), sdk.ZeroInt(), DefaultLowerTick, DefaultUpperTick)
-				s.Require().NoError(err)
-			}
+			positionId, _ := s.createPositionWithLockState(tc.createLockState, pool.GetId(), owner, lockCoins, tc.timeElapsed)
+
 			s.Ctx = s.Ctx.WithBlockTime(s.Ctx.BlockTime().Add(tc.timeElapsed))
 			preBalanceToken0 := s.App.BankKeeper.GetBalance(s.Ctx, owner, pool.GetToken0())
 
@@ -1104,12 +1105,8 @@ func (s *KeeperTestSuite) TestAddToPosition() {
 			postBalanceToken0 := s.App.BankKeeper.GetBalance(s.Ctx, sender, pool.GetToken0())
 			postBalanceToken1 := s.App.BankKeeper.GetBalance(s.Ctx, sender, pool.GetToken1())
 
-			var errTolerance osmomath.ErrTolerance
-			errTolerance.AdditiveTolerance = sdk.OneDec()
-			errTolerance.RoundingDir = osmomath.RoundDown
-
-			s.Require().Equal(0, errTolerance.Compare(preBalanceToken0.Amount, postBalanceToken0.Amount))
-			s.Require().Equal(0, errTolerance.Compare(expectedAmount1Delta, postBalanceToken1.Amount.Sub(tc.amount1ToAdd)))
+			s.Require().Equal(0, errToleranceOneRoundDown.Compare(preBalanceToken0.Amount, postBalanceToken0.Amount))
+			s.Require().Equal(0, errToleranceOneRoundDown.Compare(expectedAmount1Delta, postBalanceToken1.Amount.Sub(tc.amount1ToAdd)))
 
 			// now check that old position id has been succesfully deleted
 			_, err = s.App.ConcentratedLiquidityKeeper.GetPosition(s.Ctx, positionId)
@@ -1623,22 +1620,12 @@ func (s *KeeperTestSuite) TestInitializeInitialPositionForPool() {
 
 func (s *KeeperTestSuite) TestInverseRelation_CreatePosition_WithdrawPosition() {
 	var (
-		errToleranceOneRoundDown = osmomath.ErrTolerance{
-			AdditiveTolerance: sdk.OneDec(),
-			RoundingDir:       osmomath.RoundDown,
-		}
-
 		errToleranceOneRoundUp = osmomath.ErrTolerance{
 			AdditiveTolerance: sdk.OneDec(),
 			RoundingDir:       osmomath.RoundUp,
 		}
 	)
-	tests := map[string]lpTest{}
-
-	// add test cases for different positions
-	for name, test := range positionCases {
-		tests[name] = test
-	}
+	tests := makeTests(positionCases)
 
 	for name, tc := range tests {
 		tc := tc
@@ -1729,8 +1716,6 @@ func (s *KeeperTestSuite) TestInverseRelation_CreatePosition_WithdrawPosition()
 			liquidityAfter, err := s.App.ConcentratedLiquidityKeeper.GetTotalPoolLiquidity(s.Ctx, poolID)
 			s.Require().NoError(err)
 
-			s.Require().NoError(err)
-
 			// Note: one ends up remaining due to rounding in favor of the pool.
 			s.Require().Equal(0, errToleranceOneRoundUp.Compare(liquidityBefore.AmountOf(ETH), liquidityAfter.AmountOf(ETH)))
 			s.Require().Equal(0, errToleranceOneRoundUp.Compare(liquidityBefore.AmountOf(USDC), liquidityAfter.AmountOf(USDC)))
diff --git a/x/concentrated-liquidity/math/math_test.go b/x/concentrated-liquidity/math/math_test.go
index 6b21d9f82..2fbbdcb9c 100644
--- a/x/concentrated-liquidity/math/math_test.go
+++ b/x/concentrated-liquidity/math/math_test.go
@@ -20,6 +20,8 @@ func TestConcentratedTestSuite(t *testing.T) {
 	suite.Run(t, new(ConcentratedMathTestSuite))
 }
 
+var sqrt5000 = sdk.MustNewDecFromStr("70.710678118654752440")
+
 // liquidity1 takes an amount of asset1 in the pool as well as the sqrtpCur and the nextPrice
 // sqrtPriceA is the smaller of sqrtpCur and the nextPrice
 // sqrtPriceB is the larger of sqrtpCur and the nextPrice
@@ -32,7 +34,7 @@ func (suite *ConcentratedMathTestSuite) TestLiquidity1() {
 		expectedLiquidity string
 	}{
 		"happy path": {
-			currentSqrtP:      sdk.MustNewDecFromStr("70.710678118654752440"), // 5000
+			currentSqrtP:      sqrt5000,                                       // 5000
 			sqrtPLow:          sdk.MustNewDecFromStr("67.416615162732695594"), // 4545
 			amount1Desired:    sdk.NewInt(5000000000),
 			expectedLiquidity: "1517882343.751510418088349649",
@@ -62,7 +64,7 @@ func (suite *ConcentratedMathTestSuite) TestLiquidity0() {
 		expectedLiquidity string
 	}{
 		"happy path": {
-			currentSqrtP:      sdk.MustNewDecFromStr("70.710678118654752440"), // 5000
+			currentSqrtP:      sqrt5000,                                       // 5000
 			sqrtPHigh:         sdk.MustNewDecFromStr("74.161984870956629487"), // 5500
 			amount0Desired:    sdk.NewInt(1000000),
 			expectedLiquidity: "1519437308.014768571720923239",
@@ -98,7 +100,7 @@ func (suite *ConcentratedMathTestSuite) TestGetNextSqrtPriceFromAmount0RoundingU
 	}{
 		"happy path": {
 			liquidity:             sdk.MustNewDecFromStr("1517882343.751510418088349649"), // liquidity0 calculated above
-			sqrtPCurrent:          sdk.MustNewDecFromStr("70.710678118654752440"),
+			sqrtPCurrent:          sqrt5000,
 			amount0Remaining:      sdk.NewDec(13370),
 			sqrtPriceNextExpected: "70.666663910857144332",
 			// https://www.wolframalpha.com/input?i=%28%281517882343.751510418088349649%29%29+%2F+%28%28%281517882343.751510418088349649%29+%2F+%2870.710678118654752440%29%29+%2B+%2813370%29%29
@@ -128,7 +130,7 @@ func (suite *ConcentratedMathTestSuite) TestGetNextSqrtPriceFromAmount1RoundingD
 	}{
 		"happy path": {
 			liquidity:             sdk.MustNewDecFromStr("1519437308.014768571721000000"), // liquidity1 calculated above
-			sqrtPCurrent:          sdk.MustNewDecFromStr("70.710678118654752440"),         // 5000000000
+			sqrtPCurrent:          sqrt5000,                                               // 5000000000
 			amount1Remaining:      sdk.NewDec(42000000),
 			sqrtPriceNextExpected: "70.738319930382329008",
 			// https://www.wolframalpha.com/input?i=70.710678118654752440+%2B++++%2842000000+%2F+1519437308.014768571721000000%29
@@ -160,7 +162,7 @@ func (suite *ConcentratedMathTestSuite) TestCalcAmount0Delta() {
 	}{
 		"happy path": {
 			liquidity:       sdk.MustNewDecFromStr("1517882343.751510418088349649"), // we use the smaller liquidity between liq0 and liq1
-			sqrtPA:          sdk.MustNewDecFromStr("70.710678118654752440"),         // 5000
+			sqrtPA:          sqrt5000,                                               // 5000
 			sqrtPB:          sdk.MustNewDecFromStr("74.161984870956629487"),         // 5500
 			roundUp:         false,
 			amount0Expected: "998976.618347426388356619", // truncated at precision end.
@@ -252,7 +254,7 @@ func (suite *ConcentratedMathTestSuite) TestCalcAmount1Delta() {
 	}{
 		"round down": {
 			liquidity:       sdk.MustNewDecFromStr("1517882343.751510418088349649"), // we use the smaller liquidity between liq0 and liq1
-			sqrtPA:          sdk.MustNewDecFromStr("70.710678118654752440"),         // 5000
+			sqrtPA:          sqrt5000,                                               // 5000
 			sqrtPB:          sdk.MustNewDecFromStr("67.416615162732695594"),         // 4545
 			roundUp:         false,
 			amount1Expected: sdk.MustNewDecFromStr("5000000000.000000000000000000").Sub(sdk.SmallestDec()).String(),
@@ -338,7 +340,7 @@ func (suite *ConcentratedMathTestSuite) TestGetLiquidityFromAmounts() {
 			expectedLiquidity: "741212151.448720111852782017",
 		},
 		"happy path (case B)": {
-			currentSqrtP:      sdk.MustNewDecFromStr("70.710678118654752440"), // 5000
+			currentSqrtP:      sqrt5000,                                       // 5000
 			sqrtPHigh:         sdk.MustNewDecFromStr("74.161984870956629487"), // 5500
 			sqrtPLow:          sdk.MustNewDecFromStr("67.416615162732695594"), // 4545
 			amount0Desired:    sdk.NewInt(1000000),
@@ -402,146 +404,103 @@ func (suite *ConcentratedMathTestSuite) TestGetLiquidityFromAmounts() {
 	}
 }
 
-func (suite *ConcentratedMathTestSuite) TestGetNextSqrtPriceFromAmount0InRoundingUp() {
-	tests := map[string]struct {
-		sqrtPriceCurrent     sdk.Dec
-		liquidity            sdk.Dec
-		amountZeroRemaininIn sdk.Dec
+type sqrtRoundingTestCase struct {
+	sqrtPriceCurrent sdk.Dec
+	liquidity        sdk.Dec
+	amountRemaining  sdk.Dec
+	expected         sdk.Dec
+}
 
-		expectedSqrtPriceNext sdk.Dec
-	}{
-		"rounded up at precision end": {
-			sqrtPriceCurrent:     sdk.MustNewDecFromStr("70.710678118654752440"),
-			liquidity:            sdk.MustNewDecFromStr("3035764687.503020836176699298"),
-			amountZeroRemaininIn: sdk.MustNewDecFromStr("8398"),
+func (suite *ConcentratedMathTestSuite) runSqrtRoundingTestCase(
+	name string,
+	fn func(sdk.Dec, sdk.Dec, sdk.Dec) sdk.Dec,
+	cases map[string]sqrtRoundingTestCase,
+) {
+	for name, tc := range cases {
+		tc := tc
+		suite.Run(name, func() {
+			sqrtPriceNext := fn(tc.sqrtPriceCurrent, tc.liquidity, tc.amountRemaining)
+			suite.Require().Equal(tc.expected.String(), sqrtPriceNext.String())
+		})
+	}
+}
 
+func (suite *ConcentratedMathTestSuite) TestGetNextSqrtPriceFromAmount0InRoundingUp() {
+	tests := map[string]sqrtRoundingTestCase{
+		"rounded up at precision end": {
+			sqrtPriceCurrent: sqrt5000,
+			liquidity:        sdk.MustNewDecFromStr("3035764687.503020836176699298"),
+			amountRemaining:  sdk.MustNewDecFromStr("8398"),
 			// liq * sqrt_cur / (liq + token_in * sqrt_cur) = 70.69684905341696614869539245
-			expectedSqrtPriceNext: sdk.MustNewDecFromStr("70.696849053416966149"),
+			expected: sdk.MustNewDecFromStr("70.696849053416966149"),
 		},
 		"no round up due zeroes at precision end": {
-			sqrtPriceCurrent:     sdk.MustNewDecFromStr("2"),
-			liquidity:            sdk.MustNewDecFromStr("10"),
-			amountZeroRemaininIn: sdk.MustNewDecFromStr("15"),
-
+			sqrtPriceCurrent: sdk.MustNewDecFromStr("2"),
+			liquidity:        sdk.MustNewDecFromStr("10"),
+			amountRemaining:  sdk.MustNewDecFromStr("15"),
 			// liq * sqrt_cur / (liq + token_in * sqrt_cur) = 0.5
-			expectedSqrtPriceNext: sdk.MustNewDecFromStr("0.5"),
+			expected: sdk.MustNewDecFromStr("0.5"),
 		},
 	}
-
-	for name, tc := range tests {
-		tc := tc
-		suite.Run(name, func() {
-			sqrtPriceNext := math.GetNextSqrtPriceFromAmount0InRoundingUp(tc.sqrtPriceCurrent, tc.liquidity, tc.amountZeroRemaininIn)
-
-			suite.Require().Equal(tc.expectedSqrtPriceNext.String(), sqrtPriceNext.String())
-		})
-	}
+	suite.runSqrtRoundingTestCase("TestGetNextSqrtPriceFromAmount0InRoundingUp", math.GetNextSqrtPriceFromAmount0InRoundingUp, tests)
 }
 
 func (suite *ConcentratedMathTestSuite) TestGetNextSqrtPriceFromAmount0OutRoundingUp() {
-	tests := map[string]struct {
-		sqrtPriceCurrent       sdk.Dec
-		liquidity              sdk.Dec
-		amountZeroRemainingOut sdk.Dec
-
-		expectedSqrtPriceNext sdk.Dec
-	}{
+	tests := map[string]sqrtRoundingTestCase{
 		"rounded up at precision end": {
-			sqrtPriceCurrent:       sdk.MustNewDecFromStr("70.710678118654752440"),
-			liquidity:              sdk.MustNewDecFromStr("3035764687.503020836176699298"),
-			amountZeroRemainingOut: sdk.MustNewDecFromStr("8398"),
-
+			sqrtPriceCurrent: sqrt5000,
+			liquidity:        sdk.MustNewDecFromStr("3035764687.503020836176699298"),
+			amountRemaining:  sdk.MustNewDecFromStr("8398"),
 			// liq * sqrt_cur / (liq - token_out * sqrt_cur) = 70.72451259517930556540769876
-			expectedSqrtPriceNext: sdk.MustNewDecFromStr("70.724512595179305566"),
+			expected: sdk.MustNewDecFromStr("70.724512595179305566"),
 		},
 		"no round up due zeroes at precision end": {
-			sqrtPriceCurrent:       sdk.MustNewDecFromStr("2"),
-			liquidity:              sdk.MustNewDecFromStr("10"),
-			amountZeroRemainingOut: sdk.MustNewDecFromStr("1"),
-
+			sqrtPriceCurrent: sdk.MustNewDecFromStr("2"),
+			liquidity:        sdk.MustNewDecFromStr("10"),
+			amountRemaining:  sdk.MustNewDecFromStr("1"),
 			// liq * sqrt_cur / (liq + token_out * sqrt_cur) = 2.5
-			expectedSqrtPriceNext: sdk.MustNewDecFromStr("2.5"),
+			expected: sdk.MustNewDecFromStr("2.5"),
 		},
 	}
-
-	for name, tc := range tests {
-		tc := tc
-		suite.Run(name, func() {
-			sqrtPriceNext := math.GetNextSqrtPriceFromAmount0OutRoundingUp(tc.sqrtPriceCurrent, tc.liquidity, tc.amountZeroRemainingOut)
-
-			suite.Require().Equal(tc.expectedSqrtPriceNext.String(), sqrtPriceNext.String())
-		})
-	}
+	suite.runSqrtRoundingTestCase("TestGetNextSqrtPriceFromAmount0OutRoundingUp", math.GetNextSqrtPriceFromAmount0OutRoundingUp, tests)
 }
 
 func (suite *ConcentratedMathTestSuite) TestGetNextSqrtPriceFromAmount1InRoundingDown() {
-	tests := map[string]struct {
-		sqrtPriceCurrent     sdk.Dec
-		liquidity            sdk.Dec
-		amountOneRemainingIn sdk.Dec
-
-		expectedSqrtPriceNext sdk.Dec
-	}{
+	tests := map[string]sqrtRoundingTestCase{
 		"rounded down at precision end": {
-			sqrtPriceCurrent:     sdk.MustNewDecFromStr("70.710678118654752440"),
-			liquidity:            sdk.MustNewDecFromStr("3035764687.503020836176699298"),
-			amountOneRemainingIn: sdk.MustNewDecFromStr("8398"),
-
+			sqrtPriceCurrent: sqrt5000,
+			liquidity:        sdk.MustNewDecFromStr("3035764687.503020836176699298"),
+			amountRemaining:  sdk.MustNewDecFromStr("8398"),
 			// sqrt_next = sqrt_cur + token_in / liq = 70.71068088500882282334333927
-			expectedSqrtPriceNext: sdk.MustNewDecFromStr("70.710680885008822823"),
+			expected: sdk.MustNewDecFromStr("70.710680885008822823"),
 		},
 		"no round up due zeroes at precision end": {
-			sqrtPriceCurrent:     sdk.MustNewDecFromStr("2.5"),
-			liquidity:            sdk.MustNewDecFromStr("1"),
-			amountOneRemainingIn: sdk.MustNewDecFromStr("10"),
-
+			sqrtPriceCurrent: sdk.MustNewDecFromStr("2.5"),
+			liquidity:        sdk.MustNewDecFromStr("1"),
+			amountRemaining:  sdk.MustNewDecFromStr("10"),
 			// sqrt_next = sqrt_cur + token_in / liq
-			expectedSqrtPriceNext: sdk.MustNewDecFromStr("12.5"),
+			expected: sdk.MustNewDecFromStr("12.5"),
 		},
 	}
-
-	for name, tc := range tests {
-		tc := tc
-		suite.Run(name, func() {
-			sqrtPriceNext := math.GetNextSqrtPriceFromAmount1InRoundingDown(tc.sqrtPriceCurrent, tc.liquidity, tc.amountOneRemainingIn)
-
-			suite.Require().Equal(tc.expectedSqrtPriceNext.String(), sqrtPriceNext.String())
-		})
-	}
+	suite.runSqrtRoundingTestCase("TestGetNextSqrtPriceFromAmount1InRoundingDown", math.GetNextSqrtPriceFromAmount1InRoundingDown, tests)
 }
 
 func (suite *ConcentratedMathTestSuite) TestGetNextSqrtPriceFromAmount1OutRoundingDown() {
-	tests := map[string]struct {
-		sqrtPriceCurrent      sdk.Dec
-		liquidity             sdk.Dec
-		amountOneRemainingOut sdk.Dec
-
-		expectedSqrtPriceNext sdk.Dec
-	}{
+	tests := map[string]sqrtRoundingTestCase{
 		"rounded down at precision end": {
-			sqrtPriceCurrent:      sdk.MustNewDecFromStr("70.710678118654752440"),
-			liquidity:             sdk.MustNewDecFromStr("3035764687.503020836176699298"),
-			amountOneRemainingOut: sdk.MustNewDecFromStr("8398"),
-
+			sqrtPriceCurrent: sqrt5000,
+			liquidity:        sdk.MustNewDecFromStr("3035764687.503020836176699298"),
+			amountRemaining:  sdk.MustNewDecFromStr("8398"),
 			// sqrt_next = sqrt_cur - token_out / liq = 70.71067535230068205665666073
-			expectedSqrtPriceNext: sdk.MustNewDecFromStr("70.710675352300682056"),
+			expected: sdk.MustNewDecFromStr("70.710675352300682056"),
 		},
 		"no round up due zeroes at precision end": {
-			sqrtPriceCurrent:      sdk.MustNewDecFromStr("12.5"),
-			liquidity:             sdk.MustNewDecFromStr("1"),
-			amountOneRemainingOut: sdk.MustNewDecFromStr("10"),
-
+			sqrtPriceCurrent: sdk.MustNewDecFromStr("12.5"),
+			liquidity:        sdk.MustNewDecFromStr("1"),
+			amountRemaining:  sdk.MustNewDecFromStr("10"),
 			// sqrt_next = sqrt_cur - token_out / liq
-			expectedSqrtPriceNext: sdk.MustNewDecFromStr("2.5"),
+			expected: sdk.MustNewDecFromStr("2.5"),
 		},
 	}
-
-	for name, tc := range tests {
-		tc := tc
-		suite.Run(name, func() {
-			sqrtPriceNext := math.GetNextSqrtPriceFromAmount1OutRoundingDown(tc.sqrtPriceCurrent, tc.liquidity, tc.amountOneRemainingOut)
-
-			suite.Require().Equal(tc.expectedSqrtPriceNext.String(), sqrtPriceNext.String())
-		})
-	}
+	suite.runSqrtRoundingTestCase("TestGetNextSqrtPriceFromAmount1OutRoundingDown", math.GetNextSqrtPriceFromAmount1OutRoundingDown, tests)
 }
diff --git a/x/concentrated-liquidity/swaps_test.go b/x/concentrated-liquidity/swaps_test.go
index a80abbf1e..8f4cb361e 100644
--- a/x/concentrated-liquidity/swaps_test.go
+++ b/x/concentrated-liquidity/swaps_test.go
@@ -262,7 +262,7 @@ var (
 			expectedTokenIn:                  sdk.NewCoin("usdc", sdk.NewInt(10000000000)),
 			expectedTokenOut:                 sdk.NewCoin("eth", sdk.NewInt(1864161)),
 			expectedTick:                     32055900,
-			expectedSqrtPrice:                sdk.MustNewDecFromStr("77.819789636800169392"), // https://www.wolframalpha.com/input?i=74.16198487095662948711397441+%2B++++%282452251164.000000000000000000+%2F+670416088.605668727039240782%29
+			expectedSqrtPrice:                sdk.MustNewDecFromStr("77.819789636800169393"), // https://www.wolframalpha.com/input?i=74.16198487095662948711397441+%2B++++%282452251164.000000000000000000+%2F+670416088.605668727039240782%29
 			expectedLowerTickFeeGrowth:       DefaultFeeAccumCoins,
 			expectedUpperTickFeeGrowth:       DefaultFeeAccumCoins,
 			expectedSecondLowerTickFeeGrowth: secondPosition{tickIndex: 310010, expectedFeeGrowth: cl.EmptyCoins},
@@ -324,7 +324,7 @@ var (
 			expectedTokenIn:          sdk.NewCoin("eth", sdk.NewInt(2000000)),
 			expectedTokenOut:         sdk.NewCoin("usdc", sdk.NewInt(9321276930)),
 			expectedTick:             30129000,
-			expectedSqrtPrice:        sdk.MustNewDecFromStr("64.257943794993248954"), // https://www.wolframalpha.com/input?i=%28%28670416215.71882744366040059300%29%29+%2F+%28%28%28670416215.71882744366040059300%29+%2F+%2867.41661516273269559379442134%29%29+%2B+%28488827.000000000000000000%29%29
+			expectedSqrtPrice:        sdk.MustNewDecFromStr("64.257943794993248955"), // https://www.wolframalpha.com/input?i=%28%28670416215.71882744366040059300%29%29+%2F+%28%28%28670416215.71882744366040059300%29+%2F+%2867.41661516273269559379442134%29%29+%2B+%28488827.000000000000000000%29%29
 			// Started from DefaultFeeAccumCoins * 3, crossed tick once, thus becoming
 			// DefaultFeeAccumCoins * 3 - DefaultFeeAccumCoins = DefaultFeeAccumCoins * 2
 			expectedLowerTickFeeGrowth:       DefaultFeeAccumCoins.MulDec(sdk.NewDec(2)),
@@ -411,17 +411,17 @@ var (
 			spreadFactor:  sdk.ZeroDec(),
 			// params
 			// liquidity: 		 1517882343.751510418088349649
-			// sqrtPriceNext:    70.668238976219012614 which is 4994 https://www.wolframalpha.com/input?i=70.710678118654752440+%2B+42000000+%2F+1517882343.751510418088349649
+			// sqrtPriceNext:    70.668238976219012613 which is 4994 https://www.wolframalpha.com/input?i=70.710678118654752440+%2B+42000000+%2F+1517882343.751510418088349649
 			// sqrtPriceCurrent: 70.710678118654752440 which is 5000
-			// expectedTokenIn:  12891.26207649936510 rounded up https://www.wolframalpha.com/input?key=&i=%281517882343.751510418088349649+*+%2870.710678118654752440+-+70.668238976219012614+%29%29+%2F+%2870.710678118654752440+*+70.668238976219012614%29
-			// expectedTokenOut: 64417624.98716495170 rounded down https://www.wolframalpha.com/input?key=&i=1517882343.751510418088349649+*+%2870.710678118654752440+-+70.668238976219012614%29
+			// expectedTokenIn:  12891.26207649936540 rounded up https://www.wolframalpha.com/input?i=%281517882343.751510418088349649+*+%2870.710678118654752440+-+70.668238976219012613+%29%29+%2F+%2870.710678118654752440+*+70.668238976219012614%29
+			// expectedTokenOut: 64417624.98716495322 rounded down https://www.wolframalpha.com/input?i=1517882343.751510418088349649+*+%2870.710678118654752440+-+70.668238976219012613%29+expectedTokenIn%3A++sdk.NewCoin%28%22eth%22%2C+sdk.NewInt%2812892%29%29%2C
 			expectedTokenIn:  sdk.NewCoin("eth", sdk.NewInt(12892)),
 			expectedTokenOut: sdk.NewCoin("usdc", sdk.NewInt(64417624)),
 			expectedTick: func() int64 {
 				tick, _ := math.PriceToTickRoundDown(sdk.NewDec(4994), DefaultTickSpacing)
 				return tick
 			}(),
-			expectedSqrtPrice:          sdk.MustNewDecFromStr("70.668238976219012614"), // https://www.wolframalpha.com/input?i=%28%281517882343.751510418088349649%29%29+%2F+%28%28%281517882343.751510418088349649%29+%2F+%2870.710678118654752440%29%29+%2B+%2812891.26207649936510%29%29
+			expectedSqrtPrice:          sdk.MustNewDecFromStr("70.668238976219012613"), // https://www.wolframalpha.com/input?i=%28%281517882343.751510418088349649%29%29+%2F+%28%28%281517882343.751510418088349649%29+%2F+%2870.710678118654752440%29%29+%2B+%2812891.26207649936510%29%29
 			expectedLowerTickFeeGrowth: DefaultFeeAccumCoins,
 			expectedUpperTickFeeGrowth: DefaultFeeAccumCoins,
 		},
@@ -1026,7 +1026,7 @@ var (
 			expectedSecondLowerTickFeeGrowth: secondPosition{tickIndex: 310010, expectedFeeGrowth: cl.EmptyCoins},
 			expectedSecondUpperTickFeeGrowth: secondPosition{tickIndex: 322500, expectedFeeGrowth: cl.EmptyCoins},
 			expectedTick:                     31712600,
-			expectedSqrtPrice:                sdk.MustNewDecFromStr("75.582372355128594341"),
+			expectedSqrtPrice:                sdk.MustNewDecFromStr("75.582372355128594340"),
 			newLowerPrice:                    sdk.NewDec(5001),
 			newUpperPrice:                    sdk.NewDec(6250),
 		},
@@ -1335,7 +1335,7 @@ var (
 			expectedSecondLowerTickFeeGrowth:  secondPosition{tickIndex: 310010, expectedFeeGrowth: cl.EmptyCoins},
 			expectedSecondUpperTickFeeGrowth:  secondPosition{tickIndex: 322500, expectedFeeGrowth: cl.EmptyCoins},
 			expectedTick:                      31712600,
-			expectedSqrtPrice:                 sdk.MustNewDecFromStr("75.582372355128594341"),
+			expectedSqrtPrice:                 sdk.MustNewDecFromStr("75.582372355128594340"),
 			newLowerPrice:                     sdk.NewDec(5001),
 			newUpperPrice:                     sdk.NewDec(6250),
 			expectedFeeGrowthAccumulatorValue: sdk.MustNewDecFromStr("0.256404959888119530"),
@@ -1470,12 +1470,12 @@ func (s *KeeperTestSuite) preparePoolWithCustSpread(spread sdk.Dec) types.Concen
 	return s.PrepareCustomConcentratedPool(s.TestAccs[0], "eth", "usdc", DefaultTickSpacing, spread)
 }
 
-func makeSwapTests(tests ...map[string]SwapTest) map[string]SwapTest {
+func makeTests[T any](tests ...map[string]T) map[string]T {
 	length := 0
 	for i := range tests {
 		length += len(tests[i])
 	}
-	retTests := make(map[string]SwapTest, length)
+	retTests := make(map[string]T, length)
 	for _, tt := range tests {
 		for name, test := range tt {
 			retTests[name] = test
@@ -1550,7 +1550,7 @@ func (s *KeeperTestSuite) getExpectedLiquidity(test SwapTest, pool types.Concent
 
 func (s *KeeperTestSuite) TestComputeAndSwapOutAmtGivenIn() {
 	// add error cases as well
-	tests := makeSwapTests(swapOutGivenInCases, swapOutGivenInCases, swapOutGivenInErrorCases)
+	tests := makeTests(swapOutGivenInCases, swapOutGivenInCases, swapOutGivenInErrorCases)
 
 	for name, test := range tests {
 		test := test
@@ -1628,7 +1628,7 @@ func (s *KeeperTestSuite) TestSwap_NoPositions() {
 }
 
 func (s *KeeperTestSuite) TestSwapOutAmtGivenIn_TickUpdates() {
-	tests := makeSwapTests(swapOutGivenInCases)
+	tests := makeTests(swapOutGivenInCases)
 	for name, test := range tests {
 		test := test
 		s.Run(name, func() {
@@ -1704,7 +1704,7 @@ func (s *KeeperTestSuite) testSwapResult(test SwapTest, pool types.ConcentratedP
 
 func (s *KeeperTestSuite) TestComputeAndSwapInAmtGivenOut() {
 	// add error cases as well
-	tests := makeSwapTests(swapInGivenOutTestCases, swapInGivenOutFeeTestCases, swapInGivenOutErrorTestCases)
+	tests := makeTests(swapInGivenOutTestCases, swapInGivenOutFeeTestCases, swapInGivenOutErrorTestCases)
 	for name, test := range tests {
 		test := test
 		s.Run(name, func() {
@@ -1763,7 +1763,7 @@ func (s *KeeperTestSuite) TestComputeAndSwapInAmtGivenOut() {
 }
 
 func (s *KeeperTestSuite) TestSwapInAmtGivenOut_TickUpdates() {
-	tests := makeSwapTests(swapInGivenOutTestCases)
+	tests := makeTests(swapInGivenOutTestCases)
 	for name, test := range tests {
 		s.Run(name, func() {
 			s.setupAndFundSwapTest()
@@ -2204,7 +2204,7 @@ func (s *KeeperTestSuite) TestComputeOutAmtGivenIn() {
 // TestCalcOutAmtGivenIn_NonMutative tests that CalcOutAmtGivenIn is non-mutative.
 func (s *KeeperTestSuite) TestCalcOutAmtGivenIn_NonMutative() {
 	// we only use fee cases here since write Ctx only takes effect in the fee accumulator
-	tests := makeSwapTests(swapOutGivenInFeeCases)
+	tests := makeTests(swapOutGivenInFeeCases)
 	for name, test := range tests {
 		test := test
 		s.Run(name, func() {
@@ -2241,7 +2241,7 @@ func (s *KeeperTestSuite) setupSecondPosition(test SwapTest, pool types.Concentr
 // TestCalcInAmtGivenOut_NonMutative tests that CalcInAmtGivenOut is non-mutative.
 func (s *KeeperTestSuite) TestCalcInAmtGivenOut_NonMutative() {
 	// we only use fee cases here since write Ctx only takes effect in the fee accumulator
-	tests := makeSwapTests(swapOutGivenInFeeCases)
+	tests := makeTests(swapOutGivenInFeeCases)
 
 	for name, test := range tests {
 		test := test
@@ -2267,7 +2267,7 @@ func (s *KeeperTestSuite) TestCalcInAmtGivenOut_NonMutative() {
 // TestComputeInAmtGivenOut tests that ComputeInAmtGivenOut successfully performs state changes as expected.
 func (s *KeeperTestSuite) TestComputeInAmtGivenOut() {
 	// we only use fee cases here since write Ctx only takes effect in the fee accumulator
-	tests := makeSwapTests(swapInGivenOutFeeTestCases)
+	tests := makeTests(swapInGivenOutFeeTestCases)
 
 	for name, test := range tests {
 		test := test
diff --git a/x/concentrated-liquidity/swapstrategy/export_test.go b/x/concentrated-liquidity/swapstrategy/export_test.go
index ef3ff64f6..755d89a9a 100644
--- a/x/concentrated-liquidity/swapstrategy/export_test.go
+++ b/x/concentrated-liquidity/swapstrategy/export_test.go
@@ -2,6 +2,8 @@ package swapstrategy
 
 import sdk "github.com/cosmos/cosmos-sdk/types"
 
+type SwapStrategy = swapStrategy
+
 func ComputeFeeChargePerSwapStepOutGivenIn(hasReachedTarget bool, amountIn, amountSpecifiedRemaining, spreadFactor sdk.Dec) sdk.Dec {
 	return computeFeeChargePerSwapStepOutGivenIn(hasReachedTarget, amountIn, amountSpecifiedRemaining, spreadFactor)
 }
diff --git a/x/concentrated-liquidity/swapstrategy/one_for_zero_test.go b/x/concentrated-liquidity/swapstrategy/one_for_zero_test.go
index 9c0585bdd..6cfe465ea 100644
--- a/x/concentrated-liquidity/swapstrategy/one_for_zero_test.go
+++ b/x/concentrated-liquidity/swapstrategy/one_for_zero_test.go
@@ -3,12 +3,16 @@ package swapstrategy_test
 import (
 	sdk "github.com/cosmos/cosmos-sdk/types"
 
-	cl "github.com/osmosis-labs/osmosis/v15/x/concentrated-liquidity"
 	"github.com/osmosis-labs/osmosis/v15/x/concentrated-liquidity/math"
 	"github.com/osmosis-labs/osmosis/v15/x/concentrated-liquidity/swapstrategy"
 	"github.com/osmosis-labs/osmosis/v15/x/concentrated-liquidity/types"
 )
 
+func (suite *StrategyTestSuite) setupNewOneForZeroSwapStrategy(sqrtPriceLimit sdk.Dec, spread sdk.Dec) swapstrategy.SwapStrategy {
+	suite.SetupTest()
+	return swapstrategy.New(false, sqrtPriceLimit, suite.App.GetKey(types.ModuleName), spread, defaultTickSpacing)
+}
+
 func (suite *StrategyTestSuite) TestGetSqrtTargetPrice_OneForZero() {
 	tests := map[string]struct {
 		sqrtPriceLimit    sdk.Dec
@@ -33,14 +37,9 @@ func (suite *StrategyTestSuite) TestGetSqrtTargetPrice_OneForZero() {
 	}
 
 	for name, tc := range tests {
-		tc := tc
 		suite.Run(name, func() {
-			suite.SetupTest()
-
-			strategy := swapstrategy.New(false, tc.sqrtPriceLimit, suite.App.GetKey(types.ModuleName), sdk.ZeroDec(), defaultTickSpacing)
-
+			strategy := suite.setupNewOneForZeroSwapStrategy(tc.sqrtPriceLimit, zero)
 			actualSqrtTargetPrice := strategy.GetSqrtTargetPrice(tc.nextTickSqrtPrice)
-
 			suite.Require().Equal(tc.expectedResult, actualSqrtTargetPrice)
 		})
 	}
@@ -153,9 +152,7 @@ func (suite *StrategyTestSuite) TestComputeSwapStepOutGivenIn_OneForZero() {
 	for name, tc := range tests {
 		tc := tc
 		suite.Run(name, func() {
-			suite.SetupTest()
-			strategy := swapstrategy.New(false, types.MaxSqrtPrice, suite.App.GetKey(types.ModuleName), tc.spreadFactor, defaultTickSpacing)
-
+			strategy := suite.setupNewOneForZeroSwapStrategy(types.MaxSqrtPrice, tc.spreadFactor)
 			sqrtPriceNext, amountInConsumed, amountZeroOut, feeChargeTotal := strategy.ComputeSwapStepOutGivenIn(tc.sqrtPriceCurrent, tc.sqrtPriceTarget, tc.liquidity, tc.amountOneInRemaining)
 
 			suite.Require().Equal(tc.expectedSqrtPriceNext, sqrtPriceNext)
@@ -170,6 +167,7 @@ func (suite *StrategyTestSuite) TestComputeSwapStepInGivenOut_OneForZero() {
 	var (
 		sqrtPriceCurrent = defaultSqrtPriceLower
 		sqrtPriceNext    = defaultSqrtPriceUpper
+		sqrtPriceTarget  = sqrtPriceNext
 		// Target is not reached means that we stop at the sqrt price earlier
 		// than expected. As a result, we recalculate the amount out and amount in
 		// necessary to reach the earlier target.
@@ -183,10 +181,8 @@ func (suite *StrategyTestSuite) TestComputeSwapStepInGivenOut_OneForZero() {
 		amountZeroTargetNotReached = sdk.MustNewDecFromStr("12369.999999999999293322")
 	)
 
+	// sqrtPriceCurrent, sqrtPriceTarget, liquidity are all set to defaults defined above.
 	tests := map[string]struct {
-		sqrtPriceCurrent       sdk.Dec
-		sqrtPriceTarget        sdk.Dec
-		liquidity              sdk.Dec
 		amountZeroOutRemaining sdk.Dec
 		spreadFactor           sdk.Dec
 
@@ -198,9 +194,6 @@ func (suite *StrategyTestSuite) TestComputeSwapStepInGivenOut_OneForZero() {
 		expectError error
 	}{
 		"1: no fee - reach target": {
-			sqrtPriceCurrent: sqrtPriceCurrent,
-			sqrtPriceTarget:  sqrtPriceNext,
-			liquidity:        defaultLiquidity,
 			// Add 100.
 			amountZeroOutRemaining: defaultAmountZero.Add(sdk.NewDec(100)),
 			spreadFactor:           sdk.ZeroDec(),
@@ -213,9 +206,6 @@ func (suite *StrategyTestSuite) TestComputeSwapStepInGivenOut_OneForZero() {
 			expectedFeeChargeTotal: sdk.ZeroDec(),
 		},
 		"2: no fee - do not reach target": {
-			sqrtPriceCurrent:       sqrtPriceCurrent,
-			sqrtPriceTarget:        sqrtPriceNext,
-			liquidity:              defaultLiquidity,
 			amountZeroOutRemaining: defaultAmountZero.Sub(sdk.NewDec(1000)),
 			spreadFactor:           sdk.ZeroDec(),
 
@@ -228,9 +218,6 @@ func (suite *StrategyTestSuite) TestComputeSwapStepInGivenOut_OneForZero() {
 			expectedFeeChargeTotal: sdk.ZeroDec(),
 		},
 		"3: 3% fee - reach target": {
-			sqrtPriceCurrent:       sqrtPriceCurrent,
-			sqrtPriceTarget:        sqrtPriceNext,
-			liquidity:              defaultLiquidity,
 			amountZeroOutRemaining: defaultAmountZero.Quo(sdk.OneDec().Sub(defaultFee)),
 			spreadFactor:           defaultFee,
 
@@ -240,9 +227,6 @@ func (suite *StrategyTestSuite) TestComputeSwapStepInGivenOut_OneForZero() {
 			expectedFeeChargeTotal:        swapstrategy.ComputeFeeChargeFromAmountIn(defaultAmountOne.Ceil(), defaultFee),
 		},
 		"4: 3% fee - do not reach target": {
-			sqrtPriceCurrent:       sqrtPriceCurrent,
-			sqrtPriceTarget:        sqrtPriceNext,
-			liquidity:              defaultLiquidity,
 			amountZeroOutRemaining: defaultAmountZero.Sub(sdk.NewDec(1000)),
 			spreadFactor:           defaultFee,
 
@@ -255,12 +239,9 @@ func (suite *StrategyTestSuite) TestComputeSwapStepInGivenOut_OneForZero() {
 	}
 
 	for name, tc := range tests {
-		tc := tc
 		suite.Run(name, func() {
-			suite.SetupTest()
-			strategy := swapstrategy.New(false, types.MaxSqrtPrice, suite.App.GetKey(types.ModuleName), tc.spreadFactor, defaultTickSpacing)
-
-			sqrtPriceNext, amountZeroOutConsumed, amountOneIn, feeChargeTotal := strategy.ComputeSwapStepInGivenOut(tc.sqrtPriceCurrent, tc.sqrtPriceTarget, tc.liquidity, tc.amountZeroOutRemaining)
+			strategy := suite.setupNewOneForZeroSwapStrategy(types.MaxSqrtPrice, tc.spreadFactor)
+			sqrtPriceNext, amountZeroOutConsumed, amountOneIn, feeChargeTotal := strategy.ComputeSwapStepInGivenOut(sqrtPriceCurrent, sqrtPriceTarget, defaultLiquidity, tc.amountZeroOutRemaining)
 
 			suite.Require().Equal(tc.expectedSqrtPriceNext, sqrtPriceNext)
 			suite.Require().Equal(tc.expectedAmountZeroOutConsumed, amountZeroOutConsumed)
@@ -271,14 +252,7 @@ func (suite *StrategyTestSuite) TestComputeSwapStepInGivenOut_OneForZero() {
 }
 
 func (suite *StrategyTestSuite) TestInitializeNextTickIterator_OneForZero() {
-	tests := map[string]struct {
-		currentTick     int64
-		preSetPositions []position
-
-		expectIsValid  bool
-		expectNextTick int64
-		expectError    error
-	}{
+	tests := map[string]tickIteratorTest{
 		"1 position, one for zero": {
 			preSetPositions: []position{
 				{
@@ -328,53 +302,14 @@ func (suite *StrategyTestSuite) TestInitializeNextTickIterator_OneForZero() {
 			expectNextTick: 100,
 		},
 		"no ticks, one for zero": {
-			preSetPositions: []position{},
-			expectIsValid:   false,
+			expectIsValid: false,
 		},
 	}
 
 	for name, tc := range tests {
-		tc := tc
 		suite.Run(name, func() {
-			suite.SetupTest()
-			strategy := swapstrategy.New(false, types.MaxSqrtPrice, suite.App.GetKey(types.ModuleName), sdk.ZeroDec(), defaultTickSpacing)
-
-			pool := suite.PrepareConcentratedPool()
-
-			clMsgServer := cl.NewMsgServerImpl(suite.App.ConcentratedLiquidityKeeper)
-
-			for _, pos := range tc.preSetPositions {
-				suite.FundAcc(suite.TestAccs[0], DefaultCoins.Add(DefaultCoins...))
-				_, err := clMsgServer.CreatePosition(sdk.WrapSDKContext(suite.Ctx), &types.MsgCreatePosition{
-					PoolId:          pool.GetId(),
-					Sender:          suite.TestAccs[0].String(),
-					LowerTick:       pos.lowerTick,
-					UpperTick:       pos.upperTick,
-					TokensProvided:  DefaultCoins.Add(sdk.NewCoin(USDC, sdk.OneInt())),
-					TokenMinAmount0: sdk.ZeroInt(),
-					TokenMinAmount1: sdk.ZeroInt(),
-				})
-				suite.Require().NoError(err)
-			}
-
-			// refetch pool
-			pool, err := suite.App.ConcentratedLiquidityKeeper.GetConcentratedPoolById(suite.Ctx, pool.GetId())
-			suite.Require().NoError(err)
-
-			currentTick := pool.GetCurrentTick()
-			suite.Require().Equal(int64(0), currentTick)
-
-			tickIndex := strategy.InitializeTickValue(currentTick)
-
-			iter := strategy.InitializeNextTickIterator(suite.Ctx, defaultPoolId, tickIndex)
-			defer iter.Close()
-
-			suite.Require().Equal(tc.expectIsValid, iter.Valid())
-			if tc.expectIsValid {
-				actualNextTick, err := types.TickIndexFromBytes(iter.Key())
-				suite.Require().NoError(err)
-				suite.Require().Equal(tc.expectNextTick, actualNextTick)
-			}
+			strategy := suite.setupNewOneForZeroSwapStrategy(types.MaxSqrtPrice, zero)
+			suite.runTickIteratorTest(strategy, tc)
 		})
 	}
 }
diff --git a/x/concentrated-liquidity/swapstrategy/swap_strategy_test.go b/x/concentrated-liquidity/swapstrategy/swap_strategy_test.go
index bc9833871..c77c1ddf8 100644
--- a/x/concentrated-liquidity/swapstrategy/swap_strategy_test.go
+++ b/x/concentrated-liquidity/swapstrategy/swap_strategy_test.go
@@ -9,6 +9,7 @@ import (
 
 	"github.com/osmosis-labs/osmosis/osmomath"
 	"github.com/osmosis-labs/osmosis/v15/app/apptesting"
+	cl "github.com/osmosis-labs/osmosis/v15/x/concentrated-liquidity"
 	"github.com/osmosis-labs/osmosis/v15/x/concentrated-liquidity/swapstrategy"
 	"github.com/osmosis-labs/osmosis/v15/x/concentrated-liquidity/types"
 )
@@ -30,12 +31,15 @@ const (
 )
 
 var (
+	zero                  = sdk.NewDec(0)
+	one                   = sdk.NewDec(1)
 	two                   = sdk.NewDec(2)
-	three                 = sdk.NewDec(2)
+	three                 = sdk.NewDec(3)
 	four                  = sdk.NewDec(4)
 	five                  = sdk.NewDec(5)
+	sqrt5000              = sdk.MustNewDecFromStr("70.710678118654752440") // 5000
 	defaultSqrtPriceLower = sdk.MustNewDecFromStr("70.688664163408836321") // approx 4996.89
-	defaultSqrtPriceUpper = sdk.MustNewDecFromStr("70.710678118654752440") // 5000
+	defaultSqrtPriceUpper = sqrt5000
 	defaultAmountOne      = sdk.MustNewDecFromStr("66829187.967824033199646915")
 	defaultAmountZero     = sdk.MustNewDecFromStr("13369.999999999998920002")
 	defaultLiquidity      = sdk.MustNewDecFromStr("3035764687.503020836176699298")
@@ -53,6 +57,56 @@ func (suite *StrategyTestSuite) SetupTest() {
 	suite.Setup()
 }
 
+type tickIteratorTest struct {
+	currentTick     int64
+	preSetPositions []position
+
+	expectIsValid  bool
+	expectNextTick int64
+	expectError    error
+}
+
+func (suite *StrategyTestSuite) runTickIteratorTest(strategy swapstrategy.SwapStrategy, tc tickIteratorTest) {
+	pool := suite.PrepareConcentratedPool()
+	suite.setupPresetPositions(pool.GetId(), tc.preSetPositions)
+
+	// refetch pool
+	pool, err := suite.App.ConcentratedLiquidityKeeper.GetConcentratedPoolById(suite.Ctx, pool.GetId())
+	suite.Require().NoError(err)
+
+	currentTick := pool.GetCurrentTick()
+	suite.Require().Equal(int64(0), currentTick)
+
+	tickIndex := strategy.InitializeTickValue(currentTick)
+
+	iter := strategy.InitializeNextTickIterator(suite.Ctx, defaultPoolId, tickIndex)
+	defer iter.Close()
+
+	suite.Require().Equal(tc.expectIsValid, iter.Valid())
+	if tc.expectIsValid {
+		actualNextTick, err := types.TickIndexFromBytes(iter.Key())
+		suite.Require().NoError(err)
+		suite.Require().Equal(tc.expectNextTick, actualNextTick)
+	}
+}
+
+func (suite *StrategyTestSuite) setupPresetPositions(poolId uint64, positions []position) {
+	clMsgServer := cl.NewMsgServerImpl(suite.App.ConcentratedLiquidityKeeper)
+	for _, pos := range positions {
+		suite.FundAcc(suite.TestAccs[0], DefaultCoins.Add(DefaultCoins...))
+		_, err := clMsgServer.CreatePosition(sdk.WrapSDKContext(suite.Ctx), &types.MsgCreatePosition{
+			PoolId:          poolId,
+			Sender:          suite.TestAccs[0].String(),
+			LowerTick:       pos.lowerTick,
+			UpperTick:       pos.upperTick,
+			TokensProvided:  DefaultCoins.Add(sdk.NewCoin(USDC, sdk.OneInt())),
+			TokenMinAmount0: sdk.ZeroInt(),
+			TokenMinAmount1: sdk.ZeroInt(),
+		})
+		suite.Require().NoError(err)
+	}
+}
+
 // TestComputeSwapState_Inverse validates that out given in and in given out compute swap steps
 // for one strategy produce the same results as the other given inverse inputs.
 // That is, if we swap in A of token0 and expect to get out B of token 1,
@@ -84,7 +138,7 @@ func (suite *StrategyTestSuite) TestComputeSwapState_Inverse() {
 		expectedAmountOut               sdk.Dec
 	}{
 		"1: one_for_zero__not_equal_target__no_fee": {
-			sqrtPriceCurrent: sdk.MustNewDecFromStr("70.710678118654752440"), // 5000
+			sqrtPriceCurrent: sqrt5000,                                       // 5000
 			sqrtPriceTarget:  sdk.MustNewDecFromStr("70.724818840347693039"), // 5002
 			liquidity:        sdk.MustNewDecFromStr("3035764687.503020836176699298"),
 			amountIn:         sdk.NewDec(42000000),
@@ -101,7 +155,7 @@ func (suite *StrategyTestSuite) TestComputeSwapState_Inverse() {
 			expectedAmountOut: sdk.NewDec(8398),
 		},
 		"2: zero_for_one__not_equal_target__no_fee": {
-			sqrtPriceCurrent: sdk.MustNewDecFromStr("70.710678118654752440"), // 5000
+			sqrtPriceCurrent: sqrt5000,                                       // 5000
 			sqrtPriceTarget:  sdk.MustNewDecFromStr("70.682388188289167342"), // 4996
 			liquidity:        sdk.MustNewDecFromStr("3035764687.503020836176699298"),
 			amountIn:         sdk.NewDec(13370),
@@ -119,7 +173,7 @@ func (suite *StrategyTestSuite) TestComputeSwapState_Inverse() {
 			expectedAmountOut: sdk.NewDec(66829187),
 		},
 		"3: one_for_zero__equal_target__no_fee": {
-			sqrtPriceCurrent: sdk.MustNewDecFromStr("70.710678118654752440"), // 5000
+			sqrtPriceCurrent: sqrt5000,                                       // 5000
 			sqrtPriceTarget:  sdk.MustNewDecFromStr("70.724513183069625078"), // approx 5001.96
 			liquidity:        sdk.MustNewDecFromStr("3035764687.503020836176699298"),
 			amountIn:         sdk.NewDec(42000000),
@@ -136,7 +190,7 @@ func (suite *StrategyTestSuite) TestComputeSwapState_Inverse() {
 			expectedAmountOut: sdk.NewDec(8398),
 		},
 		"4: zero_for_one__equal_target__no_fee": {
-			sqrtPriceCurrent: sdk.MustNewDecFromStr("70.710678118654752440"), // 5000
+			sqrtPriceCurrent: sqrt5000,                                       // 5000
 			sqrtPriceTarget:  sdk.MustNewDecFromStr("70.688664163408836320"), // approx 4996.89
 			liquidity:        sdk.MustNewDecFromStr("3035764687.503020836176699298"),
 			amountIn:         sdk.NewDec(13370),
@@ -198,7 +252,6 @@ func (suite *StrategyTestSuite) TestGetPriceLimit() {
 	}
 
 	for name, tc := range tests {
-		tc := tc
 		suite.Run(name, func() {
 			priceLimit := swapstrategy.GetPriceLimit(tc.zeroForOne)
 			suite.Require().Equal(tc.expected, priceLimit)
diff --git a/x/concentrated-liquidity/swapstrategy/zero_for_one_test.go b/x/concentrated-liquidity/swapstrategy/zero_for_one_test.go
index f83519475..d91cd4dc7 100644
--- a/x/concentrated-liquidity/swapstrategy/zero_for_one_test.go
+++ b/x/concentrated-liquidity/swapstrategy/zero_for_one_test.go
@@ -3,19 +3,16 @@ package swapstrategy_test
 import (
 	sdk "github.com/cosmos/cosmos-sdk/types"
 
-	cl "github.com/osmosis-labs/osmosis/v15/x/concentrated-liquidity"
 	"github.com/osmosis-labs/osmosis/v15/x/concentrated-liquidity/swapstrategy"
 	"github.com/osmosis-labs/osmosis/v15/x/concentrated-liquidity/types"
 )
 
-func (suite *StrategyTestSuite) TestGetSqrtTargetPrice_ZeroForOne() {
-	var (
-		two   = sdk.NewDec(2)
-		three = sdk.NewDec(2)
-		four  = sdk.NewDec(4)
-		five  = sdk.NewDec(5)
-	)
+func (suite *StrategyTestSuite) setupNewZeroForOneSwapStrategy(sqrtPriceLimit sdk.Dec, spread sdk.Dec) swapstrategy.SwapStrategy {
+	suite.SetupTest()
+	return swapstrategy.New(true, sqrtPriceLimit, suite.App.GetKey(types.ModuleName), spread, defaultTickSpacing)
+}
 
+func (suite *StrategyTestSuite) TestGetSqrtTargetPrice_ZeroForOne() {
 	tests := map[string]struct {
 		isZeroForOne      bool
 		sqrtPriceLimit    sdk.Dec
@@ -42,12 +39,8 @@ func (suite *StrategyTestSuite) TestGetSqrtTargetPrice_ZeroForOne() {
 	for name, tc := range tests {
 		tc := tc
 		suite.Run(name, func() {
-			suite.SetupTest()
-
-			sut := swapstrategy.New(true, tc.sqrtPriceLimit, suite.App.GetKey(types.ModuleName), sdk.ZeroDec(), defaultTickSpacing)
-
+			sut := suite.setupNewZeroForOneSwapStrategy(tc.sqrtPriceLimit, zero)
 			actualSqrtTargetPrice := sut.GetSqrtTargetPrice(tc.nextTickSqrtPrice)
-
 			suite.Require().Equal(tc.expectedResult, actualSqrtTargetPrice)
 		})
 	}
@@ -57,6 +50,7 @@ func (suite *StrategyTestSuite) TestComputeSwapStepOutGivenIn_ZeroForOne() {
 	var (
 		sqrtPriceCurrent = defaultSqrtPriceUpper
 		sqrtPriceNext    = defaultSqrtPriceLower
+		sqrtPriceTarget  = sqrtPriceNext
 
 		// liquidity * sqrtPriceCurrent / (liquidity + amount in * sqrtPriceCurrent)
 		sqrtPriceTargetNotReached = sdk.MustNewDecFromStr("70.688828764403676330")
@@ -64,10 +58,8 @@ func (suite *StrategyTestSuite) TestComputeSwapStepOutGivenIn_ZeroForOne() {
 		amountOneTargetNotReached = sdk.MustNewDecFromStr("66329498.080160866932624794")
 	)
 
+	// sqrtPriceCurrent, sqrtPriceTarget, liquidity are all set to defaults defined above.
 	tests := map[string]struct {
-		sqrtPriceCurrent      sdk.Dec
-		sqrtPriceTarget       sdk.Dec
-		liquidity             sdk.Dec
 		amountZeroInRemaining sdk.Dec
 		spreadFactor          sdk.Dec
 
@@ -79,9 +71,6 @@ func (suite *StrategyTestSuite) TestComputeSwapStepOutGivenIn_ZeroForOne() {
 		expectError error
 	}{
 		"1: no fee - reach target": {
-			sqrtPriceCurrent: sqrtPriceCurrent,
-			sqrtPriceTarget:  sqrtPriceNext,
-			liquidity:        defaultLiquidity,
 			// add 100 more
 			amountZeroInRemaining: defaultAmountZero.Add(sdk.NewDec(100)),
 			spreadFactor:          sdk.ZeroDec(),
@@ -94,9 +83,6 @@ func (suite *StrategyTestSuite) TestComputeSwapStepOutGivenIn_ZeroForOne() {
 			expectedFeeChargeTotal: sdk.ZeroDec(),
 		},
 		"2: no fee - do not reach target": {
-			sqrtPriceCurrent:      sqrtPriceCurrent,
-			sqrtPriceTarget:       sqrtPriceNext,
-			liquidity:             defaultLiquidity,
 			amountZeroInRemaining: defaultAmountZero.Sub(sdk.NewDec(100)),
 			spreadFactor:          sdk.ZeroDec(),
 
@@ -107,11 +93,8 @@ func (suite *StrategyTestSuite) TestComputeSwapStepOutGivenIn_ZeroForOne() {
 			expectedFeeChargeTotal: sdk.ZeroDec(),
 		},
 		"3: 3% fee - reach target": {
-			sqrtPriceCurrent: sqrtPriceCurrent,
-			sqrtPriceTarget:  sqrtPriceNext,
-			liquidity:        defaultLiquidity,
 			// add 100 more
-			amountZeroInRemaining: defaultAmountZero.Add(sdk.NewDec(100)).Quo(sdk.OneDec().Sub(defaultFee)),
+			amountZeroInRemaining: defaultAmountZero.Add(sdk.NewDec(100)).Quo(one.Sub(defaultFee)),
 			spreadFactor:          defaultFee,
 
 			expectedSqrtPriceNext: sqrtPriceNext,
@@ -119,30 +102,24 @@ func (suite *StrategyTestSuite) TestComputeSwapStepOutGivenIn_ZeroForOne() {
 			amountZeroInConsumed: defaultAmountZero.Ceil(),
 			// liquidity * (sqrtPriceNext - sqrtPriceCurrent)
 			expectedAmountOneOut:   defaultAmountOne,
-			expectedFeeChargeTotal: defaultAmountZero.Ceil().Quo(sdk.OneDec().Sub(defaultFee)).Mul(defaultFee),
+			expectedFeeChargeTotal: defaultAmountZero.Ceil().Quo(one.Sub(defaultFee)).Mul(defaultFee),
 		},
 		"4: 3% fee - do not reach target": {
-			sqrtPriceCurrent:      sqrtPriceCurrent,
-			sqrtPriceTarget:       sqrtPriceNext,
-			liquidity:             defaultLiquidity,
-			amountZeroInRemaining: defaultAmountZero.Sub(sdk.NewDec(100)).Quo(sdk.OneDec().Sub(defaultFee)),
+			amountZeroInRemaining: defaultAmountZero.Sub(sdk.NewDec(100)).Quo(one.Sub(defaultFee)),
 			spreadFactor:          defaultFee,
 
 			expectedSqrtPriceNext: sqrtPriceTargetNotReached,
 			amountZeroInConsumed:  defaultAmountZero.Sub(sdk.NewDec(100)).Ceil(),
 			expectedAmountOneOut:  amountOneTargetNotReached,
 			// Difference between amount in given and actually consumed.
-			expectedFeeChargeTotal: defaultAmountZero.Sub(sdk.NewDec(100)).Quo(sdk.OneDec().Sub(defaultFee)).Sub(defaultAmountZero.Sub(sdk.NewDec(100)).Ceil()),
+			expectedFeeChargeTotal: defaultAmountZero.Sub(sdk.NewDec(100)).Quo(one.Sub(defaultFee)).Sub(defaultAmountZero.Sub(sdk.NewDec(100)).Ceil()),
 		},
 	}
 
 	for name, tc := range tests {
-		tc := tc
 		suite.Run(name, func() {
-			suite.SetupTest()
-			strategy := swapstrategy.New(true, types.MaxSqrtPrice, suite.App.GetKey(types.ModuleName), tc.spreadFactor, defaultTickSpacing)
-
-			sqrtPriceNext, amountZeroIn, amountOneOut, feeChargeTotal := strategy.ComputeSwapStepOutGivenIn(tc.sqrtPriceCurrent, tc.sqrtPriceTarget, tc.liquidity, tc.amountZeroInRemaining)
+			strategy := suite.setupNewZeroForOneSwapStrategy(types.MaxSqrtPrice, tc.spreadFactor)
+			sqrtPriceNext, amountZeroIn, amountOneOut, feeChargeTotal := strategy.ComputeSwapStepOutGivenIn(sqrtPriceCurrent, sqrtPriceTarget, defaultLiquidity, tc.amountZeroInRemaining)
 
 			suite.Require().Equal(tc.expectedSqrtPriceNext, sqrtPriceNext)
 			suite.Require().Equal(tc.amountZeroInConsumed, amountZeroIn)
@@ -156,6 +133,7 @@ func (suite *StrategyTestSuite) TestComputeSwapStepInGivenOut_ZeroForOne() {
 	var (
 		sqrtPriceCurrent = defaultSqrtPriceUpper
 		sqrtPriceNext    = defaultSqrtPriceLower
+		sqrtPriceTarget  = sqrtPriceNext
 
 		// sqrt_cur - amt_one / liq quo round up
 		sqrtPriceTargetNotReached = sdk.MustNewDecFromStr("70.688667457471792243")
@@ -168,10 +146,8 @@ func (suite *StrategyTestSuite) TestComputeSwapStepInGivenOut_ZeroForOne() {
 		amountOneOutTargetNotReached = sdk.MustNewDecFromStr("66819187.967824033372217995")
 	)
 
+	// sqrtPriceCurrent, sqrtPriceTarget, liquidity are all set to defaults defined above.
 	tests := map[string]struct {
-		sqrtPriceCurrent      sdk.Dec
-		sqrtPriceTarget       sdk.Dec
-		liquidity             sdk.Dec
 		amountOneOutRemaining sdk.Dec
 		spreadFactor          sdk.Dec
 
@@ -183,39 +159,30 @@ func (suite *StrategyTestSuite) TestComputeSwapStepInGivenOut_ZeroForOne() {
 		expectError error
 	}{
 		"1: no fee - reach target": {
-			sqrtPriceCurrent: sqrtPriceCurrent,
-			sqrtPriceTarget:  sqrtPriceNext,
-			liquidity:        defaultLiquidity,
 			// Add 100.
 			amountOneOutRemaining: defaultAmountOne.Add(sdk.NewDec(100)),
-			spreadFactor:          sdk.ZeroDec(),
+			spreadFactor:          zero,
 
 			expectedSqrtPriceNext: sqrtPriceNext,
 			// Consumes without 100 since reaches target.
 			amountOneOutConsumed:   defaultAmountOne,
 			expectedAmountInZero:   defaultAmountZero.Ceil(),
-			expectedFeeChargeTotal: sdk.ZeroDec(),
+			expectedFeeChargeTotal: zero,
 		},
 		"2: no fee - do not reach target": {
-			sqrtPriceCurrent:      sqrtPriceCurrent,
-			sqrtPriceTarget:       sqrtPriceNext,
-			liquidity:             defaultLiquidity,
 			amountOneOutRemaining: defaultAmountOne.Sub(sdk.NewDec(10000)),
-			spreadFactor:          sdk.ZeroDec(),
+			spreadFactor:          zero,
 
 			// sqrt_cur - amt_one / liq quo round up
 			expectedSqrtPriceNext: sqrtPriceTargetNotReached,
 			// subtracting 1 * smallest dec to account for truncations in favor of the pool.
 			amountOneOutConsumed:   amountOneOutTargetNotReached.Sub(sdk.SmallestDec()),
 			expectedAmountInZero:   amountZeroTargetNotReached.Ceil(),
-			expectedFeeChargeTotal: sdk.ZeroDec(),
+			expectedFeeChargeTotal: zero,
 		},
 		"3: 3% fee - reach target": {
-			sqrtPriceCurrent: sqrtPriceCurrent,
-			sqrtPriceTarget:  sqrtPriceNext,
-			liquidity:        defaultLiquidity,
 			// Add 100.
-			amountOneOutRemaining: defaultAmountOne.Quo(sdk.OneDec().Sub(defaultFee)),
+			amountOneOutRemaining: defaultAmountOne.Quo(one.Sub(defaultFee)),
 			spreadFactor:          defaultFee,
 
 			expectedSqrtPriceNext: sqrtPriceNext,
@@ -226,9 +193,6 @@ func (suite *StrategyTestSuite) TestComputeSwapStepInGivenOut_ZeroForOne() {
 			expectedFeeChargeTotal: swapstrategy.ComputeFeeChargeFromAmountIn(defaultAmountZero.Ceil(), defaultFee),
 		},
 		"4: 3% fee - do not reach target": {
-			sqrtPriceCurrent:      sqrtPriceCurrent,
-			sqrtPriceTarget:       sqrtPriceNext,
-			liquidity:             defaultLiquidity,
 			amountOneOutRemaining: defaultAmountOne.Sub(sdk.NewDec(10000)),
 			spreadFactor:          defaultFee,
 
@@ -241,12 +205,9 @@ func (suite *StrategyTestSuite) TestComputeSwapStepInGivenOut_ZeroForOne() {
 	}
 
 	for name, tc := range tests {
-		tc := tc
 		suite.Run(name, func() {
-			suite.SetupTest()
-			strategy := swapstrategy.New(true, types.MaxSqrtPrice, suite.App.GetKey(types.ModuleName), tc.spreadFactor, defaultTickSpacing)
-
-			sqrtPriceNext, amountOneOut, amountZeroIn, feeChargeTotal := strategy.ComputeSwapStepInGivenOut(tc.sqrtPriceCurrent, tc.sqrtPriceTarget, tc.liquidity, tc.amountOneOutRemaining)
+			strategy := suite.setupNewZeroForOneSwapStrategy(types.MaxSqrtPrice, tc.spreadFactor)
+			sqrtPriceNext, amountOneOut, amountZeroIn, feeChargeTotal := strategy.ComputeSwapStepInGivenOut(sqrtPriceCurrent, sqrtPriceTarget, defaultLiquidity, tc.amountOneOutRemaining)
 
 			suite.Require().Equal(tc.expectedSqrtPriceNext, sqrtPriceNext)
 			suite.Require().Equal(tc.amountOneOutConsumed, amountOneOut)
@@ -257,14 +218,7 @@ func (suite *StrategyTestSuite) TestComputeSwapStepInGivenOut_ZeroForOne() {
 }
 
 func (suite *StrategyTestSuite) TestInitializeNextTickIterator_ZeroForOne() {
-	tests := map[string]struct {
-		currentTick     int64
-		preSetPositions []position
-
-		expectIsValid  bool
-		expectNextTick int64
-		expectError    error
-	}{
+	tests := map[string]tickIteratorTest{
 		"1 position, zero for one": {
 			preSetPositions: []position{
 				{
@@ -310,53 +264,15 @@ func (suite *StrategyTestSuite) TestInitializeNextTickIterator_ZeroForOne() {
 			expectNextTick: 0,
 		},
 		"no ticks, zero for one": {
-			preSetPositions: []position{},
-			expectIsValid:   false,
+			expectIsValid: false,
 		},
 	}
 
 	for name, tc := range tests {
 		tc := tc
 		suite.Run(name, func() {
-			suite.SetupTest()
-			strategy := swapstrategy.New(true, types.MaxSqrtPrice, suite.App.GetKey(types.ModuleName), sdk.ZeroDec(), defaultTickSpacing)
-
-			pool := suite.PrepareConcentratedPool()
-
-			clMsgServer := cl.NewMsgServerImpl(suite.App.ConcentratedLiquidityKeeper)
-
-			for _, pos := range tc.preSetPositions {
-				suite.FundAcc(suite.TestAccs[0], DefaultCoins.Add(DefaultCoins...))
-				_, err := clMsgServer.CreatePosition(sdk.WrapSDKContext(suite.Ctx), &types.MsgCreatePosition{
-					PoolId:          pool.GetId(),
-					Sender:          suite.TestAccs[0].String(),
-					LowerTick:       pos.lowerTick,
-					UpperTick:       pos.upperTick,
-					TokensProvided:  DefaultCoins.Add(sdk.NewCoin(USDC, sdk.OneInt())),
-					TokenMinAmount0: sdk.ZeroInt(),
-					TokenMinAmount1: sdk.ZeroInt(),
-				})
-				suite.Require().NoError(err)
-			}
-
-			// refetch pool
-			pool, err := suite.App.ConcentratedLiquidityKeeper.GetConcentratedPoolById(suite.Ctx, pool.GetId())
-			suite.Require().NoError(err)
-
-			currentTick := pool.GetCurrentTick()
-			suite.Require().Equal(int64(0), currentTick)
-
-			tickIndex := strategy.InitializeTickValue(currentTick)
-
-			iter := strategy.InitializeNextTickIterator(suite.Ctx, defaultPoolId, tickIndex)
-			defer iter.Close()
-
-			suite.Require().Equal(tc.expectIsValid, iter.Valid())
-			if tc.expectIsValid {
-				actualNextTick, err := types.TickIndexFromBytes(iter.Key())
-				suite.Require().NoError(err)
-				suite.Require().Equal(tc.expectNextTick, actualNextTick)
-			}
+			strategy := suite.setupNewZeroForOneSwapStrategy(types.MaxSqrtPrice, zero)
+			suite.runTickIteratorTest(strategy, tc)
 		})
 	}
 }
diff --git a/x/concentrated-liquidity/tick_test.go b/x/concentrated-liquidity/tick_test.go
index 8e95e6d22..51d82c24e 100644
--- a/x/concentrated-liquidity/tick_test.go
+++ b/x/concentrated-liquidity/tick_test.go
@@ -1397,7 +1397,6 @@ func (s *KeeperTestSuite) TestGetAllInitializedTicksForPool() {
 
 			// System Under Test
 			ticks, err := s.App.ConcentratedLiquidityKeeper.GetAllInitializedTicksForPool(s.Ctx, defaultPoolId)
-
 			s.Require().NoError(err)
 
 			s.Require().Equal(len(expectedTicks), len(ticks))
diff --git a/x/concentrated-liquidity/types/msgs_test.go b/x/concentrated-liquidity/types/msgs_test.go
index a1aa02c26..8a0a258c7 100644
--- a/x/concentrated-liquidity/types/msgs_test.go
+++ b/x/concentrated-liquidity/types/msgs_test.go
@@ -14,12 +14,36 @@ import (
 	"github.com/osmosis-labs/osmosis/v15/x/concentrated-liquidity/types"
 )
 
-func TestMsgCreatePosition(t *testing.T) {
+type extMsg interface {
+	sdk.Msg
+	Route() string
+	Type() string
+}
+
+var addr1 string
+var invalidAddr sdk.AccAddress
+
+func init() {
 	appParams.SetAddressPrefixes()
 	pk1 := ed25519.GenPrivKey().PubKey()
-	addr1 := sdk.AccAddress(pk1.Address()).String()
-	invalidAddr := sdk.AccAddress("invalid")
+	addr1 = sdk.AccAddress(pk1.Address()).String()
+	invalidAddr = sdk.AccAddress("invalid")
+}
 
+func runValidateBasicTest(t *testing.T, name string, msg extMsg, expectPass bool, expType string) {
+	if expectPass {
+		require.NoError(t, msg.ValidateBasic(), "test: %v", name)
+		require.Equal(t, msg.Route(), types.RouterKey)
+		require.Equal(t, msg.Type(), expType)
+		signers := msg.GetSigners()
+		require.Equal(t, len(signers), 1)
+		require.Equal(t, signers[0].String(), addr1)
+	} else {
+		require.Error(t, msg.ValidateBasic(), "test: %v", name)
+	}
+}
+
+func TestMsgCreatePosition(t *testing.T) {
 	tests := []struct {
 		name       string
 		msg        types.MsgCreatePosition
@@ -132,29 +156,12 @@ func TestMsgCreatePosition(t *testing.T) {
 	}
 
 	for _, test := range tests {
-		msg := test.msg
-
-		if test.expectPass {
-			require.NoError(t, test.msg.ValidateBasic(), "test: %v", test.name)
-			require.Equal(t, msg.Route(), types.RouterKey)
-			require.Equal(t, msg.Type(), types.TypeMsgCreatePosition)
-			signers := msg.GetSigners()
-			require.Equal(t, len(signers), 1)
-			require.Equal(t, signers[0].String(), addr1)
-		} else {
-			require.Error(t, test.msg.ValidateBasic(), "test: %v", test.name)
-		}
+		runValidateBasicTest(t, test.name, &test.msg, test.expectPass, types.TypeMsgCreatePosition)
 	}
 }
 
 func TestMsgFungifyChargedPositions(t *testing.T) {
-	appParams.SetAddressPrefixes()
-	var (
-		pk1              = ed25519.GenPrivKey().PubKey()
-		addr1            = sdk.AccAddress(pk1.Address()).String()
-		invalidAddr      = sdk.AccAddress("invalid")
-		validPositionIds = []uint64{1, 2}
-	)
+	var validPositionIds = []uint64{1, 2}
 
 	tests := []struct {
 		name       string
@@ -186,29 +193,12 @@ func TestMsgFungifyChargedPositions(t *testing.T) {
 			expectPass: false,
 		},
 	}
-
 	for _, test := range tests {
-		msg := test.msg
-
-		if test.expectPass {
-			require.NoError(t, test.msg.ValidateBasic(), "test: %v", test.name)
-			require.Equal(t, msg.Route(), types.RouterKey)
-			require.Equal(t, msg.Type(), types.TypeMsgFungifyChargedPositions)
-			signers := msg.GetSigners()
-			require.Equal(t, len(signers), 1)
-			require.Equal(t, signers[0].String(), addr1)
-		} else {
-			require.Error(t, test.msg.ValidateBasic(), "test: %v", test.name)
-		}
+		runValidateBasicTest(t, test.name, &test.msg, test.expectPass, types.TypeMsgFungifyChargedPositions)
 	}
 }
 
 func TestMsgWithdrawPosition(t *testing.T) {
-	appParams.SetAddressPrefixes()
-	pk1 := ed25519.GenPrivKey().PubKey()
-	addr1 := sdk.AccAddress(pk1.Address()).String()
-	invalidAddr := sdk.AccAddress("invalid")
-
 	tests := []struct {
 		name       string
 		msg        types.MsgWithdrawPosition
@@ -233,26 +223,12 @@ func TestMsgWithdrawPosition(t *testing.T) {
 			expectPass: false,
 		},
 	}
-
 	for _, test := range tests {
-		msg := test.msg
-
-		if test.expectPass {
-			require.NoError(t, test.msg.ValidateBasic(), "test: %v", test.name)
-			require.Equal(t, msg.Route(), types.RouterKey)
-			require.Equal(t, msg.Type(), types.TypeMsgWithdrawPosition)
-			signers := msg.GetSigners()
-			require.Equal(t, len(signers), 1)
-			require.Equal(t, signers[0].String(), addr1)
-		} else {
-			require.Error(t, test.msg.ValidateBasic(), "test: %v", test.name)
-		}
+		runValidateBasicTest(t, test.name, &test.msg, test.expectPass, types.TypeMsgWithdrawPosition)
 	}
 }
 
 func TestConcentratedLiquiditySerialization(t *testing.T) {
-	pk1 := ed25519.GenPrivKey().PubKey()
-	addr1 := sdk.AccAddress(pk1.Address()).String()
 	defaultPoolId := uint64(1)
 
 	testCases := []struct {
diff --git a/x/poolmanager/msg_server_test.go b/x/poolmanager/msg_server_test.go
new file mode 100644
index 000000000..ad5eb0563
--- /dev/null
+++ b/x/poolmanager/msg_server_test.go
@@ -0,0 +1,198 @@
+package poolmanager_test
+
+import (
+	sdk "github.com/cosmos/cosmos-sdk/types"
+
+	poolmanagerKeeper "github.com/osmosis-labs/osmosis/v15/x/poolmanager"
+	"github.com/osmosis-labs/osmosis/v15/x/poolmanager/types"
+)
+
+var (
+	amount     = sdk.NewInt(100)
+	min_amount = sdk.ZeroInt()
+	max_amount = sdk.NewInt(10000000)
+
+	pool1_in = types.SwapAmountInRoute{PoolId: 1, TokenOutDenom: "bar"}
+	pool2_in = types.SwapAmountInRoute{PoolId: 2, TokenOutDenom: "baz"}
+	pool3_in = types.SwapAmountInRoute{PoolId: 3, TokenOutDenom: "uosmo"}
+	pool4_in = types.SwapAmountInRoute{PoolId: 4, TokenOutDenom: "baz"}
+
+	pool1_out = types.SwapAmountOutRoute{PoolId: 1, TokenInDenom: "bar"}
+	pool2_out = types.SwapAmountOutRoute{PoolId: 2, TokenInDenom: "baz"}
+	pool3_out = types.SwapAmountOutRoute{PoolId: 3, TokenInDenom: "bar"}
+	pool4_out = types.SwapAmountOutRoute{PoolId: 4, TokenInDenom: "baz"}
+)
+
+func (s *KeeperTestSuite) TestSplitRouteSwapExactAmountIn() {
+	testcases := map[string]struct {
+		routes            []types.SwapAmountInSplitRoute
+		tokenInDenom      string
+		tokenoutMinAmount sdk.Int
+
+		expectedSplitRouteSwapEvent int
+		expectedMessageEvents       int
+		expectedError               bool
+	}{
+		"valid case: two routes": {
+			routes: []types.SwapAmountInSplitRoute{
+				{
+					Pools:         []types.SwapAmountInRoute{pool1_in, pool2_in},
+					TokenInAmount: amount,
+				},
+				{
+					Pools:         []types.SwapAmountInRoute{pool3_in, pool4_in},
+					TokenInAmount: amount,
+				},
+			},
+			tokenInDenom:      "baz",
+			tokenoutMinAmount: min_amount,
+
+			expectedSplitRouteSwapEvent: 1,
+			expectedMessageEvents:       9, // 4 pool creation + 5 events in SplitRouteExactAmountIn keeper methods
+		},
+		"error: empty route": {
+			routes:            []types.SwapAmountInSplitRoute{},
+			tokenInDenom:      "baz",
+			tokenoutMinAmount: min_amount,
+			expectedError:     true,
+		},
+		"error path: denom doesnot exist routes": {
+			routes: []types.SwapAmountInSplitRoute{
+				{
+					Pools:         []types.SwapAmountInRoute{pool1_in, pool2_in},
+					TokenInAmount: amount,
+				},
+				{
+					Pools:         []types.SwapAmountInRoute{pool1_in, pool2_in},
+					TokenInAmount: amount,
+				},
+			},
+			tokenInDenom:      "baz",
+			tokenoutMinAmount: min_amount,
+
+			expectedError: true,
+		},
+	}
+
+	for name, tc := range testcases {
+		s.Run(name, func() {
+			s.Setup()
+			ctx := s.Ctx
+
+			s.PrepareBalancerPool()
+			s.PrepareBalancerPool()
+			s.PrepareBalancerPool()
+			s.PrepareBalancerPool()
+
+			msgServer := poolmanagerKeeper.NewMsgServerImpl(s.App.PoolManagerKeeper)
+
+			// Reset event counts to 0 by creating a new manager.
+			ctx = ctx.WithEventManager(sdk.NewEventManager())
+			s.Equal(0, len(ctx.EventManager().Events()))
+
+			response, err := msgServer.SplitRouteSwapExactAmountIn(sdk.WrapSDKContext(ctx), &types.MsgSplitRouteSwapExactAmountIn{
+				Sender:            s.TestAccs[0].String(),
+				Routes:            tc.routes,
+				TokenInDenom:      tc.tokenInDenom,
+				TokenOutMinAmount: tc.tokenoutMinAmount,
+			})
+			if tc.expectedError {
+				s.Require().Error(err)
+				s.Require().Nil(response)
+			} else {
+				s.Require().NoError(err)
+				s.AssertEventEmitted(ctx, types.TypeMsgSplitRouteSwapExactAmountIn, tc.expectedSplitRouteSwapEvent)
+				s.AssertEventEmitted(ctx, sdk.EventTypeMessage, tc.expectedMessageEvents)
+			}
+
+		})
+	}
+}
+
+func (s *KeeperTestSuite) TestSplitRouteSwapExactAmountOut() {
+	testcases := map[string]struct {
+		routes            []types.SwapAmountOutSplitRoute
+		tokenOutDenom     string
+		tokenoutMaxAmount sdk.Int
+
+		expectedSplitRouteSwapEvent int
+		expectedMessageEvents       int
+		expectedError               bool
+	}{
+		"valid case: two routes": {
+			routes: []types.SwapAmountOutSplitRoute{
+				{
+					Pools:          []types.SwapAmountOutRoute{pool1_out, pool2_out},
+					TokenOutAmount: amount,
+				},
+				{
+					Pools:          []types.SwapAmountOutRoute{pool3_out, pool4_out},
+					TokenOutAmount: amount,
+				},
+			},
+			tokenOutDenom:     "uosmo",
+			tokenoutMaxAmount: max_amount,
+
+			expectedSplitRouteSwapEvent: 1,
+			expectedMessageEvents:       9, // 4 pool creation + 5 events in SplitRouteExactAmountOut keeper methods
+		},
+		"error: empty route": {
+			routes:            []types.SwapAmountOutSplitRoute{},
+			tokenOutDenom:     "baz",
+			tokenoutMaxAmount: max_amount,
+
+			expectedError: true,
+		},
+		"error path: denom duplicate route": {
+			routes: []types.SwapAmountOutSplitRoute{
+				{
+					Pools:          []types.SwapAmountOutRoute{pool1_out, pool2_out},
+					TokenOutAmount: amount,
+				},
+				{
+					Pools:          []types.SwapAmountOutRoute{pool1_out, pool2_out},
+					TokenOutAmount: amount,
+				},
+			},
+			tokenOutDenom:     "baz",
+			tokenoutMaxAmount: max_amount,
+
+			expectedError: true,
+		},
+	}
+
+	for name, tc := range testcases {
+		s.Run(name, func() {
+			s.Setup()
+			ctx := s.Ctx
+
+			s.PrepareBalancerPool()
+			s.PrepareBalancerPool()
+			s.PrepareBalancerPool()
+			s.PrepareBalancerPool()
+
+			msgServer := poolmanagerKeeper.NewMsgServerImpl(s.App.PoolManagerKeeper)
+
+			// Reset event counts to 0 by creating a new manager.
+			ctx = ctx.WithEventManager(sdk.NewEventManager())
+			s.Equal(0, len(ctx.EventManager().Events()))
+
+			response, err := msgServer.SplitRouteSwapExactAmountOut(sdk.WrapSDKContext(ctx), &types.MsgSplitRouteSwapExactAmountOut{
+				Sender:           s.TestAccs[0].String(),
+				Routes:           tc.routes,
+				TokenOutDenom:    tc.tokenOutDenom,
+				TokenInMaxAmount: tc.tokenoutMaxAmount,
+			})
+			if tc.expectedError {
+				s.Require().Error(err)
+				s.Require().Nil(response)
+			} else {
+
+				s.Require().NoError(err)
+				s.AssertEventEmitted(ctx, types.TypeMsgSplitRouteSwapExactAmountOut, tc.expectedSplitRouteSwapEvent)
+				s.AssertEventEmitted(ctx, sdk.EventTypeMessage, tc.expectedMessageEvents)
+			}
+
+		})
+	}
+}
diff --git a/x/txfees/client/cli/query_test.go b/x/txfees/client/cli/query_test.go
index 4f29cccb7..f9cfa0362 100644
--- a/x/txfees/client/cli/query_test.go
+++ b/x/txfees/client/cli/query_test.go
@@ -32,9 +32,11 @@ func (s *QueryTestSuite) SetupSuite() {
 	upgradeProp := types.NewUpdateFeeTokenProposal(
 		"Test Proposal",
 		"test",
-		types.FeeToken{
-			Denom:  "uosmo",
-			PoolID: 1,
+		[]types.FeeToken{
+			{
+				Denom:  "uosmo",
+				PoolID: 1,
+			},
 		},
 	)
 	err := s.App.TxFeesKeeper.HandleUpdateFeeTokenProposal(s.Ctx, &upgradeProp)
diff --git a/x/txfees/keeper/keeper_test.go b/x/txfees/keeper/keeper_test.go
index 3e9d35684..136e53f16 100644
--- a/x/txfees/keeper/keeper_test.go
+++ b/x/txfees/keeper/keeper_test.go
@@ -55,9 +55,11 @@ func (s *KeeperTestSuite) ExecuteUpgradeFeeTokenProposal(feeToken string, poolId
 	upgradeProp := types.NewUpdateFeeTokenProposal(
 		"Test Proposal",
 		"test",
-		types.FeeToken{
-			Denom:  feeToken,
-			PoolID: poolId,
+		[]types.FeeToken{
+			{
+				Denom:  feeToken,
+				PoolID: poolId,
+			},
 		},
 	)
 	return s.App.TxFeesKeeper.HandleUpdateFeeTokenProposal(s.Ctx, &upgradeProp)