diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9ae10708ee5..f8948ac863c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -25,6 +25,10 @@ on: env: GO_VERSION: '1.20.5' +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + jobs: build: name: osmosisd-${{ matrix.targetos }}-${{ matrix.arch }} diff --git a/.github/workflows/check-generated.yml b/.github/workflows/check-generated.yml index ecf3f50662e..3452bbf8eaf 100644 --- a/.github/workflows/check-generated.yml +++ b/.github/workflows/check-generated.yml @@ -4,6 +4,7 @@ # changed, because generated code can change in response to toolchain updates # even if no files in the repository are modified. name: Check generated code + on: workflow_dispatch: pull_request: @@ -13,6 +14,10 @@ on: permissions: contents: read +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + jobs: check-proto: runs-on: ubuntu-latest diff --git a/.github/workflows/check-state-compatibility.yml b/.github/workflows/check-state-compatibility.yml index e5e3a51cf39..22c90533728 100644 --- a/.github/workflows/check-state-compatibility.yml +++ b/.github/workflows/check-state-compatibility.yml @@ -42,6 +42,10 @@ env: LCD_ENDPOINT: https://lcd.osmosis.zone DELTA_HALT_HEIGHT: 50 +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + jobs: compare_versions: # Compare current mainnet osmosis major version with the major version of github branch diff --git a/.github/workflows/contracts.yml b/.github/workflows/contracts.yml index f97ac927fc6..d9dc994c981 100644 --- a/.github/workflows/contracts.yml +++ b/.github/workflows/contracts.yml @@ -1,4 +1,5 @@ name: Cosmwasm Contracts + on: pull_request: branches: @@ -9,6 +10,9 @@ on: - "v[0-9]**" workflow_dispatch: +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true jobs: test: diff --git a/.github/workflows/protocol-docs.yml b/.github/workflows/protocol-docs.yml new file mode 100644 index 00000000000..499829768c3 --- /dev/null +++ b/.github/workflows/protocol-docs.yml @@ -0,0 +1,52 @@ +name: Render and Deploy Docs + +on: + workflow_dispatch: + push: + branches: + - main + +jobs: + + build: + name: Render and deploy protocol and API docs + timeout-minutes: 30 + runs-on: ubuntu-latest + steps: + - name: Checkout the source code + uses: actions/checkout@v3 + with: + lfs: true + - name: Install rust toolchain + uses: dtolnay/rust-toolchain@nightly + - name: Load Rust caching + uses: astriaorg/buildjet-rust-cache@v2.5.1 + - name: Load get-version action to grab version component of deployment path + uses: battila7/get-version-action@v2 + id: get_version + - name: Print version component of deployment path + run: echo ${{ steps.get_version.outputs.version }} + - name: Install mdbook + run: cargo install mdbook mdbook-katex mdbook-mermaid + - name: Build protocol spec + run: cd docs/protocol && mdbook build + - name: Move protocol spec to subdirectory & Deploy + env: + DO_DOCS_PK: ${{ secrets.DO_DOCS_PK }} + DO_DOCS_IP: ${{ secrets.DO_DOCS_IP }} + run: | + cd docs/protocol + if [ -d "do-tmp" ]; then rm -rf do-tmp; fi + mkdir do-tmp + mv book do-tmp/${{ steps.get_version.outputs.version }} + tree do-tmp + which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y ) + which rsync || ( apt-get update -y && apt-get install rsync -y ) + eval $(ssh-agent -s) + ssh-add <(echo "$DO_DOCS_PK" ) + mkdir -p ~/.ssh + chmod 700 ~/.ssh + ssh-keyscan $DO_DOCS_IP >> ~/.ssh/known_hosts + chmod 644 ~/.ssh/known_hosts + cd do-tmp/main + scp -r * root@$DO_DOCS_IP:/var/www/html diff --git a/.github/workflows/push-dev-docker-images.yml b/.github/workflows/push-dev-docker-images.yml index f9f1a05bf86..94237b0ef9d 100644 --- a/.github/workflows/push-dev-docker-images.yml +++ b/.github/workflows/push-dev-docker-images.yml @@ -21,7 +21,7 @@ on: branches: - main - v[0-9]+.x - + env: RUNNER_BASE_IMAGE_ALPINE: alpine:3.17 OSMOSIS_DEV_IMAGE_REPOSITORY: osmolabs/osmosis-dev diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e4b78c66071..77e1ac8fd35 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -12,17 +12,19 @@ on: workflow_dispatch: env: - GO_VERSION: '1.20.5' + GO_VERSION: "1.20.5" + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true jobs: get_diff: runs-on: ubuntu-latest steps: - - - name: Check out repository code + - name: Check out repository code uses: actions/checkout@v3 - - - name: Get git diff + - name: Get git diff uses: technote-space/get-diff-action@v6.1.2 with: PATTERNS: | @@ -41,37 +43,29 @@ jobs: if: needs.get_diff.outputs.git_diff runs-on: ubuntu-latest steps: - - - name: Check out repository code + - name: Check out repository code uses: actions/checkout@v3 - - - name: ๐Ÿฟ Setup Golang + - name: ๐Ÿฟ Setup Golang uses: actions/setup-go@v4 with: go-version: ${{env.GO_VERSION}} - - - name: Create a file with all core Cosmos SDK pkgs + - name: Create a file with all core Cosmos SDK pkgs run: go list ./... ./osmomath/... ./osmoutils/... ./x/ibc-hooks/... ./x/epochs | grep -E -v 'tests/simulator|e2e' > pkgs.txt - - - name: Split pkgs into 4 files + - name: Split pkgs into 4 files run: split -d -n l/4 pkgs.txt pkgs.txt.part. - - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v3 with: name: "${{ github.sha }}-00" path: ./pkgs.txt.part.00 - - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v3 with: name: "${{ github.sha }}-01" path: ./pkgs.txt.part.01 - - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v3 with: name: "${{ github.sha }}-02" path: ./pkgs.txt.part.02 - - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v3 with: name: "${{ github.sha }}-03" path: ./pkgs.txt.part.03 @@ -85,23 +79,18 @@ jobs: matrix: part: ["00", "01", "02", "03"] steps: - - - name: Check out repository code + - name: Check out repository code uses: actions/checkout@v3 - - - name: ๐Ÿฟ Setup Golang + - name: ๐Ÿฟ Setup Golang uses: actions/setup-go@v4 with: go-version: ${{env.GO_VERSION}} - - - name: Display go version + - name: Display go version run: go version - - - uses: actions/download-artifact@v3 + - uses: actions/download-artifact@v3 with: name: "${{ github.sha }}-${{ matrix.part }}" - - - name: Test & coverage report creation + - name: Test & coverage report creation run: | VERSION=$(echo $(git describe --tags) | sed 's/^v//') || VERSION=${GITHUB_SHA} TESTS=$(cat pkgs.txt.part.${{ matrix.part }}) @@ -111,59 +100,63 @@ jobs: e2e: needs: get_diff if: needs.get_diff.outputs.git_diff - runs-on: ubuntu-latest + runs-on: self-hosted timeout-minutes: 25 steps: - - - name: Check out repository code + - name: Clean up Pre-Existing E2E Docker containers + run: | + # Remove containers with names starting with "osmo-test-" + docker ps -aqf "name=osmo-test-*" | xargs -r docker rm -f + + # Remove containers with names starting with "hermes-relayer" + docker ps -aqf "name=hermes-relayer*" | xargs -r docker rm -f + - name: Check out repository code uses: actions/checkout@v3 with: fetch-depth: 0 - - - name: ๐Ÿฟ Setup Golang + - name: ๐Ÿฟ Setup Golang uses: actions/setup-go@v4 with: go-version: ${{env.GO_VERSION}} - - - name: Set up QEMU + - name: Set up QEMU uses: docker/setup-qemu-action@v2 - - - name: Set up Docker Buildx + - name: Set up Docker Buildx uses: docker/setup-buildx-action@v2 - - - name: Build e2e image + - name: Build e2e image uses: docker/build-push-action@v4 with: load: true context: . tags: osmosis:debug - # Use experimental Cache backend API: + # Use experimental Cache backend API: # https://github.com/docker/build-push-action/blob/master/docs/advanced/cache.md#cache-backend-api cache-from: type=gha cache-to: type=gha,mode=max build-args: | BASE_IMG_TAG=debug - - - name: Test e2e and Upgrade + - name: Test e2e and Upgrade run: make test-e2e-ci - - - name: Dump docker logs on failure + - name: Dump docker logs on failure if: failure() uses: jwalton/gh-docker-logs@v2 with: dest: "./logs" - - - name: Tar logs + - name: Tar logs if: failure() run: tar cvzf ./logs.tgz ./logs - - - name: Upload logs to GitHub + - name: Upload logs to GitHub uses: actions/upload-artifact@v3 with: name: logs.tgz path: ./logs.tgz if: failure() - - - name: ๐Ÿงน Clean up Osmosis Home + - name: ๐Ÿงน Clean up Osmosis Home if: always() run: rm -rf $HOME/.osmosisd/ || true + - name: Clean up E2E Docker containers + run: | + # Remove containers with names starting with "osmo-test-" + docker ps -aqf "name=osmo-test-*" | xargs -r docker rm -f + + # Remove containers with names starting with "hermes-relayer" + docker ps -aqf "name=hermes-relayer*" | xargs -r docker rm -f diff --git a/.gitignore b/.gitignore index 4313d719db8..84f981a2f3a 100644 --- a/.gitignore +++ b/.gitignore @@ -250,5 +250,8 @@ blocks.db tests/cl-genesis-positions/script tests/cl-genesis-positions/*.json +# Docs +docs/protocol/book + # Release folder -dist/ \ No newline at end of file +dist/ diff --git a/CHANGELOG.md b/CHANGELOG.md index 063907ccd86..0340bc5df35 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -51,7 +51,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * [#5883](https://github.com/osmosis-labs/osmosis/pull/5883) feat: Uninitialize empty ticks * [#5874](https://github.com/osmosis-labs/osmosis/pull/5874) Remove Partial Migration from superfluid migration to CL * [#5901](https://github.com/osmosis-labs/osmosis/pull/5901) Adding support for CW pools in ProtoRev -* [#5937](https://github.com/osmosis-labs/osmosis/pull/5937) feat: add SetScalingFactorController gov prop +* [#5937](https://github.com/osmosis-labs/osmosis/pull/5937) feat: add SetScalingFactorController gov prop * [#5939](https://github.com/osmosis-labs/osmosis/pull/5939) Fix: Flip existing twapRecords base/quote price denoms * [#5938](https://github.com/osmosis-labs/osmosis/pull/5938) Chore: Fix valset amino codec diff --git a/LICENSE b/LICENSE index ea662a3694e..062dfd8c290 100644 --- a/LICENSE +++ b/LICENSE @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright 2021 Sikka Research Pte. Ltd. + Copyright 2021 Osmosis Foundation Ltd. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/Makefile b/Makefile index 3559d6cb182..ff9018b4bcc 100644 --- a/Makefile +++ b/Makefile @@ -282,7 +282,7 @@ run-querygen: ############################################################################### PACKAGES_UNIT=$(shell go list ./... ./osmomath/... ./osmoutils/... ./x/ibc-hooks/... ./x/epochs | grep -E -v 'tests/simulator|e2e') -PACKAGES_E2E=$(shell go list ./... | grep '/e2e') +PACKAGES_E2E := $(shell go list ./... | grep '/e2e' | awk -F'/e2e' '{print $$1 "/e2e"}' | uniq) PACKAGES_SIM=$(shell go list ./... | grep '/tests/simulator') TEST_PACKAGES=./... diff --git a/app/apptesting/cosmwasmpool.go b/app/apptesting/cosmwasmpool.go index bc17512accb..94251291fa6 100644 --- a/app/apptesting/cosmwasmpool.go +++ b/app/apptesting/cosmwasmpool.go @@ -29,7 +29,7 @@ func (s *KeeperTestHelper) PrepareCosmWasmPool() cosmwasmpooltypes.CosmWasmExten return s.PrepareCustomTransmuterPool(s.TestAccs[0], []string{DefaultTransmuterDenomA, DefaultTransmuterDenomB}) } -// PrepareCustomConcentratedPool sets up a concentrated liquidity pool with the custom parameters. +// PrepareCustomTransmuterPool sets up a transmuter pool with the custom parameters. func (s *KeeperTestHelper) PrepareCustomTransmuterPool(owner sdk.AccAddress, denoms []string) cosmwasmpooltypes.CosmWasmExtension { // Mint some assets to the account. s.FundAcc(s.TestAccs[0], DefaultAcctFunds) diff --git a/app/keepers/keepers.go b/app/keepers/keepers.go index 38709d660f2..ba63d28cbac 100644 --- a/app/keepers/keepers.go +++ b/app/keepers/keepers.go @@ -62,9 +62,9 @@ import ( ibchost "github.com/cosmos/ibc-go/v4/modules/core/24-host" ibckeeper "github.com/cosmos/ibc-go/v4/modules/core/keeper" - packetforward "github.com/strangelove-ventures/packet-forward-middleware/v4/router" - packetforwardkeeper "github.com/strangelove-ventures/packet-forward-middleware/v4/router/keeper" - packetforwardtypes "github.com/strangelove-ventures/packet-forward-middleware/v4/router/types" + packetforward "github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v4/router" + packetforwardkeeper "github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v4/router/keeper" + packetforwardtypes "github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v4/router/types" // IBC Transfer: Defines the "transfer" IBC port transfer "github.com/cosmos/ibc-go/v4/modules/apps/transfer" @@ -357,7 +357,13 @@ func (appKeepers *AppKeepers) InitNormalKeepers( protorevKeeper := protorevkeeper.NewKeeper( appCodec, appKeepers.keys[protorevtypes.StoreKey], appKeepers.GetSubspace(protorevtypes.ModuleName), - appKeepers.AccountKeeper, appKeepers.BankKeeper, appKeepers.GAMMKeeper, appKeepers.EpochsKeeper, appKeepers.PoolManagerKeeper) + appKeepers.AccountKeeper, + appKeepers.BankKeeper, + appKeepers.GAMMKeeper, + appKeepers.EpochsKeeper, + appKeepers.PoolManagerKeeper, + appKeepers.ConcentratedLiquidityKeeper, + ) appKeepers.ProtoRevKeeper = &protorevKeeper txFeesKeeper := txfeeskeeper.NewKeeper( @@ -422,7 +428,7 @@ func (appKeepers *AppKeepers) InitNormalKeepers( appKeepers.keys[tokenfactorytypes.StoreKey], appKeepers.GetSubspace(tokenfactorytypes.ModuleName), appKeepers.AccountKeeper, - appKeepers.BankKeeper.WithMintCoinsRestriction(tokenfactorytypes.NewTokenFactoryDenomMintCoinsRestriction()), + appKeepers.BankKeeper, appKeepers.DistrKeeper, ) appKeepers.TokenFactoryKeeper = &tokenFactoryKeeper @@ -493,7 +499,7 @@ func (appKeepers *AppKeepers) InitNormalKeepers( AddRoute(txfeestypes.RouterKey, txfees.NewUpdateFeeTokenProposalHandler(*appKeepers.TxFeesKeeper)). AddRoute(superfluidtypes.RouterKey, superfluid.NewSuperfluidProposalHandler(*appKeepers.SuperfluidKeeper, *appKeepers.EpochsKeeper, *appKeepers.GAMMKeeper)). AddRoute(protorevtypes.RouterKey, protorev.NewProtoRevProposalHandler(*appKeepers.ProtoRevKeeper)). - AddRoute(gammtypes.RouterKey, gamm.NewMigrationRecordHandler(*appKeepers.GAMMKeeper)). + AddRoute(gammtypes.RouterKey, gamm.NewGammProposalHandler(*appKeepers.GAMMKeeper)). AddRoute(concentratedliquiditytypes.RouterKey, concentratedliquidity.NewConcentratedLiquidityProposalHandler(*appKeepers.ConcentratedLiquidityKeeper)). AddRoute(cosmwasmpooltypes.RouterKey, cosmwasmpool.NewCosmWasmPoolProposalHandler(*appKeepers.CosmwasmPoolKeeper)) @@ -518,7 +524,7 @@ func (appKeepers *AppKeepers) InitNormalKeepers( // // Note that the forward middleware is only integrated on the "reveive" direction. It can be safely skipped when sending. // Note also that the forward middleware is called "router", but we are using the name "forward" for clarity -// This may later be renamed upstream: https://github.com/strangelove-ventures/packet-forward-middleware/issues/10 +// This may later be renamed upstream: https://github.com/ibc-apps/middleware/packet-forward-middleware/issues/10 // // After this, the wasm keeper is required to be set on both // appkeepers.WasmHooks AND appKeepers.RateLimitingICS4Wrapper diff --git a/app/keepers/modules.go b/app/keepers/modules.go index 69068f1f5df..a52bc234f7f 100644 --- a/app/keepers/modules.go +++ b/app/keepers/modules.go @@ -3,10 +3,10 @@ package keepers import ( "github.com/CosmWasm/wasmd/x/wasm" wasmclient "github.com/CosmWasm/wasmd/x/wasm/client" + "github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v4/router" transfer "github.com/cosmos/ibc-go/v4/modules/apps/transfer" ibc "github.com/cosmos/ibc-go/v4/modules/core" ibcclientclient "github.com/cosmos/ibc-go/v4/modules/core/02-client/client" - "github.com/strangelove-ventures/packet-forward-middleware/v4/router" "github.com/cosmos/cosmos-sdk/types/module" "github.com/cosmos/cosmos-sdk/x/auth" @@ -82,6 +82,8 @@ var AppModuleBasics = []module.AppModuleBasic{ superfluidclient.UpdateUnpoolWhitelistProposalHandler, gammclient.ReplaceMigrationRecordsProposalHandler, gammclient.UpdateMigrationRecordsProposalHandler, + gammclient.CreateCLPoolAndLinkToCFMMProposalHandler, + gammclient.SetScalingFactorControllerProposalHandler, clclient.CreateConcentratedLiquidityPoolProposalHandler, clclient.TickSpacingDecreaseProposalHandler, cwpoolclient.UploadCodeIdAndWhitelistProposalHandler, diff --git a/app/modules.go b/app/modules.go index 88c9765f2d9..c163cc18d41 100644 --- a/app/modules.go +++ b/app/modules.go @@ -12,8 +12,8 @@ import ( ibchost "github.com/cosmos/ibc-go/v4/modules/core/24-host" ibckeeper "github.com/cosmos/ibc-go/v4/modules/core/keeper" - packetforward "github.com/strangelove-ventures/packet-forward-middleware/v4/router" - packetforwardtypes "github.com/strangelove-ventures/packet-forward-middleware/v4/router/types" + packetforward "github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v4/router" + packetforwardtypes "github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v4/router/types" ibchookstypes "github.com/osmosis-labs/osmosis/x/ibc-hooks/types" diff --git a/app/upgrades/v15/constants.go b/app/upgrades/v15/constants.go index 2338b59a01d..509f367b25a 100644 --- a/app/upgrades/v15/constants.go +++ b/app/upgrades/v15/constants.go @@ -2,8 +2,8 @@ package v15 import ( store "github.com/cosmos/cosmos-sdk/store/types" + packetforwardtypes "github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v4/router/types" icqtypes "github.com/cosmos/ibc-apps/modules/async-icq/v4/types" - packetforwardtypes "github.com/strangelove-ventures/packet-forward-middleware/v4/router/types" "github.com/osmosis-labs/osmosis/v17/app/upgrades" poolmanagertypes "github.com/osmosis-labs/osmosis/v17/x/poolmanager/types" diff --git a/app/upgrades/v15/upgrades.go b/app/upgrades/v15/upgrades.go index d2f0ba48893..7e050a47974 100644 --- a/app/upgrades/v15/upgrades.go +++ b/app/upgrades/v15/upgrades.go @@ -1,7 +1,7 @@ package v15 import ( - packetforwardtypes "github.com/strangelove-ventures/packet-forward-middleware/v4/router/types" + packetforwardtypes "github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v4/router/types" poolmanagertypes "github.com/osmosis-labs/osmosis/v17/x/poolmanager/types" diff --git a/app/upgrades/v16/upgrades_test.go b/app/upgrades/v16/upgrades_test.go index 4b78c29521b..86c1d8846cf 100644 --- a/app/upgrades/v16/upgrades_test.go +++ b/app/upgrades/v16/upgrades_test.go @@ -74,7 +74,7 @@ func (suite *UpgradeTestSuite) TestUpgrade() { multiplicativeTolerance := osmomath.ErrTolerance{ MultiplicativeTolerance: sdk.MustNewDecFromStr("0.0001"), } - + defaultDaiAmount, _ := sdk.NewIntFromString("73000000000000000000000") testCases := []struct { name string pre_upgrade func() @@ -88,11 +88,11 @@ func (suite *UpgradeTestSuite) TestUpgrade() { // Create earlier pools for i := uint64(1); i < v16.DaiOsmoPoolId; i++ { - suite.PrepareBalancerPoolWithCoins(desiredDenom0Coin, daiCoin) + suite.PrepareBalancerPoolWithCoins(sdk.NewCoin("uosmo", sdk.NewInt(10000000000)), sdk.NewCoin("ibc/0CD3A0285E1341859B5E86B6AB7682F023D03E97607CCC1DC95706411D866DF7", defaultDaiAmount)) } // Create DAI / OSMO pool - suite.PrepareBalancerPoolWithCoins(daiCoin, desiredDenom0Coin) + suite.PrepareBalancerPoolWithCoins(sdk.NewCoin("ibc/0CD3A0285E1341859B5E86B6AB7682F023D03E97607CCC1DC95706411D866DF7", defaultDaiAmount), sdk.NewCoin("uosmo", sdk.NewInt(10000000000))) }, func() { diff --git a/cosmwasm/contracts/swaprouter/src/helpers.rs b/cosmwasm/contracts/swaprouter/src/helpers.rs index 9a15d082116..de4013a010c 100644 --- a/cosmwasm/contracts/swaprouter/src/helpers.rs +++ b/cosmwasm/contracts/swaprouter/src/helpers.rs @@ -58,7 +58,7 @@ pub fn validate_pool_route( return Result::Err(ContractError::InvalidPoolRoute { reason: format!( "denom {} is not in pool id {}", - current_denom, route_part.pool_id + route_part.token_out_denom, route_part.pool_id ), }); } diff --git a/cosmwasm/contracts/swaprouter/tests/set_route_test.rs b/cosmwasm/contracts/swaprouter/tests/set_route_test.rs index 936b2234b54..2697a05059e 100644 --- a/cosmwasm/contracts/swaprouter/tests/set_route_test.rs +++ b/cosmwasm/contracts/swaprouter/tests/set_route_test.rs @@ -96,10 +96,7 @@ test_set_route!( test_set_route!( pool_does_not_have_output_asset should failed_with - r#"Invalid Pool Route: "denom uosmo is not in pool id 1": execute wasm contract failed"#, - // confusing error message from chain, should state that: - // > `denom uatom is not in pool id 1": execute wasm contract failed` - // instead. + r#"Invalid Pool Route: "denom uatom is not in pool id 1": execute wasm contract failed"#, sender = Owner, msg = ExecuteMsg::SetRoute { @@ -117,10 +114,7 @@ test_set_route!( test_set_route!( intermediary_pool_does_not_have_output_asset should failed_with - r#"Invalid Pool Route: "denom uosmo is not in pool id 1": execute wasm contract failed"#, - // confusing error message from chain, should state that: - // > `denom foocoin is not in pool id 1": execute wasm contract failed` - // instead. + r#"Invalid Pool Route: "denom foocoin is not in pool id 1": execute wasm contract failed"#, sender = Owner, msg = ExecuteMsg::SetRoute { diff --git a/docs/protocol/book.toml b/docs/protocol/book.toml new file mode 100644 index 00000000000..c94f58c7ffe --- /dev/null +++ b/docs/protocol/book.toml @@ -0,0 +1,16 @@ +[book] +authors = ["Osmosis Labs"] +language = "en" +multilingual = false +src = "src" +title = "The Osmosis Protocol" + +[preprocessor.katex] + +[preprocessor.mermaid] +command = "mdbook-mermaid" + +[output.html] +curly-quotes = true +fold = { enable = true, level = 1 } +git-repository-url = "https://github.com/osmosis-labs/osmosis" diff --git a/docs/protocol/src/SUMMARY.md b/docs/protocol/src/SUMMARY.md new file mode 100644 index 00000000000..88f1c283c13 --- /dev/null +++ b/docs/protocol/src/SUMMARY.md @@ -0,0 +1,12 @@ +# Summary + +[Osmosis](./osmosis.md) +- [Decentralized Exchange](./core_dex.md) + - [Weighted Pool](./dex/weighted.md) + - [Stableswap Pool](./dex/stableswap.md) + - [Concentrated Pool](./dex/concentrated.md) + - [Cosmwasm Pool](./dex/cosmwasm.md) +- [Governance](./governance.md) +- [Staking](./staking.md) +- [Smart Contracts](./smartcontracts.md) +- [Ecosystem](./ecosystem.md) diff --git a/docs/protocol/src/core_dex.md b/docs/protocol/src/core_dex.md new file mode 100644 index 00000000000..8a32582c463 --- /dev/null +++ b/docs/protocol/src/core_dex.md @@ -0,0 +1,12 @@ +# Decentralized Exchange + +Osmosis is a decentralized automated market maker (AMM) protocol built using Cosmos SDK that represents a flexible building block for programmable liquidity. + +By separating the AMM curve logic and math from the core swapping functionality, Osmosis becomes an extensible AMM that can incorporate any number of swap curves and pool types. This includes: + +- Traditional 50/50 weighted pools +- Custom weights like 80/20 for controlled exposure +- Solidly-style Stableswap curve +- Concentrated Liquidity pools +- CosmWasm pools + diff --git a/docs/protocol/src/dex/concentrated.md b/docs/protocol/src/dex/concentrated.md new file mode 100644 index 00000000000..d319e9e23c8 --- /dev/null +++ b/docs/protocol/src/dex/concentrated.md @@ -0,0 +1 @@ +# Concentrated Pool diff --git a/docs/protocol/src/dex/cosmwams.md b/docs/protocol/src/dex/cosmwams.md new file mode 100644 index 00000000000..a0361e071aa --- /dev/null +++ b/docs/protocol/src/dex/cosmwams.md @@ -0,0 +1 @@ +# CosmWasm Pool diff --git a/docs/protocol/src/dex/cosmwasm.md b/docs/protocol/src/dex/cosmwasm.md new file mode 100644 index 00000000000..8f9da51e6be --- /dev/null +++ b/docs/protocol/src/dex/cosmwasm.md @@ -0,0 +1 @@ +# Cosmwasm Pool diff --git a/docs/protocol/src/dex/stableswap.md b/docs/protocol/src/dex/stableswap.md new file mode 100644 index 00000000000..76fe3b47606 --- /dev/null +++ b/docs/protocol/src/dex/stableswap.md @@ -0,0 +1 @@ +# Stableswap Pool diff --git a/docs/protocol/src/dex/weighted.md b/docs/protocol/src/dex/weighted.md new file mode 100644 index 00000000000..cfdde988e32 --- /dev/null +++ b/docs/protocol/src/dex/weighted.md @@ -0,0 +1,7 @@ +# Weighted Pool + +Liquidity pools are clusters of tokens with pre-determined weights. A token's weight is how much its value accounts for the total value within the pool. For example, Uniswap pools involve two tokens with 50-50 weights. The total value of Asset A must remain equal to the total value of Asset B. Other token weights are possible, such as 90-10. It is also possible to have a liquidity pool with more than two assets. + +In Osmosis, pool creators are allowed to choose the tokens within the pool and their respective weights. The parameters chosen by the pool creator cannot be changed. Other users can create separate pools with different parameters. + +Weighted Pools are an extension of the classical AMM pools popularized by Uniswap v1. Weighted Pools are great for general cases, including tokens that don't necessarily have any price correlation (ex. DAI/WETH). Unlike pools in other AMMs that only provide 50/50 weightings, Osmosis Weighted Pools enable users to build pools with more than two tokens and custom weightings, such as pools with 80/20 or 60/20/20 weightings. diff --git a/docs/protocol/src/ecosystem.md b/docs/protocol/src/ecosystem.md new file mode 100644 index 00000000000..e46e912ed82 --- /dev/null +++ b/docs/protocol/src/ecosystem.md @@ -0,0 +1 @@ +# Ecosystem diff --git a/docs/protocol/src/governance.md b/docs/protocol/src/governance.md new file mode 100644 index 00000000000..66109a0f3d8 --- /dev/null +++ b/docs/protocol/src/governance.md @@ -0,0 +1,17 @@ +# Governance + +Osmosis is a sovereign delegated Proof-of-Stake chain with its own validator set. +Users delegate their stake to validators to secure the network while keeping the +opportunity to overwrite validator's decision with their own vote. + +The decisions are made through the governance process consisting of proposals. + +A proposal can be created by anyone. Once created with the required deposit, the +voting period begins. + +The proposal is either accepted or rejected. + +There are two types of proposals that determine the length of the voting period, +deposit amount and quorum: +1. Standard proposal +2. Expedited proposal diff --git a/docs/protocol/src/osmosis.md b/docs/protocol/src/osmosis.md new file mode 100644 index 00000000000..d558c222eb7 --- /dev/null +++ b/docs/protocol/src/osmosis.md @@ -0,0 +1,31 @@ +# Introduction to Osmosis + +Osmosis is a fair-launched, customizable automated market maker for +interchain assets that allows the creation and management of +non-custodial, self-balancing, interchain token index similar to one of +Balancer. + +Inspired by [Balancer](http://balancer.finance/whitepaper) and Sunny +Aggarwal's '[DAOfying Uniswap Automated Market Maker +Pools](https://www.sunnya97.com/blog/daoifying-uniswap-automated-market-maker-pools)', +the goal for Osmosis is to provide the best-in-class tools that extend +the use of AMMs within the Cosmos ecosystem beyond traditional token +swap-type use cases. Bonding curves, while have found its primary use +case in decentralized exchange mechanisms, its potential use case can be +further extended through the customizability that Osmosis offers. +Through the customizability offered by Osmosis such as custom-curve AMMs, +dynamic adjustments of spread factors, multi-token liquidity pools--the AMM +can offer decentralized formation of token fundraisers, interchain +staking, options market, and more for the Cosmos ecosystem. + +Whereas most Cosmos zones have focused their incentive scheme on the +delegators, Osmosis attempts to align the interests of multiple +stakeholders of the ecosystem such as LPs, DAO members, as well as +delegators. One mechanism that is introduced is how staked liquidity +providers have sovereign ownership over their pools, and through the +pool governance process allow them to adjust the parameters depending on +the pool's competition and market conditions. Osmosis is a sovereign +Cosmos zone that derives its sovereignty not only from its +application-specific blockchain architecture but also the collective +sovereignty of the LPs that has aligned interest to different tokens +that they are providing liquidity for. diff --git a/docs/protocol/src/smartcontracts.md b/docs/protocol/src/smartcontracts.md new file mode 100644 index 00000000000..95badcb05e1 --- /dev/null +++ b/docs/protocol/src/smartcontracts.md @@ -0,0 +1 @@ +# Smart Contracts (CosmWasm) diff --git a/docs/protocol/src/staking.md b/docs/protocol/src/staking.md new file mode 100644 index 00000000000..abe5cd84eb4 --- /dev/null +++ b/docs/protocol/src/staking.md @@ -0,0 +1 @@ +# Staking diff --git a/go.mod b/go.mod index 047631e713a..22f594aa2c4 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,8 @@ require ( github.com/cosmos/cosmos-proto v1.0.0-beta.2 github.com/cosmos/cosmos-sdk v0.47.4 github.com/cosmos/go-bip39 v1.0.0 - github.com/cosmos/ibc-apps/modules/async-icq/v4 v4.0.0-20230524151648-c02fa46c2860 + github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v4 v4.0.0-20230803185752-97c9635dd74a + github.com/cosmos/ibc-apps/modules/async-icq/v4 v4.0.0-20230803151532-5c60ac789ef7 github.com/cosmos/ibc-go/v4 v4.3.1 github.com/gogo/protobuf v1.3.3 github.com/golang/mock v1.6.0 @@ -20,17 +21,16 @@ require ( github.com/mattn/go-sqlite3 v1.14.17 github.com/ory/dockertest/v3 v3.10.0 github.com/osmosis-labs/go-mutesting v0.0.0-20221208041716-b43bcd97b3b3 - github.com/osmosis-labs/osmosis/osmomath v0.0.3-dev.0.20230629191111-f375469de8b6 - github.com/osmosis-labs/osmosis/osmoutils v0.0.0-20230801224523-e85e9a9cf445 + github.com/osmosis-labs/osmosis/osmomath v0.0.3-dev.0.20230804142026-a81cfe3ddde7 + github.com/osmosis-labs/osmosis/osmoutils v0.0.0-20230804142026-a81cfe3ddde7 github.com/osmosis-labs/osmosis/x/epochs v0.0.0-20230328024000-175ec88e4304 - github.com/osmosis-labs/osmosis/x/ibc-hooks v0.0.0-20230602130523-f9a94d8bbd10 + github.com/osmosis-labs/osmosis/x/ibc-hooks v0.0.6 github.com/pkg/errors v0.9.1 github.com/rakyll/statik v0.1.7 github.com/spf13/cast v1.5.1 github.com/spf13/cobra v1.7.0 github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.16.0 - github.com/strangelove-ventures/packet-forward-middleware/v4 v4.0.5 github.com/stretchr/testify v1.8.4 github.com/tendermint/tendermint v0.37.0-rc1 github.com/tendermint/tm-db v0.6.8-0.20220506192307-f628bb5dc95b @@ -38,7 +38,7 @@ require ( github.com/tidwall/gjson v1.14.4 go.uber.org/multierr v1.11.0 golang.org/x/exp v0.0.0-20230131160201-f062dba9d201 - google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 + google.golang.org/genproto/googleapis/api v0.0.0-20230706204954-ccb25ca9f130 google.golang.org/grpc v1.56.2 gopkg.in/yaml.v2 v2.4.0 mvdan.cc/gofumpt v0.5.0 @@ -65,6 +65,7 @@ require ( github.com/kkHAIKE/contextcheck v1.1.4 // indirect github.com/maratori/testableexamples v1.0.0 // indirect github.com/nunnatsa/ginkgolinter v0.9.0 // indirect + github.com/nxadm/tail v1.4.8 // indirect github.com/regen-network/cosmos-proto v0.3.1 // indirect github.com/sashamelentyev/interfacebloat v1.1.0 // indirect github.com/sashamelentyev/usestdlibvars v1.23.0 // indirect @@ -80,6 +81,8 @@ require ( go.uber.org/goleak v1.1.12 // indirect go.uber.org/zap v1.24.0 // indirect golang.org/x/arch v0.3.0 // indirect + google.golang.org/genproto v0.0.0-20230726155614-23370e0ffb3e // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20230706204954-ccb25ca9f130 // indirect ) require ( @@ -158,7 +161,7 @@ require ( github.com/gobwas/glob v0.2.3 // indirect github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect github.com/gofrs/flock v0.8.1 // indirect - github.com/golang/glog v1.1.0 // indirect + github.com/golang/glog v1.1.1 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/snappy v0.0.4 // indirect github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2 // indirect diff --git a/go.sum b/go.sum index 95bf93a83f5..a57c409861e 100644 --- a/go.sum +++ b/go.sum @@ -258,8 +258,10 @@ github.com/cosmos/gorocksdb v1.2.0 h1:d0l3jJG8M4hBouIZq0mDUHZ+zjOx044J3nGRskwTb4 github.com/cosmos/gorocksdb v1.2.0/go.mod h1:aaKvKItm514hKfNJpUJXnnOWeBnk2GL4+Qw9NHizILw= github.com/cosmos/iavl v0.19.4 h1:t82sN+Y0WeqxDLJRSpNd8YFX5URIrT+p8n6oJbJ2Dok= github.com/cosmos/iavl v0.19.4/go.mod h1:X9PKD3J0iFxdmgNLa7b2LYWdsGd90ToV5cAONApkEPw= -github.com/cosmos/ibc-apps/modules/async-icq/v4 v4.0.0-20230524151648-c02fa46c2860 h1:25/KpA4WJqdFjKFsa3VEL0ctWRovkEsqIn2phCAi9v0= -github.com/cosmos/ibc-apps/modules/async-icq/v4 v4.0.0-20230524151648-c02fa46c2860/go.mod h1:X/dLZ6QxTImzno7qvD6huLhh6ZZBcRt2URn4YCLcXFY= +github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v4 v4.0.0-20230803185752-97c9635dd74a h1:FKEtbHE+kULYf6ghxa3FvEfyR7BNde0940gAyuWborE= +github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v4 v4.0.0-20230803185752-97c9635dd74a/go.mod h1:Mn/jr9pIYr1ofFuptLEi9N6MjcshTT0cpoOY4ln1DeA= +github.com/cosmos/ibc-apps/modules/async-icq/v4 v4.0.0-20230803151532-5c60ac789ef7 h1:q6OzbGXmWRbMedDejhuctDbb3M6fWyJg3DY3bzJbYVs= +github.com/cosmos/ibc-apps/modules/async-icq/v4 v4.0.0-20230803151532-5c60ac789ef7/go.mod h1:X/dLZ6QxTImzno7qvD6huLhh6ZZBcRt2URn4YCLcXFY= github.com/cosmos/ibc-go/v4 v4.3.1 h1:xbg0CaCdxK3lvgGvSaI91ROOLd7s30UqEcexH6Ba4Ys= github.com/cosmos/ibc-go/v4 v4.3.1/go.mod h1:89E+K9CxpkS/etLEcG026jPM/RSnVMcfesvRYp/0aKI= github.com/cosmos/interchain-accounts v0.2.6 h1:TV2M2g1/Rb9MCNw1YePdBKE0rcEczNj1RGHT+2iRYas= @@ -462,8 +464,8 @@ github.com/golang-jwt/jwt/v4 v4.3.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzw github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/geo v0.0.0-20190916061304-5b978397cfec/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.1.0 h1:/d3pCKDPWNnvIWe0vVUpNP32qc8U3PDVxySP/y360qE= -github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ= +github.com/golang/glog v1.1.1 h1:jxpi2eWoU84wbX9iIEyAeeoac3FLuifZpY9tcNUD9kw= +github.com/golang/glog v1.1.1/go.mod h1:zR+okUeTbrL6EL3xHUDxZuEtGv04p5shwip1+mL/rLQ= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -905,6 +907,7 @@ github.com/nunnatsa/ginkgolinter v0.9.0 h1:Sm0zX5QfjJzkeCjEp+t6d3Ha0jwvoDjleP9XC github.com/nunnatsa/ginkgolinter v0.9.0/go.mod h1:FHaMLURXP7qImeH6bvxWJUpyH+2tuqe5j4rW1gxJRmI= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= @@ -948,16 +951,14 @@ github.com/osmosis-labs/cosmos-sdk v0.45.0-rc1.0.20230703010110-ed4eb883f2a6 h1: github.com/osmosis-labs/cosmos-sdk v0.45.0-rc1.0.20230703010110-ed4eb883f2a6/go.mod h1:9KGhMg+7ZWgZ50Wa/x8w/jN19O0TSqYLlqUj+2wwxLU= 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.20230629191111-f375469de8b6 h1:Kmkx5Rh72+LB8AL6dc6fZA+IVR0INu0YIiMF2ScDhaQ= -github.com/osmosis-labs/osmosis/osmomath v0.0.3-dev.0.20230629191111-f375469de8b6/go.mod h1:JTym95/bqrSnG5MPcXr1YDhv43JdCeo3p+iDbazoX68= -github.com/osmosis-labs/osmosis/osmoutils v0.0.0-20230728163612-426afac90c44 h1:UOaBVxEMMv2FS1znU7kHBdtSeZQIjnmXL4r9r19XyBo= -github.com/osmosis-labs/osmosis/osmoutils v0.0.0-20230728163612-426afac90c44/go.mod h1:Pl8Nzx6O6ow/+aqfMoMSz4hX+zz6RrnDYsooptECGxM= -github.com/osmosis-labs/osmosis/osmoutils v0.0.0-20230801224523-e85e9a9cf445 h1:V942btb00oVXHox7hEN8FrPfEaMTiVuInM7Tr00eOMU= -github.com/osmosis-labs/osmosis/osmoutils v0.0.0-20230801224523-e85e9a9cf445/go.mod h1:Pl8Nzx6O6ow/+aqfMoMSz4hX+zz6RrnDYsooptECGxM= +github.com/osmosis-labs/osmosis/osmomath v0.0.3-dev.0.20230804142026-a81cfe3ddde7 h1:NTR4zfrPMP4pJ5T60zyZumBAnTWmTAQX/JSZLGrM9jI= +github.com/osmosis-labs/osmosis/osmomath v0.0.3-dev.0.20230804142026-a81cfe3ddde7/go.mod h1:UlftwozB+QObT3o0YfkuuyL9fsVdgoWt0dm6J7MLYnU= +github.com/osmosis-labs/osmosis/osmoutils v0.0.0-20230804142026-a81cfe3ddde7 h1:uwP/LzPE/edqNKf/Tpn8y9L6EO3JHOVwb+zq1gjL1hE= +github.com/osmosis-labs/osmosis/osmoutils v0.0.0-20230804142026-a81cfe3ddde7/go.mod h1:Pl8Nzx6O6ow/+aqfMoMSz4hX+zz6RrnDYsooptECGxM= github.com/osmosis-labs/osmosis/x/epochs v0.0.0-20230328024000-175ec88e4304 h1:RIrWLzIiZN5Xd2JOfSOtGZaf6V3qEQYg6EaDTAkMnCo= github.com/osmosis-labs/osmosis/x/epochs v0.0.0-20230328024000-175ec88e4304/go.mod h1:yPWoJTj5RKrXKUChAicp+G/4Ni/uVEpp27mi/FF/L9c= -github.com/osmosis-labs/osmosis/x/ibc-hooks v0.0.0-20230602130523-f9a94d8bbd10 h1:XrES5AHZMZ/Y78boW35PTignkhN9h8VvJ1sP8EJDIu8= -github.com/osmosis-labs/osmosis/x/ibc-hooks v0.0.0-20230602130523-f9a94d8bbd10/go.mod h1:Ln6CKcXg/CJLSBE6Fd96/MIKPyA4iHuQTKSbl9q7vYo= +github.com/osmosis-labs/osmosis/x/ibc-hooks v0.0.6 h1:PjfLL5rwwm44CeLnNQssrFgmj4BdeIS5DriKYhGz7IM= +github.com/osmosis-labs/osmosis/x/ibc-hooks v0.0.6/go.mod h1:2Aqs0L6JnMfo+P+It8q7hJsP1YB+Is5DJc4nRSiBF/U= github.com/osmosis-labs/wasmd v0.31.0-osmo-v16 h1:X747cZYdnqc/+RV48iPVeGprpVb/fUWSaKGsZUWrdbg= github.com/osmosis-labs/wasmd v0.31.0-osmo-v16/go.mod h1:Rf8zW/GgBQyFRRB4s62VQHWA6sTlMFSjoDQQpoq64iI= github.com/otiai10/copy v1.2.0/go.mod h1:rrF5dJ5F0t/EWSYODDu4j9/vEeYHMkc8jt0zJChqQWw= @@ -1149,8 +1150,6 @@ github.com/ssgreg/nlreturn/v2 v2.2.1/go.mod h1:E/iiPB78hV7Szg2YfRgyIrk1AD6JVMTRk github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q= github.com/stbenjam/no-sprintf-host-port v0.1.1 h1:tYugd/yrm1O0dV+ThCbaKZh195Dfm07ysF0U6JQXczc= github.com/stbenjam/no-sprintf-host-port v0.1.1/go.mod h1:TLhvtIvONRzdmkFiio4O8LHsN9N74I+PhRquPsxpL0I= -github.com/strangelove-ventures/packet-forward-middleware/v4 v4.0.5 h1:KKUqeGhVBK38+1LwThC8IeIcsJZ6COX5kvhiJroFqCM= -github.com/strangelove-ventures/packet-forward-middleware/v4 v4.0.5/go.mod h1:4zAtg449/JISRmf+sbmqolqSLP+QJBh+EtWkWtt/AKE= github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= @@ -1773,8 +1772,12 @@ google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210126160654-44e461bb6506/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 h1:KpwkzHKEF7B9Zxg18WzOa7djJ+Ha5DzthMyZYQfEn2A= -google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU= +google.golang.org/genproto v0.0.0-20230726155614-23370e0ffb3e h1:xIXmWJ303kJCuogpj0bHq+dcjcZHU+XFyc1I0Yl9cRg= +google.golang.org/genproto v0.0.0-20230726155614-23370e0ffb3e/go.mod h1:0ggbjUrZYpy1q+ANUS30SEoGZ53cdfwtbuG7Ptgy108= +google.golang.org/genproto/googleapis/api v0.0.0-20230706204954-ccb25ca9f130 h1:XVeBY8d/FaK4848myy41HBqnDwvxeV3zMZhwN1TvAMU= +google.golang.org/genproto/googleapis/api v0.0.0-20230706204954-ccb25ca9f130/go.mod h1:mPBs5jNgx2GuQGvFwUvVKqtn6HsUw9nP64BedgvqEsQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230706204954-ccb25ca9f130 h1:2FZP5XuJY9zQyGM5N0rtovnoXjiMUEIUMvw0m9wlpLc= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230706204954-ccb25ca9f130/go.mod h1:8mL13HKkDa+IuJ8yruA3ci0q+0vsUz4m//+ottjwS5o= google.golang.org/grpc v1.33.2 h1:EQyQC3sa8M+p6Ulc8yy9SWSS2GVwyRc83gAbG8lrl4o= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= diff --git a/proto/osmosis/concentrated-liquidity/gov.proto b/proto/osmosis/concentrated-liquidity/gov.proto index 4ae68f117f7..7917d3e61c2 100644 --- a/proto/osmosis/concentrated-liquidity/gov.proto +++ b/proto/osmosis/concentrated-liquidity/gov.proto @@ -51,11 +51,7 @@ message PoolRecord { string denom0 = 1 [ (gogoproto.moretags) = "yaml:\"denom0\"" ]; string denom1 = 2 [ (gogoproto.moretags) = "yaml:\"denom1\"" ]; uint64 tick_spacing = 3 [ (gogoproto.moretags) = "yaml:\"tick_spacing\"" ]; - string exponent_at_price_one = 4 [ - (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", - (gogoproto.moretags) = "yaml:\"exponent_at_price_one\"", - (gogoproto.nullable) = false - ]; + reserved 4; string spread_factor = 5 [ (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", (gogoproto.moretags) = "yaml:\"spread_factor\"", diff --git a/proto/osmosis/gamm/v1beta1/gov.proto b/proto/osmosis/gamm/v1beta1/gov.proto index 9ba81f96e58..87599a8d578 100644 --- a/proto/osmosis/gamm/v1beta1/gov.proto +++ b/proto/osmosis/gamm/v1beta1/gov.proto @@ -58,3 +58,56 @@ message UpdateMigrationRecordsProposal { repeated BalancerToConcentratedPoolLink records = 3 [ (gogoproto.nullable) = false ]; } +message PoolRecordWithCFMMLink { + option (gogoproto.equal) = true; + + string denom0 = 1 [ (gogoproto.moretags) = "yaml:\"denom0\"" ]; + string denom1 = 2 [ (gogoproto.moretags) = "yaml:\"denom1\"" ]; + uint64 tick_spacing = 3 [ (gogoproto.moretags) = "yaml:\"tick_spacing\"" ]; + string exponent_at_price_one = 4 [ + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", + (gogoproto.moretags) = "yaml:\"exponent_at_price_one\"", + (gogoproto.nullable) = false + ]; + string spread_factor = 5 [ + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", + (gogoproto.moretags) = "yaml:\"spread_factor\"", + (gogoproto.nullable) = false + ]; + uint64 balancer_pool_id = 6 + [ (gogoproto.moretags) = "yaml:\"balancer_pool_id\"" ]; +} + +// CreateConcentratedLiquidityPoolsAndLinktoCFMMProposal is a gov Content type +// for creating concentrated liquidity pools and linking it to a CFMM pool. +message CreateConcentratedLiquidityPoolsAndLinktoCFMMProposal { + option (gogoproto.equal) = true; + option (gogoproto.goproto_getters) = false; + option (gogoproto.goproto_stringer) = false; + option (amino.name) = + "osmosis/CreateConcentratedLiquidityPoolsAndLinktoCFMMProposal"; + option (cosmos_proto.implements_interface) = "cosmos.gov.v1beta1.Content"; + + string title = 1; + string description = 2; + + repeated PoolRecordWithCFMMLink pool_records_with_cfmm_link = 3 [ + (gogoproto.moretags) = "yaml:\"create_cl_pool_and_link_to_cfmm\"", + (gogoproto.nullable) = false + ]; +} + +// SetScalingFactorControllerProposal is a gov Content type for updating the +// scaling factor controller address of a stableswap pool +message SetScalingFactorControllerProposal { + option (gogoproto.equal) = true; + option (gogoproto.goproto_getters) = false; + option (gogoproto.goproto_stringer) = false; + option (amino.name) = "osmosis/SetScalingFactorControllerProposal"; + option (cosmos_proto.implements_interface) = "cosmos.gov.v1beta1.Content"; + + string title = 1; + string description = 2; + uint64 pool_id = 3; + string controller_address = 4; +} \ No newline at end of file diff --git a/tests/e2e/configurer/base.go b/tests/e2e/configurer/base.go index b39f0ee5c10..f6c7ecb4b9f 100644 --- a/tests/e2e/configurer/base.go +++ b/tests/e2e/configurer/base.go @@ -8,6 +8,7 @@ import ( "os" "path" "path/filepath" + "sync" "testing" "time" @@ -75,18 +76,29 @@ func (bc *baseConfigurer) RunValidators() error { func (bc *baseConfigurer) runValidators(chainConfig *chain.Config) error { bc.t.Logf("starting %s validator containers...", chainConfig.Id) - errCh := make(chan error) // Channel to collect errors + var wg sync.WaitGroup + errCh := make(chan error, len(chainConfig.NodeConfigs)) // Buffer the channel to avoid blocking + + // Increment the WaitGroup counter for each node + wg.Add(len(chainConfig.NodeConfigs)) // Iterate over each node for _, node := range chainConfig.NodeConfigs { go func(n *chain.NodeConfig) { + defer wg.Done() // Decrement the WaitGroup counter when the goroutine is done errCh <- n.Run() // Run the node and send any error to the channel }(node) } - // Wait for goroutines to finish and collect errors - for range chainConfig.NodeConfigs { - if err := <-errCh; err != nil { + // Wait for all goroutines to finish + wg.Wait() + + // Close the error channel since all goroutines are done sending errors + close(errCh) + + // Collect errors from the channel + for err := range errCh { + if err != nil { return err } } @@ -172,8 +184,8 @@ func (bc *baseConfigurer) runIBCRelayer(chainConfigA *chain.Config, chainConfigB return status == "success" && len(chains) == 2 }, - 5*time.Minute, - time.Second, + time.Minute, + 10*time.Millisecond, "hermes relayer not healthy") bc.t.Logf("started Hermes relayer container: %s", hermesResource.Container.ID) diff --git a/tests/e2e/configurer/chain/chain.go b/tests/e2e/configurer/chain/chain.go index ce318fbc789..268f6674b8e 100644 --- a/tests/e2e/configurer/chain/chain.go +++ b/tests/e2e/configurer/chain/chain.go @@ -193,6 +193,14 @@ func (c *Config) SendIBC(dstChain *Config, recipient string, token sdk.Coin) { _, _, err = c.containerManager.ExecHermesCmd(c.t, cmd, "SUCCESS") require.NoError(c.t, err) + cmd = []string{"hermes", "clear", "packets", "--chain", dstChain.Id, "--port", "transfer", "--channel", "channel-0"} + _, _, err = c.containerManager.ExecHermesCmd(c.t, cmd, "SUCCESS") + require.NoError(c.t, err) + + cmd = []string{"hermes", "clear", "packets", "--chain", c.Id, "--port", "transfer", "--channel", "channel-0"} + _, _, err = c.containerManager.ExecHermesCmd(c.t, cmd, "SUCCESS") + require.NoError(c.t, err) + require.Eventually( c.t, func() bool { @@ -211,8 +219,8 @@ func (c *Config) SendIBC(dstChain *Config, recipient string, token sdk.Coin) { return false } }, - 5*time.Minute, - time.Second, + 1*time.Minute, + 10*time.Millisecond, "tx not received on destination chain", ) diff --git a/tests/e2e/configurer/chain/commands.go b/tests/e2e/configurer/chain/commands.go index 8571855d1f2..419cde40ada 100644 --- a/tests/e2e/configurer/chain/commands.go +++ b/tests/e2e/configurer/chain/commands.go @@ -259,6 +259,14 @@ func (n *NodeConfig) SendIBCTransfer(dstChain *Config, from, recipient, memo str _, _, err := n.containerManager.ExecHermesCmd(n.t, cmd, "SUCCESS") require.NoError(n.t, err) + cmd = []string{"hermes", "clear", "packets", "--chain", dstChain.Id, "--port", "transfer", "--channel", "channel-0"} + _, _, err = n.containerManager.ExecHermesCmd(n.t, cmd, "SUCCESS") + require.NoError(n.t, err) + + cmd = []string{"hermes", "clear", "packets", "--chain", n.chainId, "--port", "transfer", "--channel", "channel-0"} + _, _, err = n.containerManager.ExecHermesCmd(n.t, cmd, "SUCCESS") + require.NoError(n.t, err) + n.LogActionF("successfully submitted sent IBC transfer") } @@ -333,7 +341,7 @@ func (n *NodeConfig) SubmitSuperfluidProposal(asset string, initialDeposit sdk.C func (n *NodeConfig) SubmitCreateConcentratedPoolProposal(initialDeposit sdk.Coin) int { n.LogActionF("Creating concentrated liquidity pool") - cmd := []string{"osmosisd", "tx", "gov", "submit-proposal", "create-concentratedliquidity-pool-proposal", "--pool-records=stake,uosmo,100,-6,0.001", "--title=\"create concentrated pool\"", "--description=\"create concentrated pool", "--from=val", fmt.Sprintf("--deposit=%s", initialDeposit)} + cmd := []string{"osmosisd", "tx", "gov", "submit-proposal", "create-concentratedliquidity-pool-proposal", "--pool-records=stake,uosmo,100,0.001", "--title=\"create concentrated pool\"", "--description=\"create concentrated pool", "--from=val", fmt.Sprintf("--deposit=%s", initialDeposit)} resp, _, err := n.containerManager.ExecTxCmd(n.t, n.chainId, n.Name, cmd) require.NoError(n.t, err) // Extract the proposal ID from the response @@ -681,8 +689,8 @@ func (n *NodeConfig) SendIBC(dstChain *Config, recipient string, token sdk.Coin) return false } }, - 5*time.Minute, - time.Second, + time.Minute, + 10*time.Millisecond, "tx not received on destination chain", ) @@ -821,6 +829,6 @@ func (n *NodeConfig) ParamChangeProposal(subspace, key string, value []byte, cha return false } return status == proposalStatusPassed - }, time.Minute*30, time.Millisecond*500) + }, time.Minute, 10*time.Millisecond) return nil } diff --git a/tests/e2e/configurer/chain/node.go b/tests/e2e/configurer/chain/node.go index 7fd6fd1cc63..50cbbb50333 100644 --- a/tests/e2e/configurer/chain/node.go +++ b/tests/e2e/configurer/chain/node.go @@ -47,35 +47,63 @@ func NewNodeConfig(t *testing.T, initNode *initialization.Node, initConfig *init // The node configuration must be already added to the chain config prior to calling this // method. func (n *NodeConfig) Run() error { - n.t.Logf("starting node container: %s", n.Name) - resource, err := n.containerManager.RunNodeResource(n.chainId, n.Name, n.ConfigDir) - if err != nil { - return err - } + maxRetries := 3 + currentRetry := 0 + + for currentRetry < maxRetries { + n.t.Logf("starting node container: %s", n.Name) + resource, err := n.containerManager.RunNodeResource(n.chainId, n.Name, n.ConfigDir) + if err != nil { + return err + } - hostPort := resource.GetHostPort("26657/tcp") - rpcClient, err := rpchttp.New("tcp://"+hostPort, "/websocket") - if err != nil { - return err - } + hostPort := resource.GetHostPort("26657/tcp") + rpcClient, err := rpchttp.New("tcp://"+hostPort, "/websocket") + if err != nil { + return err + } - n.rpcClient = rpcClient + n.rpcClient = rpcClient + + success := false + timeout := time.After(time.Second * 20) + ticker := time.NewTicker(10 * time.Millisecond) + defer ticker.Stop() + + for { + select { + case <-timeout: + n.t.Logf("Osmosis node failed to produce blocks") + break + case <-ticker.C: + _, err := n.QueryCurrentHeight() + if err == nil { + n.t.Logf("started node container: %s", n.Name) + success = true + break + } + } + + if success { + break + } + } - require.Eventually( - n.t, - func() bool { - // This fails if unsuccessful. - _, err := n.QueryCurrentHeight() + if success { + break + } else { + n.t.Logf("failed to start node container, retrying... (%d/%d)", currentRetry+1, maxRetries) + err := n.containerManager.RemoveNodeResource(n.Name) if err != nil { - return false + return err } - n.t.Logf("started node container: %s", n.Name) - return true - }, - 2*time.Minute, - time.Second, - "Osmosis node failed to produce blocks", - ) + currentRetry++ + } + } + + if currentRetry >= maxRetries { + return fmt.Errorf("failed to start node container after %d retries", maxRetries) + } if err := n.extractOperatorAddressIfValidator(); err != nil { return err diff --git a/tests/e2e/configurer/chain/queries.go b/tests/e2e/configurer/chain/queries.go index 0fb7a165d98..759dc7a12e1 100644 --- a/tests/e2e/configurer/chain/queries.go +++ b/tests/e2e/configurer/chain/queries.go @@ -231,7 +231,7 @@ func (n *NodeConfig) QueryGRPCGateway(path string, parameters ...string) ([]byte } return resp.StatusCode != http.StatusServiceUnavailable - }, time.Minute, time.Millisecond*10, "failed to execute HTTP request") + }, time.Minute, 10*time.Millisecond, "failed to execute HTTP request") defer resp.Body.Close() diff --git a/tests/e2e/containers/containers.go b/tests/e2e/containers/containers.go index b9f86e8049c..93a9242eb29 100644 --- a/tests/e2e/containers/containers.go +++ b/tests/e2e/containers/containers.go @@ -8,6 +8,7 @@ import ( "regexp" "strconv" "strings" + "sync" "testing" "time" @@ -49,6 +50,7 @@ type Manager struct { pool *dockertest.Pool network *dockertest.Network resources map[string]*dockertest.Resource + resourcesMutex sync.RWMutex isDebugLogEnabled bool } @@ -121,7 +123,7 @@ func (m *Manager) ExecCmd(t *testing.T, containerName string, command []string, errBuf bytes.Buffer ) - ctx, cancel := context.WithTimeout(context.Background(), 3*time.Minute) + ctx, cancel := context.WithTimeout(context.Background(), time.Minute) defer cancel() if m.isDebugLogEnabled { @@ -218,7 +220,7 @@ func (m *Manager) ExecCmd(t *testing.T, containerName string, command []string, return true }, time.Minute, - 50*time.Millisecond, + 10*time.Millisecond, fmt.Sprintf("success condition (%s) was not met.\nstdout:\n %s\nstderr:\n %s\n", success, outBuf.String(), errBuf.String()), ) @@ -297,7 +299,9 @@ func (m *Manager) RunNodeResource(chainId string, containerName, valCondifDir st return nil, err } + m.resourcesMutex.Lock() m.resources[containerName] = resource + m.resourcesMutex.Unlock() return resource, nil } diff --git a/tests/e2e/e2e_setup_test.go b/tests/e2e/e2e_setup_test.go index 979a88879ba..6662a577f8e 100644 --- a/tests/e2e/e2e_setup_test.go +++ b/tests/e2e/e2e_setup_test.go @@ -3,6 +3,7 @@ package e2e import ( "os" "strconv" + "sync" "testing" "github.com/stretchr/testify/suite" @@ -34,6 +35,7 @@ type IntegrationTestSuite struct { skipUpgrade bool skipIBC bool skipStateSync bool + mutex sync.Mutex } func TestIntegrationTestSuite(t *testing.T) { diff --git a/tests/e2e/e2e_test.go b/tests/e2e/e2e_test.go index 81f2b06814d..b67d061d20e 100644 --- a/tests/e2e/e2e_test.go +++ b/tests/e2e/e2e_test.go @@ -3,6 +3,7 @@ package e2e import ( "encoding/json" "fmt" + "github.com/cosmos/cosmos-sdk/types/address" "os" "path/filepath" "strconv" @@ -14,7 +15,7 @@ import ( transfertypes "github.com/cosmos/ibc-go/v4/modules/apps/transfer/types" "github.com/iancoleman/orderedmap" - packetforwardingtypes "github.com/strangelove-ventures/packet-forward-middleware/v4/router/types" + packetforwardingtypes "github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v4/router/types" "github.com/osmosis-labs/osmosis/osmomath" ibchookskeeper "github.com/osmosis-labs/osmosis/x/ibc-hooks/keeper" @@ -1195,7 +1196,7 @@ func (s *IntegrationTestSuite) IBCTokenTransferRateLimiting() { s.Eventually(func() bool { val := chainANode.QueryParams(ibcratelimittypes.ModuleName, string(ibcratelimittypes.KeyContractAddress)) return strings.Contains(val, param) - }, time.Second*30, time.Millisecond*500) + }, time.Second*30, time.Second) } } @@ -1228,7 +1229,7 @@ func (s *IntegrationTestSuite) IBCWasmHooks() { // check the balance of the contract denomTrace := transfertypes.ParseDenomTrace(transfertypes.GetPrefixedDenom("transfer", "channel-0", "uosmo")) ibcDenom := denomTrace.IBCDenom() - s.CheckBalance(chainANode, contractAddr, ibcDenom, transferAmount) + s.CallCheckBalance(chainANode, contractAddr, ibcDenom, transferAmount) // sender wasm addr senderBech32, err := ibchookskeeper.DeriveIntermediateSender("channel-0", validatorAddr, "osmo") @@ -1301,11 +1302,20 @@ func (s *IntegrationTestSuite) PacketForwarding() { chainANode.SendIBCTransfer(chainB, validatorAddr, validatorAddr, string(forwardMemo), coin) // check the balance of the contract - s.CheckBalance(chainANode, contractAddr, "uosmo", transferAmount) + s.CallCheckBalance(chainANode, contractAddr, "uosmo", transferAmount) + + // Getting the sender as set by PFM + senderStr := fmt.Sprintf("channel-0/%s", validatorAddr) + senderHash32 := address.Hash(packetforwardingtypes.ModuleName, []byte(senderStr)) // typo intended + sender := sdk.AccAddress(senderHash32[:20]) + bech32Prefix := "osmo" + pfmSender, err := sdk.Bech32ifyAddressBytes(bech32Prefix, sender) + s.Require().NoError(err) // sender wasm addr - senderBech32, err := ibchookskeeper.DeriveIntermediateSender("channel-0", validatorAddr, "osmo") + senderBech32, err := ibchookskeeper.DeriveIntermediateSender("channel-0", pfmSender, "osmo") s.Require().NoError(err) + s.Require().Eventually(func() bool { response, err := chainANode.QueryWasmSmartObject(contractAddr, fmt.Sprintf(`{"get_count": {"addr": "%s"}}`, senderBech32)) if err != nil { @@ -1615,8 +1625,8 @@ func (s *IntegrationTestSuite) StateSync() { s.Require().NoError(err) return stateSyncNodeHeight == runningNodeHeight }, - 3*time.Minute, - 500*time.Millisecond, + 1*time.Minute, + time.Second, ) // stop the state synching node. diff --git a/tests/e2e/helpers_e2e_test.go b/tests/e2e/helpers_e2e_test.go index 483fdcad15c..728b0223036 100644 --- a/tests/e2e/helpers_e2e_test.go +++ b/tests/e2e/helpers_e2e_test.go @@ -107,6 +107,12 @@ func (s *IntegrationTestSuite) validateCLPosition(position model.Position, poolI s.Require().Equal(position.UpperTick, upperTick) } +func (s *IntegrationTestSuite) CallCheckBalance(node *chain.NodeConfig, addr, denom string, amount int64) { + s.mutex.Lock() + defer s.mutex.Unlock() + s.CheckBalance(node, addr, denom, amount) +} + // CheckBalance Checks the balance of an address func (s *IntegrationTestSuite) CheckBalance(node *chain.NodeConfig, addr, denom string, amount int64) { // check the balance of the contract @@ -125,7 +131,7 @@ func (s *IntegrationTestSuite) CheckBalance(node *chain.NodeConfig, addr, denom } return false }, - 2*time.Minute, + 1*time.Minute, 10*time.Millisecond, ) } diff --git a/tests/e2e/scripts/hermes_bootstrap.sh b/tests/e2e/scripts/hermes_bootstrap.sh index f61feeddee5..dce124221d4 100644 --- a/tests/e2e/scripts/hermes_bootstrap.sh +++ b/tests/e2e/scripts/hermes_bootstrap.sh @@ -17,7 +17,7 @@ enabled = true refresh = true misbehaviour = true [mode.connections] -enabled = false +enabled = true [mode.channels] enabled = true [mode.packets] diff --git a/tests/ibc-hooks/bytecode/swaprouter.wasm b/tests/ibc-hooks/bytecode/swaprouter.wasm index 29288d42fa0..124d0313572 100644 Binary files a/tests/ibc-hooks/bytecode/swaprouter.wasm and b/tests/ibc-hooks/bytecode/swaprouter.wasm differ diff --git a/x/concentrated-liquidity/client/cli/tx.go b/x/concentrated-liquidity/client/cli/tx.go index 29faf238546..97b838a0d75 100644 --- a/x/concentrated-liquidity/client/cli/tx.go +++ b/x/concentrated-liquidity/client/cli/tx.go @@ -102,9 +102,9 @@ func NewCmdCreateConcentratedLiquidityPoolsProposal() *cobra.Command { Long: strings.TrimSpace(`Submit a create concentrated liquidity pool proposal. Passing in FlagPoolRecords separated by commas would be parsed automatically to pairs of pool records. -Ex) --pool-records=uion,uosmo,100,-6,0.003,stake,uosmo,1000,-6,0.005 -> -[uion<>uosmo, tickSpacing 100, exponentAtPriceOne -6, spreadFactor 0.3%] -[stake<>uosmo, tickSpacing 1000, exponentAtPriceOne -6, spreadFactor 0.5%] +Ex) --pool-records=uion,uosmo,100,0.003,stake,uosmo,1000,0.005 -> +[uion<>uosmo, tickSpacing 100, spreadFactor 0.3%] +[stake<>uosmo, tickSpacing 1000, spreadFactor 0.5%] `), RunE: func(cmd *cobra.Command, args []string) error { @@ -300,8 +300,9 @@ func parsePoolRecords(cmd *cobra.Command) ([]types.PoolRecord, error) { poolRecords := strings.Split(poolRecordsStr, ",") - if len(poolRecords)%5 != 0 { - return nil, fmt.Errorf("poolRecords must be a list of denom0, denom1, tickSpacing, exponentAtPriceOne, and spreadFactor") + if len(poolRecords)%4 != 0 { + return nil, fmt.Errorf("poolRecords must be a list of denom0, denom1, tickSpacing, and spreadFactor") + } finalPoolRecords := []types.PoolRecord{} @@ -315,28 +316,21 @@ func parsePoolRecords(cmd *cobra.Command) ([]types.PoolRecord, error) { return nil, err } - exponentAtPriceOneStr := poolRecords[i+3] - exponentAtPriceOne, ok := sdk.NewIntFromString(exponentAtPriceOneStr) - if !ok { - return nil, fmt.Errorf("invalid exponentAtPriceOne: %s", exponentAtPriceOneStr) - } - - spreadFactorStr := poolRecords[i+4] + spreadFactorStr := poolRecords[i+3] spreadFactor, err := sdk.NewDecFromStr(spreadFactorStr) if err != nil { return nil, err } finalPoolRecords = append(finalPoolRecords, types.PoolRecord{ - Denom0: denom0, - Denom1: denom1, - TickSpacing: uint64(tickSpacing), - ExponentAtPriceOne: exponentAtPriceOne, - SpreadFactor: spreadFactor, + Denom0: denom0, + Denom1: denom1, + TickSpacing: uint64(tickSpacing), + SpreadFactor: spreadFactor, }) - // increase counter by the next 5 - i = i + 5 + // increase counter by the next 4 + i = i + 4 } return finalPoolRecords, nil diff --git a/x/concentrated-liquidity/genesis.go b/x/concentrated-liquidity/genesis.go index f88b0d05ef5..f933a9f3913 100644 --- a/x/concentrated-liquidity/genesis.go +++ b/x/concentrated-liquidity/genesis.go @@ -154,6 +154,7 @@ func (k Keeper) ExportGenesis(ctx sdk.Context) *genesis.GenesisState { incentivesAccumObject := make([]genesis.AccumObject, len(incentivesAccum)) for i, incentiveAccum := range incentivesAccum { incentiveAccumTotalShares := incentiveAccum.GetTotalShares() + genesisAccum := genesis.AccumObject{ Name: incentiveAccum.GetName(), AccumContent: &accum.AccumulatorContent{ diff --git a/x/concentrated-liquidity/position_test.go b/x/concentrated-liquidity/position_test.go index 81df02c09d2..9a3c33b5547 100644 --- a/x/concentrated-liquidity/position_test.go +++ b/x/concentrated-liquidity/position_test.go @@ -2462,6 +2462,15 @@ func (s *KeeperTestSuite) TestMultipleRanges() { }, rangeTestParams: DefaultRangeTestParams, }, + "two adjacent ranges (flipped order)": { + // Note: this setup covers both edge cases where initial interval accumulation is negative + // for spread rewards and incentives + tickRanges: [][]int64{ + {10000, 20000}, + {-10000, 10000}, + }, + rangeTestParams: DefaultRangeTestParams, + }, "two adjacent ranges with current tick smaller than both": { tickRanges: [][]int64{ {-10000, 10000}, diff --git a/x/concentrated-liquidity/types/gov.go b/x/concentrated-liquidity/types/gov.go index f6dcf5d3070..cf921b8eb94 100644 --- a/x/concentrated-liquidity/types/gov.go +++ b/x/concentrated-liquidity/types/gov.go @@ -83,7 +83,7 @@ func (p *CreateConcentratedLiquidityPoolsProposal) ValidateBasic() error { func (p CreateConcentratedLiquidityPoolsProposal) String() string { recordsStr := "" for _, record := range p.PoolRecords { - recordsStr = recordsStr + fmt.Sprintf("(Denom0: %s, Denom1: %s, TickSpacing: %d, ExponentAtPriceOne: %d, SpreadFactor: %d) ", record.Denom0, record.Denom1, record.TickSpacing, record.ExponentAtPriceOne, record.SpreadFactor) + recordsStr = recordsStr + fmt.Sprintf("(Denom0: %s, Denom1: %s, TickSpacing: %d, SpreadFactor: %d) ", record.Denom0, record.Denom1, record.TickSpacing, record.SpreadFactor) } var b strings.Builder diff --git a/x/concentrated-liquidity/types/gov.pb.go b/x/concentrated-liquidity/types/gov.pb.go index 51663bbd037..b710c9c83aa 100644 --- a/x/concentrated-liquidity/types/gov.pb.go +++ b/x/concentrated-liquidity/types/gov.pb.go @@ -164,11 +164,10 @@ func (m *PoolIdToTickSpacingRecord) GetNewTickSpacing() uint64 { } type PoolRecord struct { - Denom0 string `protobuf:"bytes,1,opt,name=denom0,proto3" json:"denom0,omitempty" yaml:"denom0"` - Denom1 string `protobuf:"bytes,2,opt,name=denom1,proto3" json:"denom1,omitempty" yaml:"denom1"` - TickSpacing uint64 `protobuf:"varint,3,opt,name=tick_spacing,json=tickSpacing,proto3" json:"tick_spacing,omitempty" yaml:"tick_spacing"` - ExponentAtPriceOne github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,4,opt,name=exponent_at_price_one,json=exponentAtPriceOne,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"exponent_at_price_one" yaml:"exponent_at_price_one"` - SpreadFactor github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,5,opt,name=spread_factor,json=spreadFactor,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"spread_factor" yaml:"spread_factor"` + Denom0 string `protobuf:"bytes,1,opt,name=denom0,proto3" json:"denom0,omitempty" yaml:"denom0"` + Denom1 string `protobuf:"bytes,2,opt,name=denom1,proto3" json:"denom1,omitempty" yaml:"denom1"` + TickSpacing uint64 `protobuf:"varint,3,opt,name=tick_spacing,json=tickSpacing,proto3" json:"tick_spacing,omitempty" yaml:"tick_spacing"` + SpreadFactor github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,5,opt,name=spread_factor,json=spreadFactor,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"spread_factor" yaml:"spread_factor"` } func (m *PoolRecord) Reset() { *m = PoolRecord{} } @@ -237,44 +236,41 @@ func init() { } var fileDescriptor_e6d167276ceeedc2 = []byte{ - // 584 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x54, 0x41, 0x8b, 0xd3, 0x40, - 0x14, 0x4e, 0x6c, 0xb7, 0xe2, 0xb4, 0x2b, 0x1a, 0x2b, 0x5b, 0x77, 0x25, 0x29, 0x01, 0xa5, 0x1e, - 0x9a, 0x18, 0x3d, 0x08, 0x3d, 0x69, 0x77, 0x59, 0x58, 0x10, 0x2d, 0x71, 0x4f, 0x22, 0x84, 0x74, - 0x32, 0xd6, 0xa1, 0xe9, 0x4c, 0x36, 0x33, 0xdb, 0xdd, 0x1e, 0xbd, 0x09, 0x5e, 0xbc, 0x08, 0x1e, - 0xfb, 0x73, 0xf6, 0xb8, 0x47, 0xf1, 0x10, 0xa4, 0xbd, 0x78, 0xb5, 0xbf, 0x40, 0x32, 0x93, 0xb6, - 0xe9, 0x6a, 0xc1, 0x65, 0x4f, 0xc9, 0x7b, 0xf3, 0xbd, 0xf7, 0x7d, 0xdf, 0x7b, 0xc3, 0x80, 0x06, - 0x65, 0x03, 0xca, 0x30, 0xb3, 0x21, 0x25, 0x10, 0x11, 0x1e, 0xfb, 0x1c, 0x05, 0xcd, 0x10, 0x1f, - 0x1d, 0xe3, 0x00, 0xf3, 0x91, 0xdd, 0xa3, 0x43, 0x2b, 0x8a, 0x29, 0xa7, 0xda, 0x83, 0x0c, 0x69, - 0xe5, 0x91, 0x0b, 0xa0, 0x35, 0x74, 0xba, 0x88, 0xfb, 0xce, 0x76, 0xb5, 0x47, 0x7b, 0x54, 0x54, - 0xd8, 0xe9, 0x9f, 0x2c, 0x36, 0xa7, 0x2a, 0x68, 0xec, 0xc6, 0xc8, 0xe7, 0x68, 0x37, 0x57, 0xfd, - 0x72, 0x5e, 0xdd, 0xa1, 0x34, 0x64, 0x9d, 0x98, 0x46, 0x94, 0xf9, 0xa1, 0x56, 0x05, 0x1b, 0x1c, - 0xf3, 0x10, 0xd5, 0xd4, 0xba, 0xda, 0xb8, 0xe1, 0xca, 0x40, 0xab, 0x83, 0x72, 0x80, 0x18, 0x8c, - 0x71, 0xc4, 0x31, 0x25, 0xb5, 0x6b, 0xe2, 0x2c, 0x9f, 0xd2, 0x8e, 0x40, 0x25, 0xa2, 0x34, 0xf4, - 0x62, 0x04, 0x69, 0x1c, 0xb0, 0x5a, 0xa1, 0x5e, 0x68, 0x94, 0x9f, 0x38, 0xd6, 0x7f, 0x09, 0xb7, - 0x52, 0x0d, 0xae, 0xa8, 0x6c, 0xef, 0x9c, 0x25, 0x86, 0x32, 0x4b, 0x8c, 0x3b, 0x23, 0x7f, 0x10, - 0xb6, 0xcc, 0x7c, 0x53, 0xd3, 0x2d, 0x47, 0x0b, 0x20, 0x6b, 0x55, 0x3e, 0x8d, 0x0d, 0xe5, 0xdb, - 0xd8, 0x50, 0x7e, 0x8d, 0x0d, 0xd5, 0xfc, 0xad, 0x82, 0x9d, 0x43, 0x0c, 0xfb, 0x6f, 0x22, 0x1f, - 0x62, 0xd2, 0xdb, 0x43, 0x30, 0x46, 0x3e, 0x43, 0x57, 0x36, 0xf6, 0x59, 0x05, 0x86, 0x10, 0x81, - 0x03, 0x8f, 0x53, 0x8f, 0x63, 0xd8, 0xf7, 0x98, 0xe4, 0xb8, 0x60, 0xf6, 0xf9, 0x25, 0xcc, 0x1e, - 0x04, 0x87, 0x34, 0xa7, 0x36, 0xf3, 0x5e, 0x4c, 0xbd, 0xbb, 0xdb, 0xd1, 0x3a, 0xc0, 0x45, 0xcf, - 0x01, 0xb8, 0xb7, 0xb6, 0x99, 0xb6, 0x05, 0xae, 0x67, 0xba, 0x85, 0xe5, 0xa2, 0x5b, 0x92, 0x7d, - 0xb5, 0x06, 0xb8, 0x45, 0xd0, 0xc9, 0x8a, 0x13, 0x61, 0xbc, 0xe8, 0xde, 0x24, 0xe8, 0x24, 0xd7, - 0xa8, 0x55, 0x14, 0x2c, 0x5f, 0x0b, 0x00, 0x2c, 0x17, 0xa4, 0x3d, 0x02, 0xa5, 0x00, 0x11, 0x3a, - 0x78, 0x2c, 0x27, 0xd9, 0xbe, 0x3d, 0x4b, 0x8c, 0x4d, 0xb9, 0x2c, 0x99, 0x37, 0xdd, 0x0c, 0xb0, - 0x80, 0x3a, 0x72, 0xb0, 0x7f, 0x41, 0x9d, 0x39, 0xd4, 0xd1, 0x5a, 0xa0, 0xb2, 0x22, 0xa8, 0x90, - 0x0a, 0x6a, 0x6f, 0x2d, 0x2f, 0x42, 0xfe, 0xd4, 0x74, 0xcb, 0x7c, 0x29, 0x53, 0xfb, 0xa8, 0x82, - 0xbb, 0xe8, 0x34, 0xa2, 0x04, 0x11, 0xee, 0xf9, 0xdc, 0x8b, 0x62, 0x0c, 0x91, 0x47, 0x09, 0xaa, - 0x15, 0x05, 0xed, 0xab, 0x74, 0xac, 0x3f, 0x12, 0xe3, 0x61, 0x0f, 0xf3, 0x0f, 0xc7, 0x5d, 0x0b, - 0xd2, 0x81, 0x0d, 0xc5, 0xae, 0xb2, 0x4f, 0x93, 0x05, 0x7d, 0x9b, 0x8f, 0x22, 0xc4, 0xac, 0x03, - 0xc2, 0x67, 0x89, 0x71, 0x5f, 0x72, 0xfe, 0xb3, 0xa9, 0xe9, 0x6a, 0xf3, 0xfc, 0x0b, 0xde, 0x49, - 0xb3, 0xaf, 0x09, 0xd2, 0xfa, 0x60, 0x93, 0x45, 0x31, 0xf2, 0x03, 0xef, 0xbd, 0x0f, 0x39, 0x8d, - 0x6b, 0x1b, 0x82, 0x7a, 0xff, 0x12, 0xd4, 0x7b, 0x08, 0xce, 0x12, 0xa3, 0x2a, 0xa9, 0x57, 0x9a, - 0x99, 0x6e, 0x45, 0xc6, 0xfb, 0x22, 0x94, 0x7b, 0x69, 0xbf, 0x3b, 0x9b, 0xe8, 0xea, 0xf9, 0x44, - 0x57, 0x7f, 0x4e, 0x74, 0xf5, 0xcb, 0x54, 0x57, 0xce, 0xa7, 0xba, 0xf2, 0x7d, 0xaa, 0x2b, 0x6f, - 0xdb, 0x39, 0xb6, 0xec, 0x4e, 0x36, 0x43, 0xbf, 0xcb, 0xe6, 0x81, 0x3d, 0x74, 0x9e, 0xd9, 0xa7, - 0xeb, 0x9e, 0x1d, 0xa1, 0xa6, 0x5b, 0x12, 0x8f, 0xc7, 0xd3, 0x3f, 0x01, 0x00, 0x00, 0xff, 0xff, - 0x72, 0xf6, 0xcc, 0xa4, 0xa5, 0x04, 0x00, 0x00, + // 541 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x53, 0x4f, 0x8b, 0xd3, 0x4c, + 0x18, 0x4f, 0xb6, 0x69, 0xdf, 0xd7, 0x69, 0x57, 0xd6, 0x58, 0xd8, 0xba, 0x0b, 0x49, 0x09, 0x28, + 0xf5, 0xd0, 0xc4, 0xe8, 0x41, 0xe8, 0x49, 0xba, 0xcb, 0x82, 0xe2, 0x61, 0x89, 0x7b, 0x12, 0xa1, + 0xa4, 0x93, 0xb1, 0x0e, 0x4d, 0xf3, 0x64, 0x67, 0x66, 0xbb, 0xf6, 0x1b, 0x08, 0x5e, 0xbc, 0xe9, + 0xb1, 0x1f, 0x67, 0x8f, 0x7b, 0x14, 0x0f, 0x45, 0xda, 0x8b, 0x57, 0xfb, 0x09, 0xa4, 0x33, 0x69, + 0x9b, 0xae, 0x14, 0x14, 0x4f, 0xc9, 0x33, 0xf3, 0x7b, 0x7e, 0x7f, 0x9e, 0x99, 0x41, 0x0d, 0xe0, + 0x03, 0xe0, 0x94, 0x7b, 0x18, 0x12, 0x4c, 0x12, 0xc1, 0x42, 0x41, 0xa2, 0x66, 0x4c, 0xcf, 0x2f, + 0x68, 0x44, 0xc5, 0xc8, 0xeb, 0xc1, 0xd0, 0x4d, 0x19, 0x08, 0x30, 0xef, 0x67, 0x48, 0x37, 0x8f, + 0x5c, 0x01, 0xdd, 0xa1, 0xdf, 0x25, 0x22, 0xf4, 0x0f, 0xaa, 0x3d, 0xe8, 0x81, 0xec, 0xf0, 0x16, + 0x7f, 0xaa, 0xd9, 0x99, 0xe9, 0xa8, 0x71, 0xc4, 0x48, 0x28, 0xc8, 0x51, 0xae, 0xfb, 0xe5, 0xb2, + 0xfb, 0x14, 0x20, 0xe6, 0xa7, 0x0c, 0x52, 0xe0, 0x61, 0x6c, 0x56, 0x51, 0x51, 0x50, 0x11, 0x93, + 0x9a, 0x5e, 0xd7, 0x1b, 0xb7, 0x02, 0x55, 0x98, 0x75, 0x54, 0x8e, 0x08, 0xc7, 0x8c, 0xa6, 0x82, + 0x42, 0x52, 0xdb, 0x91, 0x7b, 0xf9, 0x25, 0xf3, 0x1c, 0x55, 0x52, 0x80, 0xb8, 0xc3, 0x08, 0x06, + 0x16, 0xf1, 0x5a, 0xa1, 0x5e, 0x68, 0x94, 0x1f, 0xfb, 0xee, 0x1f, 0x19, 0x77, 0x17, 0x1e, 0x02, + 0xd9, 0xd9, 0x3e, 0xbc, 0x9a, 0xd8, 0xda, 0x7c, 0x62, 0xdf, 0x1d, 0x85, 0x83, 0xb8, 0xe5, 0xe4, + 0x49, 0x9d, 0xa0, 0x9c, 0xae, 0x80, 0xbc, 0x55, 0xf9, 0x30, 0xb6, 0xb5, 0x2f, 0x63, 0x5b, 0xfb, + 0x31, 0xb6, 0x75, 0xe7, 0xa7, 0x8e, 0x0e, 0xcf, 0x28, 0xee, 0xbf, 0x4a, 0x43, 0x4c, 0x93, 0xde, + 0x31, 0xc1, 0x8c, 0x84, 0x9c, 0xfc, 0x73, 0xb0, 0x8f, 0x3a, 0xb2, 0xa5, 0x09, 0x1a, 0x75, 0x04, + 0x74, 0x04, 0xc5, 0xfd, 0x0e, 0x57, 0x1a, 0x37, 0xc2, 0x3e, 0xfb, 0x8b, 0xb0, 0xcf, 0xa3, 0x33, + 0xc8, 0xb9, 0xcd, 0xb2, 0x1b, 0x8b, 0xec, 0xc1, 0x41, 0xba, 0x0d, 0x70, 0x33, 0x73, 0x84, 0xee, + 0x6d, 0x25, 0x33, 0xf7, 0xd1, 0x7f, 0x99, 0x6f, 0x19, 0xd9, 0x08, 0x4a, 0x8a, 0xd7, 0x6c, 0xa0, + 0xbd, 0x84, 0x5c, 0x6e, 0x24, 0x91, 0xc1, 0x8d, 0xe0, 0x76, 0x42, 0x2e, 0x73, 0x44, 0x2d, 0x43, + 0xaa, 0x7c, 0xde, 0x41, 0x68, 0x7d, 0x40, 0xe6, 0x43, 0x54, 0x8a, 0x48, 0x02, 0x83, 0x47, 0x6a, + 0x92, 0xed, 0x3b, 0xf3, 0x89, 0xbd, 0xab, 0x0e, 0x4b, 0xad, 0x3b, 0x41, 0x06, 0x58, 0x41, 0x7d, + 0x35, 0xd8, 0xdf, 0xa0, 0xfe, 0x12, 0xea, 0x9b, 0x2d, 0x54, 0xd9, 0x30, 0x54, 0x58, 0x18, 0x6a, + 0xef, 0xaf, 0x2f, 0x42, 0x7e, 0xd7, 0x09, 0xca, 0x62, 0x6d, 0xd3, 0xec, 0xa3, 0x5d, 0x9e, 0x32, + 0x12, 0x46, 0x9d, 0xb7, 0x21, 0x16, 0xc0, 0x6a, 0x45, 0xa9, 0x76, 0xb2, 0x98, 0xe6, 0xb7, 0x89, + 0xfd, 0xa0, 0x47, 0xc5, 0xbb, 0x8b, 0xae, 0x8b, 0x61, 0xe0, 0x61, 0x79, 0x44, 0xd9, 0xa7, 0xc9, + 0xa3, 0xbe, 0x27, 0x46, 0x29, 0xe1, 0xee, 0x31, 0xc1, 0xf3, 0x89, 0x5d, 0x55, 0x52, 0x1b, 0x64, + 0x4e, 0x50, 0x51, 0xf5, 0x89, 0x2c, 0xd5, 0x4c, 0x5e, 0x18, 0xff, 0x1b, 0x7b, 0xc5, 0xf6, 0x9b, + 0xab, 0xa9, 0xa5, 0x5f, 0x4f, 0x2d, 0xfd, 0xfb, 0xd4, 0xd2, 0x3f, 0xcd, 0x2c, 0xed, 0x7a, 0x66, + 0x69, 0x5f, 0x67, 0x96, 0xf6, 0xba, 0x9d, 0xd3, 0xcc, 0x6e, 0x45, 0x33, 0x0e, 0xbb, 0x7c, 0x59, + 0x78, 0x43, 0xff, 0xa9, 0xf7, 0x7e, 0xdb, 0xc3, 0x97, 0x9e, 0xba, 0x25, 0xf9, 0x7c, 0x9f, 0xfc, + 0x0a, 0x00, 0x00, 0xff, 0xff, 0x1c, 0x38, 0xa8, 0xb5, 0x27, 0x04, 0x00, 0x00, } func (this *CreateConcentratedLiquidityPoolsProposal) Equal(that interface{}) bool { @@ -402,9 +398,6 @@ func (this *PoolRecord) Equal(that interface{}) bool { if this.TickSpacing != that1.TickSpacing { return false } - if !this.ExponentAtPriceOne.Equal(that1.ExponentAtPriceOne) { - return false - } if !this.SpreadFactor.Equal(that1.SpreadFactor) { return false } @@ -575,16 +568,6 @@ func (m *PoolRecord) MarshalToSizedBuffer(dAtA []byte) (int, error) { } i-- dAtA[i] = 0x2a - { - size := m.ExponentAtPriceOne.Size() - i -= size - if _, err := m.ExponentAtPriceOne.MarshalTo(dAtA[i:]); err != nil { - return 0, err - } - i = encodeVarintGov(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x22 if m.TickSpacing != 0 { i = encodeVarintGov(dAtA, i, uint64(m.TickSpacing)) i-- @@ -696,8 +679,6 @@ func (m *PoolRecord) Size() (n int) { if m.TickSpacing != 0 { n += 1 + sovGov(uint64(m.TickSpacing)) } - l = m.ExponentAtPriceOne.Size() - n += 1 + l + sovGov(uint64(l)) l = m.SpreadFactor.Size() n += 1 + l + sovGov(uint64(l)) return n @@ -1205,40 +1186,6 @@ func (m *PoolRecord) Unmarshal(dAtA []byte) error { break } } - case 4: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ExponentAtPriceOne", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGov - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthGov - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthGov - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if err := m.ExponentAtPriceOne.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex case 5: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field SpreadFactor", wireType) diff --git a/x/concentrated-liquidity/types/gov_test.go b/x/concentrated-liquidity/types/gov_test.go index 4a0ad7fade5..d12554289bb 100644 --- a/x/concentrated-liquidity/types/gov_test.go +++ b/x/concentrated-liquidity/types/gov_test.go @@ -13,25 +13,23 @@ import ( func TestCreateConcentratedLiquidityPoolsProposalMarshalUnmarshal(t *testing.T) { records := []types.PoolRecord{ { - Denom0: "uion", - Denom1: "uosmo", - TickSpacing: 100, - ExponentAtPriceOne: sdk.NewInt(-1), - SpreadFactor: sdk.MustNewDecFromStr("0.01"), + Denom0: "uion", + Denom1: "uosmo", + TickSpacing: 100, + SpreadFactor: sdk.MustNewDecFromStr("0.01"), }, { - Denom0: "stake", - Denom1: "uosmo", - TickSpacing: 1000, - ExponentAtPriceOne: sdk.NewInt(-5), - SpreadFactor: sdk.MustNewDecFromStr("0.02"), + Denom0: "stake", + Denom1: "uosmo", + TickSpacing: 1000, + SpreadFactor: sdk.MustNewDecFromStr("0.02"), }, { - Denom0: "ibc/27394FB092D2ECCD56123C74F36E4C1F926001CEADA9CA97EA622B25F41E5EB2", - Denom1: "uosmo", - TickSpacing: 10, - ExponentAtPriceOne: sdk.NewInt(-3), - SpreadFactor: sdk.MustNewDecFromStr("0.05"), + Denom0: "ibc/27394FB092D2ECCD56123C74F36E4C1F926001CEADA9CA97EA622B25F41E5EB2", + Denom1: "uosmo", + TickSpacing: 10, + + SpreadFactor: sdk.MustNewDecFromStr("0.05"), }, } @@ -111,11 +109,10 @@ func TestTickSpacingDecreaseProposalMarshalUnmarshal(t *testing.T) { func TestCreateConcentratedLiquidityPoolsProposal_ValidateBasic(t *testing.T) { baseRecord := types.PoolRecord{ - Denom0: "uion", - Denom1: "uosmo", - TickSpacing: 100, - ExponentAtPriceOne: sdk.NewInt(-1), - SpreadFactor: sdk.MustNewDecFromStr("0.01"), + Denom0: "uion", + Denom1: "uosmo", + TickSpacing: 100, + SpreadFactor: sdk.MustNewDecFromStr("0.01"), } withInvalidTickSpacing := func(record types.PoolRecord) types.PoolRecord { diff --git a/x/cosmwasmpool/model/pool.go b/x/cosmwasmpool/model/pool.go index 10014ca1a25..79b833a9196 100644 --- a/x/cosmwasmpool/model/pool.go +++ b/x/cosmwasmpool/model/pool.go @@ -71,7 +71,7 @@ func (p Pool) IsActive(ctx sdk.Context) bool { } // SpotPrice returns the spot price of the pool. -func (p Pool) SpotPrice(ctx sdk.Context, baseAssetDenom string, quoteAssetDenom string) (sdk.Dec, error) { +func (p Pool) SpotPrice(ctx sdk.Context, quoteAssetDenom string, baseAssetDenom string) (sdk.Dec, error) { request := msg.SpotPriceQueryMsg{ SpotPrice: msg.SpotPrice{ QuoteAssetDenom: quoteAssetDenom, diff --git a/x/gamm/client/cli/flags.go b/x/gamm/client/cli/flags.go index 29d6d610758..24a71f1f571 100644 --- a/x/gamm/client/cli/flags.go +++ b/x/gamm/client/cli/flags.go @@ -39,9 +39,12 @@ const ( // Will be parsed to []string. FlagSwapRouteDenoms = "swap-route-denoms" // FlagScalingFactors represents the flag name for the scaling factors. - FlagScalingFactors = "scaling-factors" + FlagScalingFactors = "scaling-factors" + FlagScalingFactorControllerAddress = "scaling-factor-controller-address" FlagMigrationRecords = "migration-records" + + FlagPoolRecords = "pool-records" ) type createBalancerPoolInputs struct { diff --git a/x/gamm/client/cli/tx.go b/x/gamm/client/cli/tx.go index 107a368d088..7d781345748 100644 --- a/x/gamm/client/cli/tx.go +++ b/x/gamm/client/cli/tx.go @@ -1,8 +1,10 @@ package cli import ( + "encoding/json" "errors" "fmt" + "os" "strconv" "strings" "time" @@ -295,6 +297,129 @@ Ex) 2,4,1,5 -> [(Balancer 2, CL 4), (Balancer 1, CL 5)] return cmd } +// NewCmdSubmitUpdateMigrationRecordsProposal implements a command handler for update migration records proposal +func NewCmdSubmitCreateCLPoolAndLinkToCFMMProposal() *cobra.Command { + cmd := &cobra.Command{ + Use: "create-cl-pool-and-cfmm-link [flags]", + Args: cobra.ExactArgs(0), + Short: "Submit a create clpool and link to cfmm proposal", + Long: strings.TrimSpace(`submit a proposal to create CL pool and link to Balancer pool.`), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + content, err := parseCreateConcentratedLiquidityPoolArgsToContent(cmd) + if err != nil { + return err + } + + from := clientCtx.GetFromAddress() + + depositStr, err := cmd.Flags().GetString(govcli.FlagDeposit) + if err != nil { + return err + } + deposit, err := sdk.ParseCoinsNormalized(depositStr) + if err != nil { + return err + } + + msg, err := govtypes.NewMsgSubmitProposal(content, deposit, from) + if err != nil { + return err + } + + if err = msg.ValidateBasic(); err != nil { + return err + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + cmd.Flags().String(govcli.FlagTitle, "", "title of proposal") + cmd.Flags().String(govcli.FlagDescription, "", "description of proposal") + cmd.Flags().String(govcli.FlagDeposit, "", "deposit of proposal") + cmd.Flags().Bool(govcli.FlagIsExpedited, false, "If true, makes the proposal an expedited one") + cmd.Flags().String(govcli.FlagProposal, "", "Proposal file path (if this path is given, other proposal flags are ignored)") + cmd.Flags().String(FlagPoolRecords, "", "The pool records array") + + return cmd +} + +// NewCmdSubmitSetScalingFactorControllerProposal implements a command handler for the set scaling factor controller proposal +func NewCmdSubmitSetScalingFactorControllerProposal() *cobra.Command { + cmd := &cobra.Command{ + Use: "set-scaling-factor-controller-proposal [flags]", + Args: cobra.ExactArgs(0), + Short: "Submit a set scaling factor controller proposal", + Long: strings.TrimSpace(`Submit a set scaling factor controller proposal. + +Sample proposal file: +{ + "title": "Set Scaling Factor Controller Proposal", + "description": "Change scaling factor controller address from osmoXXX to osmoYYY" + "pool-id": 1, + "controller-address": "osmoYYY" +} +>>> osmosisd tx gov submit-proposal set-scaling-factor-controller-proposal \ + --proposal proposal.json \ + --deposit 1600000000uosmo \ + +Sample proposal with flags +>>> osmosisd tx gov submit-proposal set-scaling-factor-controller-proposal \ + --title "Set Scaling Factor Controller Proposal" \ + --description "Change scaling factor controller address from osmoXXX to osmoYYY" + --deposit 1600000000uosmo + --pool-id 1 + --controller-address osmoYYY + `), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + content, err := parseSetScalingFactorControllerArgsToContent(cmd) + if err != nil { + return err + } + + from := clientCtx.GetFromAddress() + + depositStr, err := cmd.Flags().GetString(govcli.FlagDeposit) + if err != nil { + return err + } + deposit, err := sdk.ParseCoinsNormalized(depositStr) + if err != nil { + return err + } + + msg, err := govtypes.NewMsgSubmitProposal(content, deposit, from) + if err != nil { + return err + } + + if err = msg.ValidateBasic(); err != nil { + return err + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + cmd.Flags().String(govcli.FlagTitle, "", "title of proposal") + cmd.Flags().String(govcli.FlagDescription, "", "description of proposal") + cmd.Flags().String(govcli.FlagDeposit, "", "deposit of proposal") + cmd.Flags().Uint64(FlagPoolId, 0, "stableswap pool-id") + cmd.Flags().String(FlagScalingFactorControllerAddress, "", "target scaling factor controller address") + cmd.Flags().Bool(govcli.FlagIsExpedited, false, "If true, makes the proposal an expedited one") + cmd.Flags().String(govcli.FlagProposal, "", "Proposal file path (if this path is given, other proposal flags are ignored)") + + return cmd +} + func BuildCreatePoolCmd(clientCtx client.Context, args []string, fs *flag.FlagSet) (sdk.Msg, error) { poolType, err := fs.GetString(FlagPoolType) if err != nil { @@ -714,3 +839,133 @@ func parseUpdateMigrationRecordsArgsToContent(cmd *cobra.Command) (govtypes.Cont } return content, nil } + +func parseCreateConcentratedLiquidityPoolArgsToContent(cmd *cobra.Command) (govtypes.Content, error) { + title, err := cmd.Flags().GetString(govcli.FlagTitle) + if err != nil { + return nil, err + } + + description, err := cmd.Flags().GetString(govcli.FlagDescription) + if err != nil { + return nil, err + } + + poolRecordsWithCFMMLink, err := parsePoolRecordsWithCFMMLink(cmd) + if err != nil { + return nil, err + } + + content := &types.CreateConcentratedLiquidityPoolsAndLinktoCFMMProposal{ + Title: title, + Description: description, + PoolRecordsWithCfmmLink: poolRecordsWithCFMMLink, + } + + return content, nil +} + +func parsePoolRecordsWithCFMMLink(cmd *cobra.Command) ([]types.PoolRecordWithCFMMLink, error) { + poolRecordsStr, err := cmd.Flags().GetString(FlagPoolRecords) + if err != nil { + return nil, err + } + + poolRecordsWithCFMMLink := strings.Split(poolRecordsStr, ",") + + if len(poolRecordsWithCFMMLink)%6 != 0 { + return nil, fmt.Errorf("poolRecordswithCFMMLink must be a list of denom0, denom1, tickSpacing, exponentAtPriceOne, spreadFactor and balancerPoolId") + } + + finalPoolRecords := []types.PoolRecordWithCFMMLink{} + i := 0 + for i < len(poolRecordsWithCFMMLink) { + denom0 := poolRecordsWithCFMMLink[i] + denom1 := poolRecordsWithCFMMLink[i+1] + + tickSpacing, err := strconv.Atoi(poolRecordsWithCFMMLink[i+2]) + if err != nil { + return nil, err + } + + exponentAtPriceOneStr := poolRecordsWithCFMMLink[i+3] + exponentAtPriceOne, ok := sdk.NewIntFromString(exponentAtPriceOneStr) + if !ok { + return nil, fmt.Errorf("invalid exponentAtPriceOne: %s", exponentAtPriceOneStr) + } + + spreadFactorStr := poolRecordsWithCFMMLink[i+4] + spreadFactor, err := sdk.NewDecFromStr(spreadFactorStr) + if err != nil { + return nil, err + } + + balancerPoolId, err := strconv.Atoi(poolRecordsWithCFMMLink[i+5]) + if err != nil { + return nil, err + } + + finalPoolRecords = append(finalPoolRecords, types.PoolRecordWithCFMMLink{ + Denom0: denom0, + Denom1: denom1, + TickSpacing: uint64(tickSpacing), + ExponentAtPriceOne: exponentAtPriceOne, + SpreadFactor: spreadFactor, + BalancerPoolId: uint64(balancerPoolId), + }) + + // increase counter by the next 6 + i = i + 6 + } + + return finalPoolRecords, nil +} + +func parseSetScalingFactorControllerArgsToContent(cmd *cobra.Command) (govtypes.Content, error) { + proposalFile, err := cmd.Flags().GetString(govcli.FlagProposal) + if err != nil { + return nil, err + } + + if proposalFile != "" { + contents, err := os.ReadFile(proposalFile) + if err != nil { + return nil, err + } + + var proposal types.SetScalingFactorControllerProposal + if err := json.Unmarshal(contents, &proposal); err != nil { + return nil, err + } + return &proposal, nil + } + + title, err := cmd.Flags().GetString(govcli.FlagTitle) + if err != nil { + return nil, err + } + + description, err := cmd.Flags().GetString(govcli.FlagDescription) + if err != nil { + return nil, err + } + + poolId, err := cmd.Flags().GetUint64(FlagPoolId) + if err != nil { + return nil, err + } + + controllerAddress, err := cmd.Flags().GetString(FlagScalingFactorControllerAddress) + if err != nil { + return nil, err + } + + content := &types.SetScalingFactorControllerProposal{ + Title: title, + Description: description, + PoolId: poolId, + ControllerAddress: controllerAddress, + } + + return content, nil +} diff --git a/x/gamm/client/proposal_handler.go b/x/gamm/client/proposal_handler.go index 053da15248a..916aa9777c9 100644 --- a/x/gamm/client/proposal_handler.go +++ b/x/gamm/client/proposal_handler.go @@ -8,6 +8,8 @@ import ( ) var ( - ReplaceMigrationRecordsProposalHandler = govclient.NewProposalHandler(cli.NewCmdSubmitReplaceMigrationRecordsProposal, rest.ProposalReplaceMigrationRecordsRESTHandler) - UpdateMigrationRecordsProposalHandler = govclient.NewProposalHandler(cli.NewCmdSubmitUpdateMigrationRecordsProposal, rest.ProposalUpdateMigrationRecordsRESTHandler) + ReplaceMigrationRecordsProposalHandler = govclient.NewProposalHandler(cli.NewCmdSubmitReplaceMigrationRecordsProposal, rest.ProposalReplaceMigrationRecordsRESTHandler) + UpdateMigrationRecordsProposalHandler = govclient.NewProposalHandler(cli.NewCmdSubmitUpdateMigrationRecordsProposal, rest.ProposalUpdateMigrationRecordsRESTHandler) + CreateCLPoolAndLinkToCFMMProposalHandler = govclient.NewProposalHandler(cli.NewCmdSubmitCreateCLPoolAndLinkToCFMMProposal, rest.ProposalCreateConcentratedLiquidityPoolAndLinkToCFMMHandler) + SetScalingFactorControllerProposalHandler = govclient.NewProposalHandler(cli.NewCmdSubmitSetScalingFactorControllerProposal, rest.ProposalSetScalingFactorController) ) diff --git a/x/gamm/client/rest/tx.go b/x/gamm/client/rest/tx.go index 29d089b48a3..419bbcdb589 100644 --- a/x/gamm/client/rest/tx.go +++ b/x/gamm/client/rest/tx.go @@ -21,6 +21,20 @@ func ProposalUpdateMigrationRecordsRESTHandler(clientCtx client.Context) govrest } } +func ProposalCreateConcentratedLiquidityPoolAndLinkToCFMMHandler(clientCtx client.Context) govrest.ProposalRESTHandler { + return govrest.ProposalRESTHandler{ + SubRoute: "create-cl-pool-and-cfmm-link", + Handler: emptyHandler(clientCtx), + } +} + +func ProposalSetScalingFactorController(clientCtx client.Context) govrest.ProposalRESTHandler { + return govrest.ProposalRESTHandler{ + SubRoute: "set-scaling-factor-controller", + Handler: emptyHandler(clientCtx), + } +} + func emptyHandler(clientCtx client.Context) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { } diff --git a/x/gamm/handler.go b/x/gamm/handler.go index 1cc31858bfd..9daae7ed5bd 100644 --- a/x/gamm/handler.go +++ b/x/gamm/handler.go @@ -11,14 +11,18 @@ import ( "github.com/osmosis-labs/osmosis/v17/x/gamm/types" ) -// NewMigrationRecordHandler is a handler for governance proposals on new migration records. -func NewMigrationRecordHandler(k keeper.Keeper) govtypes.Handler { +// NewGammProposalHandler is a handler for governance proposals for the GAMM module. +func NewGammProposalHandler(k keeper.Keeper) govtypes.Handler { return func(ctx sdk.Context, content govtypes.Content) error { switch c := content.(type) { case *types.UpdateMigrationRecordsProposal: return handleUpdateMigrationRecordsProposal(ctx, k, c) case *types.ReplaceMigrationRecordsProposal: return handleReplaceMigrationRecordsProposal(ctx, k, c) + case *types.CreateConcentratedLiquidityPoolsAndLinktoCFMMProposal: + return handleCreatingCLPoolAndLinkToCFMMProposal(ctx, k, c) + case *types.SetScalingFactorControllerProposal: + return handleSetScalingFactorControllerProposal(ctx, k, c) default: return errorsmod.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized migration record proposal content type: %T", c) @@ -35,3 +39,19 @@ func handleReplaceMigrationRecordsProposal(ctx sdk.Context, k keeper.Keeper, p * func handleUpdateMigrationRecordsProposal(ctx sdk.Context, k keeper.Keeper, p *types.UpdateMigrationRecordsProposal) error { return k.HandleUpdateMigrationRecordsProposal(ctx, p) } + +func handleCreatingCLPoolAndLinkToCFMMProposal(ctx sdk.Context, k keeper.Keeper, p *types.CreateConcentratedLiquidityPoolsAndLinktoCFMMProposal) error { + for _, record := range p.PoolRecordsWithCfmmLink { + _, err := k.CreateCanonicalConcentratedLiquidityPoolAndMigrationLink(ctx, record.BalancerPoolId, record.Denom0, record.SpreadFactor, record.TickSpacing) + if err != nil { + return err + } + } + return nil +} + +// handleSetScalingFactorControllerProposal is a handler for gov proposals to set a stableswap pool's +// scaling factor controller address +func handleSetScalingFactorControllerProposal(ctx sdk.Context, k keeper.Keeper, p *types.SetScalingFactorControllerProposal) error { + return k.HandleSetScalingFactorControllerProposal(ctx, p) +} diff --git a/x/gamm/keeper/export_test.go b/x/gamm/keeper/export_test.go index 7730b538448..3b4036de523 100644 --- a/x/gamm/keeper/export_test.go +++ b/x/gamm/keeper/export_test.go @@ -21,6 +21,10 @@ func (k Keeper) SetStableSwapScalingFactors(ctx sdk.Context, poolId uint64, scal return k.setStableSwapScalingFactors(ctx, poolId, scalingFactors, sender) } +func (k Keeper) SetStableSwapScalingFactorController(ctx sdk.Context, poolId uint64, controllerAddress string) error { + return k.setStableSwapScalingFactorController(ctx, poolId, controllerAddress) +} + func AsCFMMPool(pool poolmanagertypes.PoolI) (types.CFMMPoolI, error) { return asCFMMPool(pool) } diff --git a/x/gamm/keeper/gov.go b/x/gamm/keeper/gov.go index b45516233c2..b6523ad5251 100644 --- a/x/gamm/keeper/gov.go +++ b/x/gamm/keeper/gov.go @@ -13,3 +13,7 @@ func (k Keeper) HandleReplaceMigrationRecordsProposal(ctx sdk.Context, p *types. func (k Keeper) HandleUpdateMigrationRecordsProposal(ctx sdk.Context, p *types.UpdateMigrationRecordsProposal) error { return k.UpdateMigrationRecords(ctx, p.Records) } + +func (k Keeper) HandleSetScalingFactorControllerProposal(ctx sdk.Context, p *types.SetScalingFactorControllerProposal) error { + return k.setStableSwapScalingFactorController(ctx, p.PoolId, p.ControllerAddress) +} diff --git a/x/gamm/keeper/migrate.go b/x/gamm/keeper/migrate.go index 5072c1c34f0..0b5edfc304c 100644 --- a/x/gamm/keeper/migrate.go +++ b/x/gamm/keeper/migrate.go @@ -388,6 +388,10 @@ func (k Keeper) CreateConcentratedPoolFromCFMM(ctx sdk.Context, cfmmPoolIdToLink } } + if spreadFactor.IsZero() || spreadFactor.IsNil() { + spreadFactor = cfmmPool.GetSpreadFactor(ctx) + } + createPoolMsg := clmodel.NewMsgCreateConcentratedPool(poolCreatorAddress, desiredDenom0, denom1, tickSpacing, spreadFactor) concentratedPool, err := k.poolManager.CreateConcentratedPoolAsPoolManager(ctx, createPoolMsg) if err != nil { diff --git a/x/gamm/keeper/migrate_test.go b/x/gamm/keeper/migrate_test.go index 4c24bc78162..8d9f9771c6c 100644 --- a/x/gamm/keeper/migrate_test.go +++ b/x/gamm/keeper/migrate_test.go @@ -916,8 +916,8 @@ func (s *KeeperTestSuite) TestGetAllMigrationInfo() { } } -func (suite *KeeperTestSuite) TestRedirectDistributionRecord() { - suite.Setup() +func (s *KeeperTestSuite) TestRedirectDistributionRecord() { + s.Setup() var ( defaultUsdcAmount = sdk.NewInt(7300000000) @@ -926,8 +926,8 @@ func (suite *KeeperTestSuite) TestRedirectDistributionRecord() { osmoCoin = sdk.NewCoin("uosmo", defaultOsmoAmount) ) - longestLockableDuration, err := suite.App.PoolIncentivesKeeper.GetLongestLockableDuration(suite.Ctx) - suite.Require().NoError(err) + longestLockableDuration, err := s.App.PoolIncentivesKeeper.GetLongestLockableDuration(s.Ctx) + s.Require().NoError(err) tests := map[string]struct { poolLiquidity sdk.Coins @@ -956,22 +956,22 @@ func (suite *KeeperTestSuite) TestRedirectDistributionRecord() { for name, tc := range tests { tc := tc - suite.Run(name, func() { - suite.SetupTest() + s.Run(name, func() { + s.SetupTest() // Create primary balancer pool. - balancerId := suite.PrepareBalancerPoolWithCoins(tc.poolLiquidity...) - balancerPool, err := suite.App.PoolManagerKeeper.GetPool(suite.Ctx, balancerId) - suite.Require().NoError(err) + balancerId := s.PrepareBalancerPoolWithCoins(tc.poolLiquidity...) + balancerPool, err := s.App.PoolManagerKeeper.GetPool(s.Ctx, balancerId) + s.Require().NoError(err) // Create another balancer pool to test that its gauge links are unchanged - balancerId2 := suite.PrepareBalancerPoolWithCoins(tc.poolLiquidity...) + balancerId2 := s.PrepareBalancerPoolWithCoins(tc.poolLiquidity...) // Get gauges for both balancer pools. - gaugeToRedirect, err := suite.App.PoolIncentivesKeeper.GetPoolGaugeId(suite.Ctx, balancerPool.GetId(), longestLockableDuration) - suite.Require().NoError(err) - gaugeToNotRedirect, err := suite.App.PoolIncentivesKeeper.GetPoolGaugeId(suite.Ctx, balancerId2, longestLockableDuration) - suite.Require().NoError(err) + gaugeToRedirect, err := s.App.PoolIncentivesKeeper.GetPoolGaugeId(s.Ctx, balancerPool.GetId(), longestLockableDuration) + s.Require().NoError(err) + gaugeToNotRedirect, err := s.App.PoolIncentivesKeeper.GetPoolGaugeId(s.Ctx, balancerId2, longestLockableDuration) + s.Require().NoError(err) // Distribution info prior to redirecting. originalDistrInfo := poolincentivestypes.DistrInfo{ @@ -987,31 +987,31 @@ func (suite *KeeperTestSuite) TestRedirectDistributionRecord() { }, }, } - suite.App.PoolIncentivesKeeper.SetDistrInfo(suite.Ctx, originalDistrInfo) + s.App.PoolIncentivesKeeper.SetDistrInfo(s.Ctx, originalDistrInfo) // Create concentrated pool. - clPool := suite.PrepareCustomConcentratedPool(suite.TestAccs[0], tc.poolLiquidity[1].Denom, tc.poolLiquidity[0].Denom, 100, sdk.MustNewDecFromStr("0.001")) + clPool := s.PrepareCustomConcentratedPool(s.TestAccs[0], tc.poolLiquidity[1].Denom, tc.poolLiquidity[0].Denom, 100, sdk.MustNewDecFromStr("0.001")) // Redirect distribution record from the primary balancer pool to the concentrated pool. - err = suite.App.GAMMKeeper.RedirectDistributionRecord(suite.Ctx, tc.cfmmPoolId, tc.clPoolId) + err = s.App.GAMMKeeper.RedirectDistributionRecord(s.Ctx, tc.cfmmPoolId, tc.clPoolId) if tc.expectError != nil { - suite.Require().Error(err) + s.Require().Error(err) return } - suite.Require().NoError(err) + s.Require().NoError(err) // Validate that the balancer gauge is now linked to the new concentrated pool. - concentratedPoolGaugeId, err := suite.App.PoolIncentivesKeeper.GetPoolGaugeId(suite.Ctx, clPool.GetId(), suite.App.IncentivesKeeper.GetEpochInfo(suite.Ctx).Duration) - suite.Require().NoError(err) - distrInfo := suite.App.PoolIncentivesKeeper.GetDistrInfo(suite.Ctx) - suite.Require().Equal(distrInfo.Records[0].GaugeId, concentratedPoolGaugeId) + concentratedPoolGaugeId, err := s.App.PoolIncentivesKeeper.GetPoolGaugeId(s.Ctx, clPool.GetId(), s.App.IncentivesKeeper.GetEpochInfo(s.Ctx).Duration) + s.Require().NoError(err) + distrInfo := s.App.PoolIncentivesKeeper.GetDistrInfo(s.Ctx) + s.Require().Equal(distrInfo.Records[0].GaugeId, concentratedPoolGaugeId) // Validate that distribution record from another pool is not redirected. - suite.Require().Equal(distrInfo.Records[1].GaugeId, gaugeToNotRedirect) + s.Require().Equal(distrInfo.Records[1].GaugeId, gaugeToNotRedirect) // Validate that old gauge still exist - _, err = suite.App.IncentivesKeeper.GetGaugeByID(suite.Ctx, gaugeToRedirect) - suite.Require().NoError(err) + _, err = s.App.IncentivesKeeper.GetGaugeByID(s.Ctx, gaugeToRedirect) + s.Require().NoError(err) }) } } @@ -1022,7 +1022,6 @@ func (s *KeeperTestSuite) TestCreateConcentratedPoolFromCFMM() { cfmmPoolIdToLinkWith uint64 desiredDenom0 string - spreadFactor sdk.Dec expectedDenoms []string expectError error }{ @@ -1030,22 +1029,19 @@ func (s *KeeperTestSuite) TestCreateConcentratedPoolFromCFMM() { poolLiquidity: sdk.NewCoins(desiredDenom0Coin, daiCoin), cfmmPoolIdToLinkWith: validPoolId, desiredDenom0: desiredDenom0, - spreadFactor: sdk.MustNewDecFromStr("0.0001"), expectedDenoms: []string{desiredDenom0, daiCoin.Denom}, }, "error: invalid denom 0": { poolLiquidity: sdk.NewCoins(desiredDenom0Coin, daiCoin), cfmmPoolIdToLinkWith: validPoolId, desiredDenom0: USDCIBCDenom, - spreadFactor: sdk.MustNewDecFromStr("0.0001"), - expectError: types.NoDesiredDenomInPoolError{DesiredDenom: USDCIBCDenom}, + expectError: types.NoDesiredDenomInPoolError{USDCIBCDenom}, }, "error: pool with 3 assets, must have two": { poolLiquidity: sdk.NewCoins(desiredDenom0Coin, daiCoin, usdcCoin), cfmmPoolIdToLinkWith: validPoolId, desiredDenom0: USDCIBCDenom, - spreadFactor: sdk.MustNewDecFromStr("0.0001"), - expectError: types.MustHaveTwoDenomsError{NumDenoms: 3}, + expectError: types.ErrMustHaveTwoDenoms, }, } @@ -1059,7 +1055,7 @@ func (s *KeeperTestSuite) TestCreateConcentratedPoolFromCFMM() { balancerPool, err := s.App.PoolManagerKeeper.GetPool(s.Ctx, balancerId) s.Require().NoError(err) - clPoolReturned, err := s.App.GAMMKeeper.CreateConcentratedPoolFromCFMM(s.Ctx, tc.cfmmPoolIdToLinkWith, tc.desiredDenom0, tc.spreadFactor, defaultTickSpacing) + clPoolReturned, err := s.App.GAMMKeeper.CreateConcentratedPoolFromCFMM(s.Ctx, tc.cfmmPoolIdToLinkWith, tc.desiredDenom0, sdk.ZeroDec(), defaultTickSpacing) if tc.expectError != nil { s.Require().Error(err) @@ -1074,7 +1070,7 @@ func (s *KeeperTestSuite) TestCreateConcentratedPoolFromCFMM() { s.Require().Equal(clPoolReturned, clPoolInState) // Validate CL and balancer pools have the same spread factor. - s.Require().Equal(tc.spreadFactor, clPoolReturned.GetSpreadFactor(s.Ctx)) + s.Require().Equal(balancerPool.GetSpreadFactor(s.Ctx), clPoolReturned.GetSpreadFactor(s.Ctx)) // Validate that CL and balancer pools have the same denoms balancerDenoms, err := s.App.PoolManagerKeeper.RouteGetPoolDenoms(s.Ctx, balancerPool.GetId()) @@ -1101,7 +1097,6 @@ func (s *KeeperTestSuite) TestCreateCanonicalConcentratedLiquidityPoolAndMigrati poolLiquidity sdk.Coins cfmmPoolIdToLinkWith uint64 desiredDenom0 string - spreadFactor sdk.Dec expectedBalancerDenoms []string expectedConcentratedDenoms []string setupInvalidDuraitons bool @@ -1115,7 +1110,6 @@ func (s *KeeperTestSuite) TestCreateCanonicalConcentratedLiquidityPoolAndMigrati // determined by desired denom 0 expectedConcentratedDenoms: []string{desiredDenom0Coin.Denom, daiCoin.Denom}, desiredDenom0: desiredDenom0, - spreadFactor: sdk.MustNewDecFromStr("0.0001"), }, "success - denoms are not reordered relative to balancer": { poolLiquidity: sdk.NewCoins(desiredDenom0Coin, daiCoin), @@ -1125,27 +1119,23 @@ func (s *KeeperTestSuite) TestCreateCanonicalConcentratedLiquidityPoolAndMigrati // determined by desired denom 0 expectedConcentratedDenoms: []string{daiCoin.Denom, desiredDenom0Coin.Denom}, desiredDenom0: daiCoin.Denom, - spreadFactor: sdk.MustNewDecFromStr("0.0001"), }, "error: invalid denom 0": { poolLiquidity: sdk.NewCoins(desiredDenom0Coin, daiCoin), cfmmPoolIdToLinkWith: validPoolId, desiredDenom0: USDCIBCDenom, - spreadFactor: sdk.MustNewDecFromStr("0.0001"), - expectError: types.NoDesiredDenomInPoolError{DesiredDenom: USDCIBCDenom}, + expectError: types.NoDesiredDenomInPoolError{USDCIBCDenom}, }, "error: pool with 3 assets, must have two": { poolLiquidity: sdk.NewCoins(desiredDenom0Coin, daiCoin, usdcCoin), cfmmPoolIdToLinkWith: validPoolId, desiredDenom0: USDCIBCDenom, - spreadFactor: sdk.MustNewDecFromStr("0.0001"), - expectError: types.MustHaveTwoDenomsError{NumDenoms: 3}, + expectError: types.ErrMustHaveTwoDenoms, }, "error: invalid denom durations": { poolLiquidity: sdk.NewCoins(desiredDenom0Coin, daiCoin), cfmmPoolIdToLinkWith: validPoolId, desiredDenom0: desiredDenom0, - spreadFactor: sdk.MustNewDecFromStr("0.0001"), setupInvalidDuraitons: true, expectError: types.ErrNoGaugeToRedirect, }, @@ -1189,7 +1179,7 @@ func (s *KeeperTestSuite) TestCreateCanonicalConcentratedLiquidityPoolAndMigrati } s.App.PoolIncentivesKeeper.SetDistrInfo(s.Ctx, originalDistrInfo) - clPool, err := s.App.GAMMKeeper.CreateCanonicalConcentratedLiquidityPoolAndMigrationLink(s.Ctx, tc.cfmmPoolIdToLinkWith, tc.desiredDenom0, tc.spreadFactor, defaultTickSpacing) + clPool, err := s.App.GAMMKeeper.CreateCanonicalConcentratedLiquidityPoolAndMigrationLink(s.Ctx, tc.cfmmPoolIdToLinkWith, tc.desiredDenom0, sdk.ZeroDec(), defaultTickSpacing) if tc.expectError != nil { s.Require().Error(err) diff --git a/x/gamm/keeper/pool.go b/x/gamm/keeper/pool.go index 98a05b2e837..cfbc8149ee7 100644 --- a/x/gamm/keeper/pool.go +++ b/x/gamm/keeper/pool.go @@ -327,6 +327,23 @@ func (k Keeper) setStableSwapScalingFactors(ctx sdk.Context, poolId uint64, scal return k.setPool(ctx, stableswapPool) } +// setStableSwapScalingFactorController updates the scaling factor controller address for a stable swap pool +// errors if the pool does not exist or is not a stable swap pool +func (k Keeper) setStableSwapScalingFactorController(ctx sdk.Context, poolId uint64, controllerAddress string) error { + pool, err := k.GetPoolAndPoke(ctx, poolId) + if err != nil { + return err + } + stableswapPool, ok := pool.(*stableswap.Pool) + if !ok { + return fmt.Errorf("pool id %d is not of type stableswap pool", poolId) + } + + stableswapPool.ScalingFactorController = controllerAddress + + return k.setPool(ctx, stableswapPool) +} + // asCFMMPool converts PoolI to CFMMPoolI by casting the input. // Returns the pool of the CFMMPoolI or error if the given pool does not implement // CFMMPoolI. diff --git a/x/gamm/keeper/pool_test.go b/x/gamm/keeper/pool_test.go index 4e75034de0e..4ec3b17d63c 100644 --- a/x/gamm/keeper/pool_test.go +++ b/x/gamm/keeper/pool_test.go @@ -518,6 +518,83 @@ func (s *KeeperTestSuite) TestSetStableSwapScalingFactors() { } } +func (s *KeeperTestSuite) TestSetStableSwapScalingFactorController() { + initialControllerAddr := s.TestAccs[0].String() + updatedControllerAddr := s.TestAccs[1].String() + + testcases := []struct { + name string + poolId uint64 + expError error + isStableSwapPool bool + }{ + { + name: "Error: Pool does not exist", + poolId: 2, + expError: types.PoolDoesNotExistError{PoolId: defaultPoolId + 1}, + isStableSwapPool: false, + }, + { + name: "Error: Pool id is not of type stableswap pool", + poolId: 1, + expError: fmt.Errorf("pool id 1 is not of type stableswap pool"), + isStableSwapPool: false, + }, + { + name: "Valid case", + poolId: 1, + isStableSwapPool: true, + }, + } + for _, tc := range testcases { + s.Run(tc.name, func() { + s.SetupTest() + if tc.isStableSwapPool == true { + poolId := s.prepareCustomStableswapPool( + defaultAcctFunds, + stableswap.PoolParams{ + SwapFee: defaultSpreadFactor, + ExitFee: defaultZeroExitFee, + }, + sdk.NewCoins(sdk.NewCoin(defaultAcctFunds[0].Denom, defaultAcctFunds[0].Amount.QuoRaw(2)), sdk.NewCoin(defaultAcctFunds[1].Denom, defaultAcctFunds[1].Amount.QuoRaw(2))), + []uint64{1, 1}, + ) + pool, _ := s.App.GAMMKeeper.GetPoolAndPoke(s.Ctx, poolId) + stableswapPool, _ := pool.(*stableswap.Pool) + stableswapPool.ScalingFactorController = initialControllerAddr + err := s.App.GAMMKeeper.SetPool(s.Ctx, stableswapPool) + s.Require().NoError(err) + + // attempt to adjust the scaling factor from the new address - it should fail + err = s.App.GAMMKeeper.SetStableSwapScalingFactors(s.Ctx, tc.poolId, []uint64{1, 2}, updatedControllerAddr) + s.Require().ErrorIs(err, types.ErrNotScalingFactorGovernor) + } else { + s.prepareCustomBalancerPool( + defaultAcctFunds, + defaultPoolAssets, + defaultPoolParams) + } + + err := s.App.GAMMKeeper.SetStableSwapScalingFactorController(s.Ctx, tc.poolId, updatedControllerAddr) + if tc.expError != nil { + s.Require().Error(err) + s.Require().EqualError(err, tc.expError.Error()) + } else { + s.Require().NoError(err) + + // confirm the scaling factor controller has been updated + pool, _ := s.App.GAMMKeeper.GetPoolAndPoke(s.Ctx, tc.poolId) + stableswapPool, _ := pool.(*stableswap.Pool) + s.Require().Equal(updatedControllerAddr, stableswapPool.ScalingFactorController) + + // confirm the new controller can update the scaling factor + err = s.App.GAMMKeeper.SetStableSwapScalingFactors(s.Ctx, tc.poolId, []uint64{1, 2}, updatedControllerAddr) + s.Require().NoError(err) + } + }) + } +} + func (suite *KeeperTestSuite) TestGetMaximalNoSwapLPAmount() { tests := map[string]struct { poolId uint64 diff --git a/x/gamm/types/codec.go b/x/gamm/types/codec.go index b842641502f..416d235d0bd 100644 --- a/x/gamm/types/codec.go +++ b/x/gamm/types/codec.go @@ -23,6 +23,8 @@ func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { cdc.RegisterConcrete(&MsgExitSwapShareAmountIn{}, "osmosis/gamm/exit-swap-share-amount-in", nil) cdc.RegisterConcrete(&UpdateMigrationRecordsProposal{}, "osmosis/gamm/update-migration-records-proposal", nil) cdc.RegisterConcrete(&ReplaceMigrationRecordsProposal{}, "osmosis/gamm/replace-migration-records-proposal", nil) + cdc.RegisterConcrete(&CreateConcentratedLiquidityPoolsAndLinktoCFMMProposal{}, "osmosis/gamm/create-cl-pool-and-cfmm-link", nil) + cdc.RegisterConcrete(&SetScalingFactorControllerProposal{}, "osmosis/gamm/scaling-factor-controller", nil) } func RegisterInterfaces(registry types.InterfaceRegistry) { @@ -47,6 +49,8 @@ func RegisterInterfaces(registry types.InterfaceRegistry) { (*govtypes.Content)(nil), &UpdateMigrationRecordsProposal{}, &ReplaceMigrationRecordsProposal{}, + &CreateConcentratedLiquidityPoolsAndLinktoCFMMProposal{}, + &SetScalingFactorControllerProposal{}, ) msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) diff --git a/x/gamm/types/errors.go b/x/gamm/types/errors.go index ec82293ea86..2c9781ff2c9 100644 --- a/x/gamm/types/errors.go +++ b/x/gamm/types/errors.go @@ -107,4 +107,5 @@ var ( ErrHitMaxScaledAssets = errorsmod.Register(ModuleName, 65, "post-scaled pool assets can not exceed 10^34") ErrHitMinScaledAssets = errorsmod.Register(ModuleName, 66, "post-scaled pool assets can not be less than 1") ErrNoGaugeToRedirect = errorsmod.Register(ModuleName, 67, "could not find gauge to redirect") + ErrMustHaveTwoDenoms = errorsmod.Register(ModuleName, 68, "can only have 2 denoms in CL pool") ) diff --git a/x/gamm/types/expected_keepers.go b/x/gamm/types/expected_keepers.go index ddc798aa7f6..adce072e991 100644 --- a/x/gamm/types/expected_keepers.go +++ b/x/gamm/types/expected_keepers.go @@ -53,6 +53,7 @@ type CommunityPoolKeeper interface { // ConcentratedLiquidityKeeper defines the contract needed to be fulfilled for the concentrated liquidity keeper. type ConcentratedLiquidityKeeper interface { + SetParams(ctx sdk.Context, params cltypes.Params) GetConcentratedPoolById(ctx sdk.Context, poolId uint64) (cltypes.ConcentratedPoolExtension, error) CreateFullRangePosition(ctx sdk.Context, clPoolId uint64, owner sdk.AccAddress, coins sdk.Coins) (positionId uint64, amount0, amount1 sdk.Int, liquidity sdk.Dec, err error) } diff --git a/x/gamm/types/gov.go b/x/gamm/types/gov.go index 8592d14fa6d..2424c395b6d 100644 --- a/x/gamm/types/gov.go +++ b/x/gamm/types/gov.go @@ -4,13 +4,17 @@ import ( "fmt" "strings" + sdk "github.com/cosmos/cosmos-sdk/types" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" + gammmigration "github.com/osmosis-labs/osmosis/v17/x/gamm/types/migration" ) const ( - ProposalTypeUpdateMigrationRecords = "UpdateMigrationRecords" - ProposalTypeReplaceMigrationRecords = "ReplaceMigrationRecords" + ProposalTypeUpdateMigrationRecords = "UpdateMigrationRecords" + ProposalTypeReplaceMigrationRecords = "ReplaceMigrationRecords" + ProposalTypeCreateConcentratedLiquidityPoolAndLinktoCFMM = "CreateConcentratedLiquidityPoolAndLinktoCFMM" + ProposalTypeSetScalingFactorController = "SetScalingFactorController" ) // Init registers proposals to update and replace migration records. @@ -19,11 +23,17 @@ func init() { govtypes.RegisterProposalTypeCodec(&UpdateMigrationRecordsProposal{}, "osmosis/UpdateMigrationRecordsProposal") govtypes.RegisterProposalType(ProposalTypeReplaceMigrationRecords) govtypes.RegisterProposalTypeCodec(&ReplaceMigrationRecordsProposal{}, "osmosis/ReplaceMigrationRecordsProposal") + govtypes.RegisterProposalType(ProposalTypeCreateConcentratedLiquidityPoolAndLinktoCFMM) + govtypes.RegisterProposalTypeCodec(&CreateConcentratedLiquidityPoolsAndLinktoCFMMProposal{}, "osmosis/CreateConcentratedLiquidityPoolsAndLinktoCFMMProposal") + govtypes.RegisterProposalType(ProposalTypeSetScalingFactorController) + govtypes.RegisterProposalTypeCodec(&SetScalingFactorControllerProposal{}, "osmosis/SetScalingFactorControllerProposal") } var ( _ govtypes.Content = &UpdateMigrationRecordsProposal{} _ govtypes.Content = &ReplaceMigrationRecordsProposal{} + _ govtypes.Content = &CreateConcentratedLiquidityPoolsAndLinktoCFMMProposal{} + _ govtypes.Content = &SetScalingFactorControllerProposal{} ) // NewReplacePoolIncentivesProposal returns a new instance of a replace migration record's proposal struct. @@ -130,3 +140,131 @@ func (p UpdateMigrationRecordsProposal) String() string { `, p.Title, p.Description, recordsStr)) return b.String() } + +func NewCreateConcentratedLiquidityPoolsAndLinktoCFMMProposal(title, description string, records []PoolRecordWithCFMMLink) govtypes.Content { + return &CreateConcentratedLiquidityPoolsAndLinktoCFMMProposal{ + Title: title, + Description: description, + PoolRecordsWithCfmmLink: records, + } +} + +// GetTitle gets the title of the proposal +func (p *CreateConcentratedLiquidityPoolsAndLinktoCFMMProposal) GetTitle() string { return p.Title } + +// GetDescription gets the description of the proposal +func (p *CreateConcentratedLiquidityPoolsAndLinktoCFMMProposal) GetDescription() string { + return p.Description +} + +// ProposalRoute returns the router key for the proposal +func (p *CreateConcentratedLiquidityPoolsAndLinktoCFMMProposal) ProposalRoute() string { + return RouterKey +} + +// ProposalType returns the type of the proposal +func (p *CreateConcentratedLiquidityPoolsAndLinktoCFMMProposal) ProposalType() string { + return ProposalTypeCreateConcentratedLiquidityPoolAndLinktoCFMM +} + +// ValidateBasic validates a governance proposal's abstract and basic contents. +func (p *CreateConcentratedLiquidityPoolsAndLinktoCFMMProposal) ValidateBasic() error { + err := govtypes.ValidateAbstract(p) + if err != nil { + return err + } + + for _, record := range p.PoolRecordsWithCfmmLink { + if record.TickSpacing <= 0 { + return fmt.Errorf("tick spacing must be positive") + } + + if record.Denom0 == record.Denom1 { + return fmt.Errorf("denom0 and denom1 must be different") + } + + if sdk.ValidateDenom(record.Denom0) != nil { + return fmt.Errorf("denom0 is invalid: %s", sdk.ValidateDenom(record.Denom0)) + } + + if sdk.ValidateDenom(record.Denom1) != nil { + return fmt.Errorf("denom1 is invalid: %s", sdk.ValidateDenom(record.Denom1)) + } + + spreadFactor := record.SpreadFactor + if spreadFactor.IsNegative() || spreadFactor.GTE(sdk.OneDec()) { + return fmt.Errorf("Invalid Spread factor") + } + + if record.BalancerPoolId <= 0 { + return fmt.Errorf("Invalid Balancer Pool Id") + } + } + return nil +} + +// String returns a string containing creating CL pool and linking it to an existing CFMM pool. +func (p CreateConcentratedLiquidityPoolsAndLinktoCFMMProposal) String() string { + recordsStr := "" + for _, record := range p.PoolRecordsWithCfmmLink { + recordsStr = recordsStr + fmt.Sprintf("(Denom0: %s, Denom1: %s, TickSpacing: %d, ExponentAtPriceOne: %d, SpreadFactor: %d, BalancerPoolId: %d) ", record.Denom0, record.Denom1, record.TickSpacing, record.ExponentAtPriceOne, record.SpreadFactor, record.BalancerPoolId) + } + + var b strings.Builder + b.WriteString(fmt.Sprintf(`Create Concentrated Liquidity Pool Proposal: +Title: %s +Description: %s +Records: %s +`, p.Title, p.Description, recordsStr)) + return b.String() +} + +// NewSetScalingFactorControllerProposal returns a new instance of a replace migration record's proposal struct. +func NewSetScalingFactorControllerProposal(title, description string, poolId uint64, controllerAddress string) govtypes.Content { + return &SetScalingFactorControllerProposal{ + Title: title, + Description: description, + PoolId: poolId, + ControllerAddress: controllerAddress, + } +} + +// GetTitle gets the title of the proposal +func (p *SetScalingFactorControllerProposal) GetTitle() string { return p.Title } + +// GetDescription gets the description of the proposal +func (p *SetScalingFactorControllerProposal) GetDescription() string { return p.Description } + +// ProposalRoute returns the router key for the proposal +func (p *SetScalingFactorControllerProposal) ProposalRoute() string { return RouterKey } + +// ProposalType returns the type of the proposal +func (p *SetScalingFactorControllerProposal) ProposalType() string { + return ProposalTypeReplaceMigrationRecords +} + +// ValidateBasic validates a governance proposal's abstract and basic contents +func (p *SetScalingFactorControllerProposal) ValidateBasic() error { + err := govtypes.ValidateAbstract(p) + if err != nil { + return err + } + _, err = sdk.AccAddressFromBech32(p.ControllerAddress) + if err != nil { + return fmt.Errorf("Invalid controller address (%s)", err) + } + + return nil +} + +// String returns a string containing the migration record's proposal. +func (p SetScalingFactorControllerProposal) String() string { + var b strings.Builder + b.WriteString(fmt.Sprintf(`Set Scaling Factor Controller Address Proposal: + Title: %s + Description: %s + PoolId: %d + ControllerAddress: %s +`, p.Title, p.Description, p.PoolId, p.ControllerAddress)) + return b.String() +} diff --git a/x/gamm/types/gov.pb.go b/x/gamm/types/gov.pb.go index 2a149902eb1..2a0dec0b3cd 100644 --- a/x/gamm/types/gov.pb.go +++ b/x/gamm/types/gov.pb.go @@ -6,6 +6,7 @@ package types import ( fmt "fmt" _ "github.com/cosmos/cosmos-proto" + github_com_cosmos_cosmos_sdk_types "github.com/cosmos/cosmos-sdk/types" _ "github.com/cosmos/cosmos-sdk/types/tx/amino" _ "github.com/gogo/protobuf/gogoproto" proto "github.com/gogo/protobuf/proto" @@ -115,40 +116,222 @@ func (m *UpdateMigrationRecordsProposal) XXX_DiscardUnknown() { var xxx_messageInfo_UpdateMigrationRecordsProposal proto.InternalMessageInfo +type PoolRecordWithCFMMLink struct { + Denom0 string `protobuf:"bytes,1,opt,name=denom0,proto3" json:"denom0,omitempty" yaml:"denom0"` + Denom1 string `protobuf:"bytes,2,opt,name=denom1,proto3" json:"denom1,omitempty" yaml:"denom1"` + TickSpacing uint64 `protobuf:"varint,3,opt,name=tick_spacing,json=tickSpacing,proto3" json:"tick_spacing,omitempty" yaml:"tick_spacing"` + ExponentAtPriceOne github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,4,opt,name=exponent_at_price_one,json=exponentAtPriceOne,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"exponent_at_price_one" yaml:"exponent_at_price_one"` + SpreadFactor github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,5,opt,name=spread_factor,json=spreadFactor,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"spread_factor" yaml:"spread_factor"` + BalancerPoolId uint64 `protobuf:"varint,6,opt,name=balancer_pool_id,json=balancerPoolId,proto3" json:"balancer_pool_id,omitempty" yaml:"balancer_pool_id"` +} + +func (m *PoolRecordWithCFMMLink) Reset() { *m = PoolRecordWithCFMMLink{} } +func (m *PoolRecordWithCFMMLink) String() string { return proto.CompactTextString(m) } +func (*PoolRecordWithCFMMLink) ProtoMessage() {} +func (*PoolRecordWithCFMMLink) Descriptor() ([]byte, []int) { + return fileDescriptor_f31b9a6c0dbbdfa3, []int{2} +} +func (m *PoolRecordWithCFMMLink) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *PoolRecordWithCFMMLink) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_PoolRecordWithCFMMLink.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *PoolRecordWithCFMMLink) XXX_Merge(src proto.Message) { + xxx_messageInfo_PoolRecordWithCFMMLink.Merge(m, src) +} +func (m *PoolRecordWithCFMMLink) XXX_Size() int { + return m.Size() +} +func (m *PoolRecordWithCFMMLink) XXX_DiscardUnknown() { + xxx_messageInfo_PoolRecordWithCFMMLink.DiscardUnknown(m) +} + +var xxx_messageInfo_PoolRecordWithCFMMLink proto.InternalMessageInfo + +func (m *PoolRecordWithCFMMLink) GetDenom0() string { + if m != nil { + return m.Denom0 + } + return "" +} + +func (m *PoolRecordWithCFMMLink) GetDenom1() string { + if m != nil { + return m.Denom1 + } + return "" +} + +func (m *PoolRecordWithCFMMLink) GetTickSpacing() uint64 { + if m != nil { + return m.TickSpacing + } + return 0 +} + +func (m *PoolRecordWithCFMMLink) GetBalancerPoolId() uint64 { + if m != nil { + return m.BalancerPoolId + } + return 0 +} + +// CreateConcentratedLiquidityPoolsAndLinktoCFMMProposal is a gov Content type +// for creating concentrated liquidity pools and linking it to a CFMM pool. +type CreateConcentratedLiquidityPoolsAndLinktoCFMMProposal struct { + Title string `protobuf:"bytes,1,opt,name=title,proto3" json:"title,omitempty"` + Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"` + PoolRecordsWithCfmmLink []PoolRecordWithCFMMLink `protobuf:"bytes,3,rep,name=pool_records_with_cfmm_link,json=poolRecordsWithCfmmLink,proto3" json:"pool_records_with_cfmm_link" yaml:"create_cl_pool_and_link_to_cfmm"` +} + +func (m *CreateConcentratedLiquidityPoolsAndLinktoCFMMProposal) Reset() { + *m = CreateConcentratedLiquidityPoolsAndLinktoCFMMProposal{} +} +func (*CreateConcentratedLiquidityPoolsAndLinktoCFMMProposal) ProtoMessage() {} +func (*CreateConcentratedLiquidityPoolsAndLinktoCFMMProposal) Descriptor() ([]byte, []int) { + return fileDescriptor_f31b9a6c0dbbdfa3, []int{3} +} +func (m *CreateConcentratedLiquidityPoolsAndLinktoCFMMProposal) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *CreateConcentratedLiquidityPoolsAndLinktoCFMMProposal) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_CreateConcentratedLiquidityPoolsAndLinktoCFMMProposal.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *CreateConcentratedLiquidityPoolsAndLinktoCFMMProposal) XXX_Merge(src proto.Message) { + xxx_messageInfo_CreateConcentratedLiquidityPoolsAndLinktoCFMMProposal.Merge(m, src) +} +func (m *CreateConcentratedLiquidityPoolsAndLinktoCFMMProposal) XXX_Size() int { + return m.Size() +} +func (m *CreateConcentratedLiquidityPoolsAndLinktoCFMMProposal) XXX_DiscardUnknown() { + xxx_messageInfo_CreateConcentratedLiquidityPoolsAndLinktoCFMMProposal.DiscardUnknown(m) +} + +var xxx_messageInfo_CreateConcentratedLiquidityPoolsAndLinktoCFMMProposal proto.InternalMessageInfo + +// SetScalingFactorControllerProposal is a gov Content type for updating the +// scaling factor controller address of a stableswap pool +type SetScalingFactorControllerProposal struct { + Title string `protobuf:"bytes,1,opt,name=title,proto3" json:"title,omitempty"` + Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"` + PoolId uint64 `protobuf:"varint,3,opt,name=pool_id,json=poolId,proto3" json:"pool_id,omitempty"` + ControllerAddress string `protobuf:"bytes,4,opt,name=controller_address,json=controllerAddress,proto3" json:"controller_address,omitempty"` +} + +func (m *SetScalingFactorControllerProposal) Reset() { *m = SetScalingFactorControllerProposal{} } +func (*SetScalingFactorControllerProposal) ProtoMessage() {} +func (*SetScalingFactorControllerProposal) Descriptor() ([]byte, []int) { + return fileDescriptor_f31b9a6c0dbbdfa3, []int{4} +} +func (m *SetScalingFactorControllerProposal) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *SetScalingFactorControllerProposal) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_SetScalingFactorControllerProposal.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *SetScalingFactorControllerProposal) XXX_Merge(src proto.Message) { + xxx_messageInfo_SetScalingFactorControllerProposal.Merge(m, src) +} +func (m *SetScalingFactorControllerProposal) XXX_Size() int { + return m.Size() +} +func (m *SetScalingFactorControllerProposal) XXX_DiscardUnknown() { + xxx_messageInfo_SetScalingFactorControllerProposal.DiscardUnknown(m) +} + +var xxx_messageInfo_SetScalingFactorControllerProposal proto.InternalMessageInfo + func init() { proto.RegisterType((*ReplaceMigrationRecordsProposal)(nil), "osmosis.gamm.v1beta1.ReplaceMigrationRecordsProposal") proto.RegisterType((*UpdateMigrationRecordsProposal)(nil), "osmosis.gamm.v1beta1.UpdateMigrationRecordsProposal") + proto.RegisterType((*PoolRecordWithCFMMLink)(nil), "osmosis.gamm.v1beta1.PoolRecordWithCFMMLink") + proto.RegisterType((*CreateConcentratedLiquidityPoolsAndLinktoCFMMProposal)(nil), "osmosis.gamm.v1beta1.CreateConcentratedLiquidityPoolsAndLinktoCFMMProposal") + proto.RegisterType((*SetScalingFactorControllerProposal)(nil), "osmosis.gamm.v1beta1.SetScalingFactorControllerProposal") } func init() { proto.RegisterFile("osmosis/gamm/v1beta1/gov.proto", fileDescriptor_f31b9a6c0dbbdfa3) } var fileDescriptor_f31b9a6c0dbbdfa3 = []byte{ - // 388 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0xcb, 0x2f, 0xce, 0xcd, - 0x2f, 0xce, 0x2c, 0xd6, 0x4f, 0x4f, 0xcc, 0xcd, 0xd5, 0x2f, 0x33, 0x4c, 0x4a, 0x2d, 0x49, 0x34, - 0xd4, 0x4f, 0xcf, 0x2f, 0xd3, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x81, 0xca, 0xeb, 0x81, - 0xe4, 0xf5, 0xa0, 0xf2, 0x52, 0x22, 0xe9, 0xf9, 0xe9, 0xf9, 0x60, 0x05, 0xfa, 0x20, 0x16, 0x44, - 0xad, 0x94, 0x12, 0x76, 0xb3, 0x52, 0xf3, 0x52, 0x41, 0x06, 0x40, 0xd4, 0x28, 0x62, 0x55, 0x53, - 0x9c, 0x91, 0x58, 0x94, 0x9a, 0x02, 0x55, 0x22, 0x99, 0x0c, 0x56, 0x13, 0x0f, 0x31, 0x1f, 0xc2, - 0x81, 0x4a, 0x09, 0x26, 0xe6, 0x66, 0xe6, 0xe5, 0xeb, 0x83, 0x49, 0x88, 0x90, 0x52, 0x3b, 0x13, - 0x97, 0x7c, 0x50, 0x6a, 0x41, 0x4e, 0x62, 0x72, 0xaa, 0x6f, 0x66, 0x7a, 0x51, 0x62, 0x49, 0x66, - 0x7e, 0x5e, 0x50, 0x6a, 0x72, 0x7e, 0x51, 0x4a, 0x71, 0x40, 0x51, 0x7e, 0x41, 0x7e, 0x71, 0x62, - 0x8e, 0x90, 0x08, 0x17, 0x6b, 0x49, 0x66, 0x49, 0x4e, 0xaa, 0x04, 0xa3, 0x02, 0xa3, 0x06, 0x67, - 0x10, 0x84, 0x23, 0xa4, 0xc0, 0xc5, 0x9d, 0x92, 0x5a, 0x9c, 0x5c, 0x94, 0x59, 0x00, 0xd2, 0x23, - 0xc1, 0x04, 0x96, 0x43, 0x16, 0x12, 0x0a, 0xe1, 0x62, 0x2f, 0x82, 0x18, 0x25, 0xc1, 0xac, 0xc0, - 0xac, 0xc1, 0x6d, 0x64, 0xa2, 0x87, 0x2d, 0x38, 0xf4, 0x9c, 0x12, 0x73, 0x12, 0xf3, 0x92, 0x53, - 0x8b, 0x42, 0xf2, 0x9d, 0xf3, 0xf3, 0x92, 0x53, 0xf3, 0x4a, 0x8a, 0x12, 0x4b, 0x52, 0x53, 0x02, - 0xf2, 0xf3, 0x73, 0x7c, 0x32, 0xf3, 0xb2, 0x9d, 0x58, 0x4e, 0xdc, 0x93, 0x67, 0x08, 0x82, 0x19, - 0x65, 0x15, 0xd6, 0xb1, 0x40, 0x9e, 0x61, 0xc6, 0x02, 0x79, 0x86, 0x17, 0x0b, 0xe4, 0x19, 0x4f, - 0x6d, 0xd1, 0x95, 0x82, 0x7a, 0x11, 0x14, 0xe8, 0x30, 0x13, 0x9d, 0xf3, 0xf3, 0x4a, 0x52, 0xf3, - 0x4a, 0xba, 0x9e, 0x6f, 0xd0, 0x52, 0x87, 0x85, 0x18, 0x01, 0x5f, 0x2a, 0xb5, 0x32, 0x71, 0xc9, - 0x85, 0x16, 0xa4, 0x24, 0x96, 0x0c, 0x95, 0x80, 0x08, 0x25, 0x2d, 0x20, 0xd4, 0x60, 0x01, 0x81, - 0xdf, 0x93, 0x4e, 0x5e, 0x27, 0x1e, 0xc9, 0x31, 0x5e, 0x78, 0x24, 0xc7, 0xf8, 0xe0, 0x91, 0x1c, - 0xe3, 0x84, 0xc7, 0x72, 0x0c, 0x17, 0x1e, 0xcb, 0x31, 0xdc, 0x78, 0x2c, 0xc7, 0x10, 0x65, 0x90, - 0x9e, 0x59, 0x92, 0x51, 0x9a, 0xa4, 0x97, 0x9c, 0x9f, 0xab, 0x0f, 0x35, 0x4c, 0x37, 0x27, 0x31, - 0xa9, 0x18, 0xc6, 0xd1, 0x2f, 0x33, 0x34, 0xd7, 0xaf, 0x80, 0x24, 0xcd, 0x92, 0xca, 0x82, 0xd4, - 0xe2, 0x24, 0x36, 0x70, 0x22, 0x33, 0x06, 0x04, 0x00, 0x00, 0xff, 0xff, 0x8c, 0xe5, 0x3d, 0x03, - 0x27, 0x03, 0x00, 0x00, + // 801 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x55, 0xcf, 0x6f, 0xe3, 0x44, + 0x14, 0x8e, 0x93, 0x6c, 0x56, 0x4c, 0x77, 0x11, 0x35, 0x81, 0x84, 0x2e, 0xb2, 0x83, 0x0f, 0xa5, + 0xac, 0x88, 0xbd, 0xe1, 0x87, 0x90, 0x22, 0x71, 0x68, 0x02, 0x95, 0x16, 0x6d, 0xa1, 0x72, 0x77, + 0x41, 0x70, 0xb1, 0x26, 0xe3, 0xa9, 0x33, 0x8a, 0x3d, 0x63, 0x66, 0x66, 0xcb, 0xf6, 0xc8, 0x01, + 0x81, 0x38, 0x71, 0x44, 0x9c, 0xfa, 0x27, 0x70, 0xe0, 0x8f, 0xa8, 0x38, 0xf5, 0x88, 0x38, 0x58, + 0xa8, 0x3d, 0xd0, 0x73, 0x8e, 0x5c, 0x40, 0x33, 0x63, 0x97, 0x00, 0x11, 0x55, 0xe8, 0x89, 0x4b, + 0xe2, 0xf7, 0xde, 0xe7, 0xef, 0xf9, 0x7d, 0xf3, 0x3e, 0x0d, 0x70, 0x98, 0xc8, 0x98, 0x20, 0x22, + 0x48, 0x60, 0x96, 0x05, 0x87, 0x83, 0x09, 0x96, 0x70, 0x10, 0x24, 0xec, 0xd0, 0xcf, 0x39, 0x93, + 0xcc, 0x6e, 0x97, 0x75, 0x5f, 0xd5, 0xfd, 0xb2, 0xbe, 0xd1, 0x4e, 0x58, 0xc2, 0x34, 0x20, 0x50, + 0x4f, 0x06, 0xbb, 0xe1, 0x2d, 0xe7, 0xc2, 0x14, 0x2b, 0x02, 0x83, 0x79, 0x69, 0x29, 0x46, 0x4c, + 0x21, 0xc7, 0x71, 0x09, 0x79, 0x01, 0x69, 0x4c, 0x64, 0xf8, 0x4d, 0x50, 0x96, 0xd6, 0x61, 0x46, + 0x28, 0x0b, 0xf4, 0xaf, 0x49, 0x79, 0x5f, 0xd6, 0x81, 0x1b, 0xe2, 0x3c, 0x85, 0x08, 0xef, 0x92, + 0x84, 0x43, 0x49, 0x18, 0x0d, 0x31, 0x62, 0x3c, 0x16, 0x7b, 0x9c, 0xe5, 0x4c, 0xc0, 0xd4, 0x6e, + 0x83, 0x1b, 0x92, 0xc8, 0x14, 0x77, 0xad, 0x9e, 0xb5, 0xf5, 0x54, 0x68, 0x02, 0xbb, 0x07, 0xd6, + 0x62, 0x2c, 0x10, 0x27, 0xb9, 0x7a, 0xa7, 0x5b, 0xd7, 0xb5, 0xc5, 0x94, 0xfd, 0x10, 0xdc, 0xe4, + 0x86, 0xaa, 0xdb, 0xe8, 0x35, 0xb6, 0xd6, 0x5e, 0x7b, 0xc3, 0x5f, 0x26, 0x87, 0x3f, 0x82, 0x29, + 0xa4, 0x08, 0xf3, 0x87, 0x6c, 0xcc, 0x28, 0xc2, 0x54, 0x72, 0x28, 0x71, 0xbc, 0xc7, 0x58, 0xfa, + 0x80, 0xd0, 0xd9, 0xa8, 0x79, 0x52, 0xb8, 0xb5, 0xb0, 0xa2, 0x1a, 0x7e, 0xf8, 0xd5, 0xb1, 0x5b, + 0xfb, 0xf6, 0xd8, 0xad, 0x5d, 0x1c, 0xbb, 0xd6, 0x8f, 0x3f, 0xf4, 0x37, 0xca, 0x11, 0x95, 0xe8, + 0x15, 0xe3, 0x98, 0x51, 0x89, 0xa9, 0xfc, 0xfa, 0xd7, 0xef, 0xef, 0xbe, 0x5c, 0x29, 0x76, 0xc5, + 0x94, 0xde, 0x17, 0x75, 0xe0, 0x3c, 0xca, 0x63, 0x28, 0xff, 0x2f, 0x42, 0x3c, 0x5a, 0x4d, 0x88, + 0xcd, 0x4a, 0x88, 0x7f, 0x1f, 0xd2, 0xbb, 0x68, 0x80, 0xe7, 0x55, 0x4b, 0x93, 0xff, 0x88, 0xc8, + 0xe9, 0x78, 0x67, 0x77, 0x57, 0x7d, 0x80, 0xfd, 0x0a, 0x68, 0xc5, 0x98, 0xb2, 0xec, 0x9e, 0x11, + 0x60, 0xb4, 0x3e, 0x2f, 0xdc, 0xdb, 0x47, 0x30, 0x4b, 0x87, 0x9e, 0xc9, 0x7b, 0x61, 0x09, 0xb8, + 0x84, 0x0e, 0x8c, 0x1e, 0xff, 0x80, 0x0e, 0x2a, 0xe8, 0xc0, 0x1e, 0x82, 0x5b, 0x92, 0xa0, 0x59, + 0x24, 0x72, 0x88, 0x08, 0x4d, 0xba, 0x8d, 0x9e, 0xb5, 0xd5, 0x1c, 0x75, 0xe6, 0x85, 0xfb, 0xac, + 0x79, 0x61, 0xb1, 0xea, 0x85, 0x6b, 0x2a, 0xdc, 0x37, 0x91, 0xfd, 0xb9, 0x05, 0x9e, 0xc3, 0x4f, + 0x72, 0x46, 0x31, 0x95, 0x11, 0x94, 0x51, 0xce, 0x09, 0xc2, 0x11, 0xa3, 0xb8, 0xdb, 0xd4, 0x6d, + 0xdf, 0x57, 0x92, 0xfd, 0x5c, 0xb8, 0x9b, 0x09, 0x91, 0xd3, 0xc7, 0x13, 0x1f, 0xb1, 0xac, 0xb4, + 0x44, 0xf9, 0xd7, 0x17, 0xf1, 0x2c, 0x90, 0x47, 0x39, 0x16, 0xfe, 0x7d, 0x2a, 0xe7, 0x85, 0xfb, + 0xa2, 0xe9, 0xb9, 0x94, 0xd4, 0x0b, 0xed, 0x2a, 0xbf, 0x2d, 0xf7, 0x54, 0xf6, 0x03, 0x8a, 0xed, + 0x19, 0xb8, 0x2d, 0x72, 0x8e, 0x61, 0x1c, 0x1d, 0x40, 0x24, 0x19, 0xef, 0xde, 0xd0, 0xad, 0x77, + 0x56, 0x68, 0xfd, 0x0e, 0x46, 0xf3, 0xc2, 0x6d, 0x9b, 0xd6, 0x7f, 0x21, 0xf3, 0xc2, 0x5b, 0x26, + 0xde, 0xd1, 0xa1, 0xfd, 0x2e, 0x78, 0x66, 0x52, 0x6e, 0x49, 0x94, 0x33, 0x96, 0x46, 0x24, 0xee, + 0xb6, 0xb4, 0x60, 0x77, 0xe6, 0x85, 0xdb, 0x31, 0x0c, 0x7f, 0x47, 0x78, 0xe1, 0xd3, 0x55, 0x4a, + 0x9d, 0xec, 0xfd, 0x78, 0xd8, 0x54, 0x3b, 0xe3, 0xfd, 0x56, 0x07, 0x6f, 0x8e, 0x39, 0x86, 0x12, + 0x2f, 0xee, 0xdb, 0x03, 0xf2, 0xe9, 0x63, 0x12, 0x13, 0x79, 0xa4, 0xb0, 0x62, 0x9b, 0xc6, 0xea, + 0xec, 0x25, 0x53, 0x5b, 0x70, 0x6d, 0x27, 0x7c, 0x67, 0x81, 0x3b, 0xfa, 0xa3, 0xca, 0x25, 0x8e, + 0x3e, 0x23, 0x72, 0x1a, 0xa1, 0x83, 0x2c, 0x8b, 0x52, 0x42, 0x67, 0xa5, 0x3d, 0x5e, 0x5d, 0x6e, + 0x8f, 0xe5, 0x5b, 0x39, 0xf2, 0x95, 0xd0, 0xf3, 0xc2, 0xdd, 0x34, 0xc3, 0x23, 0x3d, 0x50, 0x84, + 0x52, 0x33, 0x3d, 0xa4, 0xb1, 0xa6, 0x8e, 0x24, 0xd3, 0x7d, 0xbc, 0xb0, 0x93, 0x5f, 0xf2, 0x08, + 0x4d, 0x74, 0x90, 0x65, 0x8a, 0x68, 0x98, 0xae, 0x66, 0xa8, 0xb7, 0x2b, 0x43, 0xfd, 0x27, 0x09, + 0xbd, 0xdf, 0x2d, 0xe0, 0xed, 0x63, 0xb9, 0x8f, 0x60, 0x4a, 0x68, 0x62, 0x8e, 0x57, 0xb1, 0x73, + 0x96, 0xa6, 0x98, 0x5f, 0x5b, 0xe9, 0x0e, 0xb8, 0x59, 0xed, 0x87, 0x36, 0x54, 0xd8, 0xca, 0xf5, + 0xd1, 0xdb, 0x7d, 0x60, 0xa3, 0xcb, 0x36, 0x11, 0x8c, 0x63, 0x8e, 0x85, 0x30, 0x76, 0x09, 0xd7, + 0xff, 0xac, 0x6c, 0x9b, 0xc2, 0xf0, 0xe3, 0xd5, 0x44, 0xb9, 0x5b, 0x89, 0x72, 0xf5, 0x68, 0xa3, + 0xf7, 0x4e, 0xce, 0x1c, 0xeb, 0xf4, 0xcc, 0xb1, 0x7e, 0x39, 0x73, 0xac, 0x6f, 0xce, 0x9d, 0xda, + 0xe9, 0xb9, 0x53, 0xfb, 0xe9, 0xdc, 0xa9, 0x7d, 0x72, 0x6f, 0xc1, 0x33, 0x25, 0x61, 0x3f, 0x85, + 0x13, 0x51, 0x05, 0xc1, 0xe1, 0xe0, 0xad, 0xe0, 0x89, 0xb9, 0x04, 0xb5, 0x83, 0x26, 0x2d, 0x7d, + 0x9d, 0xbd, 0xfe, 0x47, 0x00, 0x00, 0x00, 0xff, 0xff, 0x68, 0x7c, 0x85, 0x26, 0x91, 0x07, 0x00, + 0x00, } func (this *ReplaceMigrationRecordsProposal) Equal(that interface{}) bool { @@ -221,6 +404,113 @@ func (this *UpdateMigrationRecordsProposal) Equal(that interface{}) bool { } return true } +func (this *PoolRecordWithCFMMLink) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*PoolRecordWithCFMMLink) + if !ok { + that2, ok := that.(PoolRecordWithCFMMLink) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.Denom0 != that1.Denom0 { + return false + } + if this.Denom1 != that1.Denom1 { + return false + } + if this.TickSpacing != that1.TickSpacing { + return false + } + if !this.ExponentAtPriceOne.Equal(that1.ExponentAtPriceOne) { + return false + } + if !this.SpreadFactor.Equal(that1.SpreadFactor) { + return false + } + if this.BalancerPoolId != that1.BalancerPoolId { + return false + } + return true +} +func (this *CreateConcentratedLiquidityPoolsAndLinktoCFMMProposal) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*CreateConcentratedLiquidityPoolsAndLinktoCFMMProposal) + if !ok { + that2, ok := that.(CreateConcentratedLiquidityPoolsAndLinktoCFMMProposal) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.Title != that1.Title { + return false + } + if this.Description != that1.Description { + return false + } + if len(this.PoolRecordsWithCfmmLink) != len(that1.PoolRecordsWithCfmmLink) { + return false + } + for i := range this.PoolRecordsWithCfmmLink { + if !this.PoolRecordsWithCfmmLink[i].Equal(&that1.PoolRecordsWithCfmmLink[i]) { + return false + } + } + return true +} +func (this *SetScalingFactorControllerProposal) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*SetScalingFactorControllerProposal) + if !ok { + that2, ok := that.(SetScalingFactorControllerProposal) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.Title != that1.Title { + return false + } + if this.Description != that1.Description { + return false + } + if this.PoolId != that1.PoolId { + return false + } + if this.ControllerAddress != that1.ControllerAddress { + return false + } + return true +} func (m *ReplaceMigrationRecordsProposal) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -248,145 +538,902 @@ func (m *ReplaceMigrationRecordsProposal) MarshalToSizedBuffer(dAtA []byte) (int if err != nil { return 0, err } - i -= size - i = encodeVarintGov(dAtA, i, uint64(size)) + 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) + i = encodeVarintGov(dAtA, i, uint64(len(m.Description))) + i-- + dAtA[i] = 0x12 + } + if len(m.Title) > 0 { + i -= len(m.Title) + copy(dAtA[i:], m.Title) + i = encodeVarintGov(dAtA, i, uint64(len(m.Title))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *UpdateMigrationRecordsProposal) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *UpdateMigrationRecordsProposal) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *UpdateMigrationRecordsProposal) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Records) > 0 { + for iNdEx := len(m.Records) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Records[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + 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) + i = encodeVarintGov(dAtA, i, uint64(len(m.Description))) + i-- + dAtA[i] = 0x12 + } + if len(m.Title) > 0 { + i -= len(m.Title) + copy(dAtA[i:], m.Title) + i = encodeVarintGov(dAtA, i, uint64(len(m.Title))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *PoolRecordWithCFMMLink) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *PoolRecordWithCFMMLink) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *PoolRecordWithCFMMLink) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.BalancerPoolId != 0 { + i = encodeVarintGov(dAtA, i, uint64(m.BalancerPoolId)) + i-- + dAtA[i] = 0x30 + } + { + size := m.SpreadFactor.Size() + i -= size + if _, err := m.SpreadFactor.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintGov(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x2a + { + size := m.ExponentAtPriceOne.Size() + i -= size + if _, err := m.ExponentAtPriceOne.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintGov(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + if m.TickSpacing != 0 { + i = encodeVarintGov(dAtA, i, uint64(m.TickSpacing)) + i-- + dAtA[i] = 0x18 + } + if len(m.Denom1) > 0 { + i -= len(m.Denom1) + copy(dAtA[i:], m.Denom1) + i = encodeVarintGov(dAtA, i, uint64(len(m.Denom1))) + i-- + dAtA[i] = 0x12 + } + if len(m.Denom0) > 0 { + i -= len(m.Denom0) + copy(dAtA[i:], m.Denom0) + i = encodeVarintGov(dAtA, i, uint64(len(m.Denom0))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *CreateConcentratedLiquidityPoolsAndLinktoCFMMProposal) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *CreateConcentratedLiquidityPoolsAndLinktoCFMMProposal) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *CreateConcentratedLiquidityPoolsAndLinktoCFMMProposal) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.PoolRecordsWithCfmmLink) > 0 { + for iNdEx := len(m.PoolRecordsWithCfmmLink) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.PoolRecordsWithCfmmLink[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + 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) + i = encodeVarintGov(dAtA, i, uint64(len(m.Description))) + i-- + dAtA[i] = 0x12 + } + if len(m.Title) > 0 { + i -= len(m.Title) + copy(dAtA[i:], m.Title) + i = encodeVarintGov(dAtA, i, uint64(len(m.Title))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *SetScalingFactorControllerProposal) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *SetScalingFactorControllerProposal) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *SetScalingFactorControllerProposal) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.ControllerAddress) > 0 { + i -= len(m.ControllerAddress) + copy(dAtA[i:], m.ControllerAddress) + i = encodeVarintGov(dAtA, i, uint64(len(m.ControllerAddress))) + i-- + dAtA[i] = 0x22 + } + if m.PoolId != 0 { + i = encodeVarintGov(dAtA, i, uint64(m.PoolId)) + i-- + dAtA[i] = 0x18 + } + if len(m.Description) > 0 { + i -= len(m.Description) + copy(dAtA[i:], m.Description) + i = encodeVarintGov(dAtA, i, uint64(len(m.Description))) + i-- + dAtA[i] = 0x12 + } + if len(m.Title) > 0 { + i -= len(m.Title) + copy(dAtA[i:], m.Title) + i = encodeVarintGov(dAtA, i, uint64(len(m.Title))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func encodeVarintGov(dAtA []byte, offset int, v uint64) int { + offset -= sovGov(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *ReplaceMigrationRecordsProposal) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Title) + if l > 0 { + n += 1 + l + sovGov(uint64(l)) + } + l = len(m.Description) + if l > 0 { + n += 1 + l + sovGov(uint64(l)) + } + if len(m.Records) > 0 { + for _, e := range m.Records { + l = e.Size() + n += 1 + l + sovGov(uint64(l)) + } + } + return n +} + +func (m *UpdateMigrationRecordsProposal) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Title) + if l > 0 { + n += 1 + l + sovGov(uint64(l)) + } + l = len(m.Description) + if l > 0 { + n += 1 + l + sovGov(uint64(l)) + } + if len(m.Records) > 0 { + for _, e := range m.Records { + l = e.Size() + n += 1 + l + sovGov(uint64(l)) + } + } + return n +} + +func (m *PoolRecordWithCFMMLink) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Denom0) + if l > 0 { + n += 1 + l + sovGov(uint64(l)) + } + l = len(m.Denom1) + if l > 0 { + n += 1 + l + sovGov(uint64(l)) + } + if m.TickSpacing != 0 { + n += 1 + sovGov(uint64(m.TickSpacing)) + } + l = m.ExponentAtPriceOne.Size() + n += 1 + l + sovGov(uint64(l)) + l = m.SpreadFactor.Size() + n += 1 + l + sovGov(uint64(l)) + if m.BalancerPoolId != 0 { + n += 1 + sovGov(uint64(m.BalancerPoolId)) + } + return n +} + +func (m *CreateConcentratedLiquidityPoolsAndLinktoCFMMProposal) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Title) + if l > 0 { + n += 1 + l + sovGov(uint64(l)) + } + l = len(m.Description) + if l > 0 { + n += 1 + l + sovGov(uint64(l)) + } + if len(m.PoolRecordsWithCfmmLink) > 0 { + for _, e := range m.PoolRecordsWithCfmmLink { + l = e.Size() + n += 1 + l + sovGov(uint64(l)) + } + } + return n +} + +func (m *SetScalingFactorControllerProposal) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Title) + if l > 0 { + n += 1 + l + sovGov(uint64(l)) + } + l = len(m.Description) + if l > 0 { + n += 1 + l + sovGov(uint64(l)) + } + if m.PoolId != 0 { + n += 1 + sovGov(uint64(m.PoolId)) + } + l = len(m.ControllerAddress) + if l > 0 { + n += 1 + l + sovGov(uint64(l)) + } + return n +} + +func sovGov(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozGov(x uint64) (n int) { + return sovGov(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *ReplaceMigrationRecordsProposal) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGov + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ReplaceMigrationRecordsProposal: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ReplaceMigrationRecordsProposal: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Title", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGov + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGov + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGov + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Title = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Description", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGov + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGov + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGov + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Description = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Records", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGov + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGov + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGov + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Records = append(m.Records, migration.BalancerToConcentratedPoolLink{}) + if err := m.Records[len(m.Records)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGov(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGov + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *UpdateMigrationRecordsProposal) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGov + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: UpdateMigrationRecordsProposal: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: UpdateMigrationRecordsProposal: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Title", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGov + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGov + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGov + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Title = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Description", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGov + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGov + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGov + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Description = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Records", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGov + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGov + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGov + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Records = append(m.Records, migration.BalancerToConcentratedPoolLink{}) + if err := m.Records[len(m.Records)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGov(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGov + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *PoolRecordWithCFMMLink) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGov + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: PoolRecordWithCFMMLink: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: PoolRecordWithCFMMLink: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Denom0", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGov + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGov + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGov + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Denom0 = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Denom1", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGov + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGov + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGov + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Denom1 = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field TickSpacing", wireType) + } + m.TickSpacing = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGov + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.TickSpacing |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ExponentAtPriceOne", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGov + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } } - i-- - dAtA[i] = 0x1a - } - } - if len(m.Description) > 0 { - i -= len(m.Description) - copy(dAtA[i:], m.Description) - i = encodeVarintGov(dAtA, i, uint64(len(m.Description))) - i-- - dAtA[i] = 0x12 - } - if len(m.Title) > 0 { - i -= len(m.Title) - copy(dAtA[i:], m.Title) - i = encodeVarintGov(dAtA, i, uint64(len(m.Title))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *UpdateMigrationRecordsProposal) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *UpdateMigrationRecordsProposal) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *UpdateMigrationRecordsProposal) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.Records) > 0 { - for iNdEx := len(m.Records) - 1; iNdEx >= 0; iNdEx-- { - { - size, err := m.Records[iNdEx].MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGov + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGov + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.ExponentAtPriceOne.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SpreadFactor", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGov + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break } - 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) - i = encodeVarintGov(dAtA, i, uint64(len(m.Description))) - i-- - dAtA[i] = 0x12 - } - if len(m.Title) > 0 { - i -= len(m.Title) - copy(dAtA[i:], m.Title) - i = encodeVarintGov(dAtA, i, uint64(len(m.Title))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func encodeVarintGov(dAtA []byte, offset int, v uint64) int { - offset -= sovGov(v) - base := offset - for v >= 1<<7 { - dAtA[offset] = uint8(v&0x7f | 0x80) - v >>= 7 - offset++ - } - dAtA[offset] = uint8(v) - return base -} -func (m *ReplaceMigrationRecordsProposal) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.Title) - if l > 0 { - n += 1 + l + sovGov(uint64(l)) - } - l = len(m.Description) - if l > 0 { - n += 1 + l + sovGov(uint64(l)) - } - if len(m.Records) > 0 { - for _, e := range m.Records { - l = e.Size() - n += 1 + l + sovGov(uint64(l)) + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGov + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGov + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.SpreadFactor.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 6: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field BalancerPoolId", wireType) + } + m.BalancerPoolId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGov + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.BalancerPoolId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipGov(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGov + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy } } - return n -} -func (m *UpdateMigrationRecordsProposal) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.Title) - if l > 0 { - n += 1 + l + sovGov(uint64(l)) - } - l = len(m.Description) - if l > 0 { - n += 1 + l + sovGov(uint64(l)) - } - if len(m.Records) > 0 { - for _, e := range m.Records { - l = e.Size() - n += 1 + l + sovGov(uint64(l)) - } + if iNdEx > l { + return io.ErrUnexpectedEOF } - return n -} - -func sovGov(x uint64) (n int) { - return (math_bits.Len64(x|1) + 6) / 7 -} -func sozGov(x uint64) (n int) { - return sovGov(uint64((x << 1) ^ uint64((int64(x) >> 63)))) + return nil } -func (m *ReplaceMigrationRecordsProposal) Unmarshal(dAtA []byte) error { +func (m *CreateConcentratedLiquidityPoolsAndLinktoCFMMProposal) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -409,10 +1456,10 @@ func (m *ReplaceMigrationRecordsProposal) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: ReplaceMigrationRecordsProposal: wiretype end group for non-group") + return fmt.Errorf("proto: CreateConcentratedLiquidityPoolsAndLinktoCFMMProposal: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: ReplaceMigrationRecordsProposal: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: CreateConcentratedLiquidityPoolsAndLinktoCFMMProposal: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -481,7 +1528,7 @@ func (m *ReplaceMigrationRecordsProposal) Unmarshal(dAtA []byte) error { iNdEx = postIndex case 3: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Records", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field PoolRecordsWithCfmmLink", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -508,8 +1555,8 @@ func (m *ReplaceMigrationRecordsProposal) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Records = append(m.Records, migration.BalancerToConcentratedPoolLink{}) - if err := m.Records[len(m.Records)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + m.PoolRecordsWithCfmmLink = append(m.PoolRecordsWithCfmmLink, PoolRecordWithCFMMLink{}) + if err := m.PoolRecordsWithCfmmLink[len(m.PoolRecordsWithCfmmLink)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex @@ -534,7 +1581,7 @@ func (m *ReplaceMigrationRecordsProposal) Unmarshal(dAtA []byte) error { } return nil } -func (m *UpdateMigrationRecordsProposal) Unmarshal(dAtA []byte) error { +func (m *SetScalingFactorControllerProposal) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -557,10 +1604,10 @@ func (m *UpdateMigrationRecordsProposal) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: UpdateMigrationRecordsProposal: wiretype end group for non-group") + return fmt.Errorf("proto: SetScalingFactorControllerProposal: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: UpdateMigrationRecordsProposal: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: SetScalingFactorControllerProposal: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -628,10 +1675,29 @@ func (m *UpdateMigrationRecordsProposal) Unmarshal(dAtA []byte) error { m.Description = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field PoolId", wireType) + } + m.PoolId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGov + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.PoolId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 4: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Records", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field ControllerAddress", wireType) } - var msglen int + var stringLen uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowGov @@ -641,25 +1707,23 @@ func (m *UpdateMigrationRecordsProposal) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - msglen |= int(b&0x7F) << shift + stringLen |= uint64(b&0x7F) << shift if b < 0x80 { break } } - if msglen < 0 { + intStringLen := int(stringLen) + if intStringLen < 0 { return ErrInvalidLengthGov } - postIndex := iNdEx + msglen + postIndex := iNdEx + intStringLen if postIndex < 0 { return ErrInvalidLengthGov } if postIndex > l { return io.ErrUnexpectedEOF } - m.Records = append(m.Records, migration.BalancerToConcentratedPoolLink{}) - if err := m.Records[len(m.Records)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } + m.ControllerAddress = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex default: iNdEx = preIndex diff --git a/x/ibc-rate-limit/bytecode/rate_limiter.wasm b/x/ibc-rate-limit/bytecode/rate_limiter.wasm index 30b545e0612..9dee6eabb6f 100644 Binary files a/x/ibc-rate-limit/bytecode/rate_limiter.wasm and b/x/ibc-rate-limit/bytecode/rate_limiter.wasm differ diff --git a/x/ibc-rate-limit/contracts/rate-limiter/src/sudo.rs b/x/ibc-rate-limit/contracts/rate-limiter/src/sudo.rs index 36a16f638d4..80e6985d578 100644 --- a/x/ibc-rate-limit/contracts/rate-limiter/src/sudo.rs +++ b/x/ibc-rate-limit/contracts/rate-limiter/src/sudo.rs @@ -21,7 +21,7 @@ pub fn process_packet( #[cfg(test)] channel_value_mock: Option, ) -> Result { let (channel_id, denom) = packet.path_data(&direction); - let path = &Path::new(&channel_id, &denom); + let path = &Path::new(channel_id, denom); let funds = packet.get_funds(); #[cfg(test)] @@ -144,7 +144,7 @@ fn add_rate_limit_attributes(response: Response, result: &RateLimit) -> Response pub fn undo_send(deps: DepsMut, packet: Packet) -> Result { // Sudo call. Only go modules should be allowed to access this let (channel_id, denom) = packet.path_data(&FlowType::Out); // Sends have direction out. - let path = &Path::new(&channel_id, &denom); + let path = &Path::new(channel_id, &denom); let any_path = Path::new("any", &denom); let funds = packet.get_funds(); diff --git a/x/protorev/keeper/epoch_hook_test.go b/x/protorev/keeper/epoch_hook_test.go index d3f135514be..81b8f44ce66 100644 --- a/x/protorev/keeper/epoch_hook_test.go +++ b/x/protorev/keeper/epoch_hook_test.go @@ -152,8 +152,8 @@ func (s *KeeperTestSuite) TestUpdateHighestLiquidityPools() { // There are 2 pools with epochTwo and uosmo as denoms, // One in the GAMM module and one in the Concentrated Liquidity module. // pool with ID 48 has a liquidity value of 1,000,000 - // pool with ID 49 has a liquidity value of 2,000,000 - // pool with ID 49 should be returned as the highest liquidity pool + // pool with ID 50 has a liquidity value of 2,000,000 + // pool with ID 50 should be returned as the highest liquidity pool // We provide epochTwo as the input base denom, to test the method chooses the correct pool // across the GAMM and Concentrated Liquidity modules name: "Get highest liquidity pools for one GAMM pool and one Concentrated Liquidity pool", @@ -162,7 +162,7 @@ func (s *KeeperTestSuite) TestUpdateHighestLiquidityPools() { }, expectedBaseDenomPools: map[string]map[string]keeper.LiquidityPoolStruct{ "epochTwo": { - "uosmo": {Liquidity: sdk.Int(sdk.NewUintFromString("999999000000000001000000000000000000")), PoolId: 49}, + "uosmo": {Liquidity: sdk.Int(sdk.NewUintFromString("999999000000000001000000000000000000")), PoolId: 50}, }, }, }, diff --git a/x/protorev/keeper/hooks_test.go b/x/protorev/keeper/hooks_test.go index 76f620c45cb..17c3e683147 100644 --- a/x/protorev/keeper/hooks_test.go +++ b/x/protorev/keeper/hooks_test.go @@ -108,14 +108,14 @@ func (s *KeeperTestSuite) TestSwapping() { param: param{ expectedTrades: []types.Trade{ { - Pool: 49, + Pool: 50, TokenIn: "uosmo", TokenOut: "epochTwo", }, }, executeSwap: func() { - route := []poolmanagertypes.SwapAmountInRoute{{PoolId: 49, TokenOutDenom: "epochTwo"}} + route := []poolmanagertypes.SwapAmountInRoute{{PoolId: 50, TokenOutDenom: "epochTwo"}} _, err := s.App.PoolManagerKeeper.RouteExactAmountIn(s.Ctx, s.TestAccs[0], route, sdk.NewCoin("uosmo", sdk.NewInt(10)), sdk.NewInt(1)) s.Require().NoError(err) @@ -606,7 +606,7 @@ func (s *KeeperTestSuite) TestStoreJoinExitPoolSwaps() { { name: "Non-Gamm Pool, Return Early Do Not Store Any Swaps", param: param{ - poolId: 49, + poolId: 50, denom: "uosmo", isJoin: true, expectedSwap: types.Trade{}, diff --git a/x/protorev/keeper/keeper.go b/x/protorev/keeper/keeper.go index 7145aba4e58..ef7f0e75f59 100644 --- a/x/protorev/keeper/keeper.go +++ b/x/protorev/keeper/keeper.go @@ -19,11 +19,12 @@ type ( storeKey storetypes.StoreKey paramstore paramtypes.Subspace - accountKeeper types.AccountKeeper - bankKeeper types.BankKeeper - gammKeeper types.GAMMKeeper - epochKeeper types.EpochKeeper - poolmanagerKeeper types.PoolManagerKeeper + accountKeeper types.AccountKeeper + bankKeeper types.BankKeeper + gammKeeper types.GAMMKeeper + epochKeeper types.EpochKeeper + poolmanagerKeeper types.PoolManagerKeeper + concentratedLiquidityKeeper types.ConcentratedLiquidityKeeper } ) @@ -36,6 +37,7 @@ func NewKeeper( gammKeeper types.GAMMKeeper, epochKeeper types.EpochKeeper, poolmanagerKeeper types.PoolManagerKeeper, + concentratedLiquidityKeeper types.ConcentratedLiquidityKeeper, ) Keeper { // set KeyTable if it has not already been set if !ps.HasKeyTable() { @@ -43,14 +45,15 @@ func NewKeeper( } return Keeper{ - cdc: cdc, - storeKey: storeKey, - paramstore: ps, - accountKeeper: accountKeeper, - bankKeeper: bankKeeper, - gammKeeper: gammKeeper, - epochKeeper: epochKeeper, - poolmanagerKeeper: poolmanagerKeeper, + cdc: cdc, + storeKey: storeKey, + paramstore: ps, + accountKeeper: accountKeeper, + bankKeeper: bankKeeper, + gammKeeper: gammKeeper, + epochKeeper: epochKeeper, + poolmanagerKeeper: poolmanagerKeeper, + concentratedLiquidityKeeper: concentratedLiquidityKeeper, } } diff --git a/x/protorev/keeper/keeper_test.go b/x/protorev/keeper/keeper_test.go index 1c378d5a025..0cb50715022 100644 --- a/x/protorev/keeper/keeper_test.go +++ b/x/protorev/keeper/keeper_test.go @@ -888,6 +888,17 @@ func (s *KeeperTestSuite) setUpPools() { }, scalingFactors: []uint64{1, 1}, }, + { // Pool 49 - Used for CL testing + initialLiquidity: sdk.NewCoins( + sdk.NewCoin("uosmo", sdk.NewInt(10_000_000_000_000)), + sdk.NewCoin("epochTwo", sdk.NewInt(8_000_000_000_000)), + ), + poolParams: stableswap.PoolParams{ + SwapFee: sdk.NewDecWithPrec(0, 2), + ExitFee: sdk.NewDecWithPrec(0, 2), + }, + scalingFactors: []uint64{1, 1}, + }, } for _, pool := range s.stableSwapPools { @@ -895,13 +906,29 @@ func (s *KeeperTestSuite) setUpPools() { } // Create a concentrated liquidity pool for epoch_hook testing - // Pool 49 + // Pool 50 s.PrepareConcentratedPoolWithCoinsAndFullRangePosition("epochTwo", "uosmo") // Create a cosmwasm pool for testing - // Pool 50 + // Pool 51 s.PrepareCosmWasmPool() + // Create a concentrated liquidity pool for range testing + // Pool 52 + // Create the CL pool + clPool := s.PrepareCustomConcentratedPool(s.TestAccs[0], "epochTwo", "uosmo", apptesting.DefaultTickSpacing, sdk.ZeroDec()) + fundCoins := sdk.NewCoins(sdk.NewCoin("epochTwo", sdk.NewInt(10_000_000_000_000)), sdk.NewCoin("uosmo", sdk.NewInt(10_000_000_000_000))) + s.FundAcc(s.TestAccs[0], fundCoins) + s.CreateFullRangePosition(clPool, fundCoins) + + // Create a concentrated liquidity pool for range testing + // Pool 53 + // Create the CL pool + clPool = s.PrepareCustomConcentratedPool(s.TestAccs[0], "epochTwo", "uosmo", apptesting.DefaultTickSpacing, sdk.ZeroDec()) + fundCoins = sdk.NewCoins(sdk.NewCoin("epochTwo", sdk.NewInt(2_000_000_000)), sdk.NewCoin("uosmo", sdk.NewInt(1_000_000_000))) + s.FundAcc(s.TestAccs[0], fundCoins) + s.CreateFullRangePosition(clPool, fundCoins) + // Set all of the pool info into the stores err := s.App.ProtoRevKeeper.UpdatePools(s.Ctx) s.Require().NoError(err) diff --git a/x/protorev/keeper/posthandler_test.go b/x/protorev/keeper/posthandler_test.go index 725652e7e66..1897f807669 100644 --- a/x/protorev/keeper/posthandler_test.go +++ b/x/protorev/keeper/posthandler_test.go @@ -335,35 +335,6 @@ func (s *KeeperTestSuite) TestAnteHandle() { }, expectPass: true, }, - { - name: "Concentrated Liquidity - Many Ticks Run Out of Gas While Rebalacing, Ensure Doesn't Fail User Tx", - params: param{ - trades: []types.Trade{ - { - Pool: 51, - TokenOut: "ibc/0CD3A0285E1341859B5E86B6AB7682F023D03E97607CCC1DC95706411D866DF7", - TokenIn: "uosmo", - }, - }, - expectedNumOfTrades: sdk.NewInt(5), - expectedProfits: []sdk.Coin{ - { - Denom: "Atom", - Amount: sdk.NewInt(15_767_231), - }, - { - Denom: "ibc/0CD3A0285E1341859B5E86B6AB7682F023D03E97607CCC1DC95706411D866DF7", - Amount: sdk.NewInt(218_149_058), - }, - { - Denom: types.OsmosisDenomination, - Amount: sdk.NewInt(56_609_900), - }, - }, - expectedPoolPoints: 37, - }, - expectPass: true, - }, } // Ensure that the max points per tx is enough for the test suite diff --git a/x/protorev/keeper/rebalance.go b/x/protorev/keeper/rebalance.go index e3b658929ae..f1df9655f2f 100644 --- a/x/protorev/keeper/rebalance.go +++ b/x/protorev/keeper/rebalance.go @@ -24,19 +24,16 @@ func (k Keeper) IterateRoutes(ctx sdk.Context, routes []RouteMetaData, remaining // Find the max profit for the route if it exists inputCoin, profit, err := k.FindMaxProfitForRoute(ctx, routes[index], remainingTxPoolPoints, remainingBlockPoolPoints) if err != nil { - k.Logger(ctx).Error("Error finding max profit for route: ", err) + k.Logger(ctx).Error("Error finding max profit for route: " + err.Error()) continue } // If the profit is greater than zero, then we convert the profits to uosmo and compare profits in terms of uosmo if profit.GT(sdk.ZeroInt()) { - if inputCoin.Denom != types.OsmosisDenomination { - uosmoProfit, err := k.ConvertProfits(ctx, inputCoin, profit) - if err != nil { - k.Logger(ctx).Error("Error converting profits: ", err) - continue - } - profit = uosmoProfit + profit, err := k.ConvertProfits(ctx, inputCoin, profit) + if err != nil { + k.Logger(ctx).Error("Error converting profits: " + err.Error()) + continue } // Select the optimal route King of the Hill style (route with the highest profit will be executed) @@ -52,7 +49,13 @@ func (k Keeper) IterateRoutes(ctx sdk.Context, routes []RouteMetaData, remaining } // ConvertProfits converts the profit denom to uosmo to allow for a fair comparison of profits +// +// NOTE: This does not check the underlying pool before swapping so this may go over the MaxTicksCrossed. func (k Keeper) ConvertProfits(ctx sdk.Context, inputCoin sdk.Coin, profit sdk.Int) (sdk.Int, error) { + if inputCoin.Denom == types.OsmosisDenomination { + return profit, nil + } + // Get highest liquidity pool ID for the input coin and uosmo conversionPoolID, err := k.GetPoolForDenomPair(ctx, types.OsmosisDenomination, inputCoin.Denom) if err != nil { @@ -132,8 +135,11 @@ func (k Keeper) FindMaxProfitForRoute(ctx sdk.Context, route RouteMetaData, rema return sdk.Coin{}, sdk.ZeroInt(), err } - // Extend the search range if the max input amount is too small - curLeft, curRight = k.ExtendSearchRangeIfNeeded(ctx, route, inputDenom, curLeft, curRight) + // Update the search range if the max input amount is too small/large + curLeft, curRight, err = k.UpdateSearchRangeIfNeeded(ctx, route, inputDenom, curLeft, curRight) + if err != nil { + return sdk.Coin{}, sdk.ZeroInt(), err + } // Binary search to find the max profit for iteration := 0; curLeft.LT(curRight) && iteration < types.MaxIterations; iteration++ { @@ -167,12 +173,156 @@ func (k Keeper) FindMaxProfitForRoute(ctx sdk.Context, route RouteMetaData, rema return tokenIn, profit, nil } +// UpdateSearchRangeIfNeeded updates the search range for the binary search. First, we check if there are any +// concentrated liquidity pools in the route. If there are, then we may need to reduce the upper bound of the +// binary search since it is gas intensive to move across several ticks. Next, we determine if the current bound +// includes the optimal amount in. If it does not, then we can extend the search range to capture more profits. +func (k Keeper) UpdateSearchRangeIfNeeded( + ctx sdk.Context, + route RouteMetaData, + inputDenom string, + curLeft, curRight sdk.Int, +) (sdk.Int, sdk.Int, error) { + // If there are concentrated liquidity pools in the route, then we may need to reduce the upper bound of the binary search. + updatedMax, err := k.CalculateUpperBoundForSearch(ctx, route, inputDenom) + if err != nil { + return sdk.ZeroInt(), sdk.ZeroInt(), err + } + + // In the case where the updated upper bound is less than the current upper bound, we know we will not extend + // the search range so we can short-circuit return. + if updatedMax.LT(curRight) { + return curLeft, updatedMax, nil + } + + return k.ExtendSearchRangeIfNeeded(ctx, route, inputDenom, curLeft, curRight, updatedMax) +} + +// CalculateUpperBoundForSearch returns the max amount in that can be used for the binary search +// respecting the max ticks moved across all concentrated liquidity pools in the route. +func (k Keeper) CalculateUpperBoundForSearch( + ctx sdk.Context, + route RouteMetaData, + inputDenom string, +) (sdk.Int, error) { + var intermidiateCoin sdk.Coin + + // Iterate through all CL pools and determine the maximal amount of input that can be used + // respecting the max ticks moved. + for index := route.Route.Length() - 1; index >= 0; index-- { + hop := route.Route[index] + pool, err := k.poolmanagerKeeper.GetPool(ctx, hop.PoolId) + if err != nil { + return sdk.ZeroInt(), err + } + + tokenInDenom := inputDenom + if index > 0 { + tokenInDenom = route.Route[index-1].TokenOutDenom + } + + switch { + case pool.GetType() == poolmanagertypes.Concentrated: + // If the pool is a concentrated liquidity pool, then check the maximum amount in that can be used + // and determine what this amount is as an input at the previous pool (working all the way up to the + // beginning of the route). + maxTokenIn, maxTokenOut, err := k.concentratedLiquidityKeeper.ComputeMaxInAmtGivenMaxTicksCrossed( + ctx, + pool.GetId(), + tokenInDenom, + types.MaxTicksCrossed, + ) + if err != nil { + return sdk.ZeroInt(), err + } + + // if there have been no other CL pools in the route, then we can set the intermediate coin to the max input amount. + // Additionally, if the amount of the previous token is greater than the possible amount from this pool, then we + // can set the intermediate coin to the max input amount (from the current pool). Otherwise we have to do a + // safe swap given the previous max amount. + if intermidiateCoin.IsNil() || maxTokenOut.Amount.LT(intermidiateCoin.Amount) { + intermidiateCoin = maxTokenIn + continue + } + + // In the scenario where there are multiple CL pools in a route, we select the one that inputs + // the smaller amount to ensure we do not overstep the max ticks moved. + intermidiateCoin, err = k.executeSafeSwap(ctx, pool.GetId(), intermidiateCoin, tokenInDenom, route.StepSize) + if err != nil { + return sdk.ZeroInt(), err + } + case !intermidiateCoin.IsNil(): + // If we have already seen a CL pool in the route, then simply propagate the intermediate coin up + // the route. + intermidiateCoin, err = k.executeSafeSwap(ctx, pool.GetId(), intermidiateCoin, tokenInDenom, route.StepSize) + if err != nil { + return sdk.ZeroInt(), err + } + } + } + + // In the case where there are no CL pools, we want to return the extended max input amount + if intermidiateCoin.IsNil() { + return types.ExtendedMaxInputAmount, nil + } + + // Ensure that the normalized upper bound is not greater than the extended max input amount + upperBound := intermidiateCoin.Amount.Quo(route.StepSize) + if upperBound.GT(types.ExtendedMaxInputAmount) { + return types.ExtendedMaxInputAmount, nil + } + + return upperBound, nil +} + +// executeSafeSwap executes a safe swap by first ensuring the swap amount is less than the +// amount of total liquidity in the pool. +func (k Keeper) executeSafeSwap( + ctx sdk.Context, + poolID uint64, + outputCoin sdk.Coin, + tokenInDenom string, + stepSize sdk.Int, +) (sdk.Coin, error) { + liquidity, err := k.poolmanagerKeeper.GetTotalPoolLiquidity(ctx, poolID) + if err != nil { + return sdk.NewCoin(tokenInDenom, sdk.ZeroInt()), err + } + + // At most we can swap half of the liquidity in the pool + liquidTokenAmt := liquidity.AmountOf(outputCoin.Denom).Quo(sdk.NewInt(4)) + if liquidTokenAmt.LT(outputCoin.Amount) { + outputCoin.Amount = liquidTokenAmt + } + + amt, err := k.poolmanagerKeeper.MultihopEstimateInGivenExactAmountOut( + ctx, + poolmanagertypes.SwapAmountOutRoutes{ + { + PoolId: poolID, + TokenInDenom: tokenInDenom, + }, + }, + outputCoin, + ) + if err != nil { + return sdk.NewCoin(tokenInDenom, sdk.ZeroInt()), err + } + + return sdk.NewCoin(tokenInDenom, amt), nil +} + // Determine if the binary search range needs to be extended -func (k Keeper) ExtendSearchRangeIfNeeded(ctx sdk.Context, route RouteMetaData, inputDenom string, curLeft, curRight sdk.Int) (sdk.Int, sdk.Int) { +func (k Keeper) ExtendSearchRangeIfNeeded( + ctx sdk.Context, + route RouteMetaData, + inputDenom string, + curLeft, curRight, updatedMax sdk.Int, +) (sdk.Int, sdk.Int, error) { // Get the profit for the maximum amount in _, maxInProfit, err := k.EstimateMultihopProfit(ctx, inputDenom, curRight.Mul(route.StepSize), route.Route) if err != nil { - return curLeft, curRight + return sdk.ZeroInt(), sdk.ZeroInt(), err } // If the profit for the maximum amount in is still increasing, then we can increase the range of the binary search @@ -180,17 +330,17 @@ func (k Keeper) ExtendSearchRangeIfNeeded(ctx sdk.Context, route RouteMetaData, // Get the profit for the maximum amount in + 1 _, maxInProfitPlusOne, err := k.EstimateMultihopProfit(ctx, inputDenom, curRight.Add(sdk.OneInt()).Mul(route.StepSize), route.Route) if err != nil { - return curLeft, curRight + return sdk.ZeroInt(), sdk.ZeroInt(), err } // Change the range of the binary search if the profit is still increasing if maxInProfitPlusOne.GT(maxInProfit) { curLeft = curRight - curRight = types.ExtendedMaxInputAmount + curRight = updatedMax } } - return curLeft, curRight + return curLeft, curRight, nil } // ExecuteTrade inputs a route, amount in, and rebalances the pool diff --git a/x/protorev/keeper/rebalance_test.go b/x/protorev/keeper/rebalance_test.go index 26c83e835c5..c6753381326 100644 --- a/x/protorev/keeper/rebalance_test.go +++ b/x/protorev/keeper/rebalance_test.go @@ -4,7 +4,9 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/osmosis-labs/osmosis/v17/app/apptesting" + "github.com/osmosis-labs/osmosis/v17/x/gamm/pool-models/stableswap" poolmanagertypes "github.com/osmosis-labs/osmosis/v17/x/poolmanager/types" + "github.com/osmosis-labs/osmosis/v17/x/protorev/keeper" protorevtypes "github.com/osmosis-labs/osmosis/v17/x/protorev/keeper" "github.com/osmosis-labs/osmosis/v17/x/protorev/types" ) @@ -165,6 +167,42 @@ var extendedRangeRoute = poolmanagertypes.SwapAmountInRoutes{ }, } +// Tests the binary search range for CL pools +var clPoolRouteExtended = poolmanagertypes.SwapAmountInRoutes{ + poolmanagertypes.SwapAmountInRoute{ + PoolId: 49, + TokenOutDenom: "uosmo", + }, + poolmanagertypes.SwapAmountInRoute{ + PoolId: 50, + TokenOutDenom: "epochTwo", + }, +} + +// Tests multiple CL pools in the same route +var clPoolRouteMulti = poolmanagertypes.SwapAmountInRoutes{ + poolmanagertypes.SwapAmountInRoute{ + PoolId: 52, + TokenOutDenom: "uosmo", + }, + poolmanagertypes.SwapAmountInRoute{ + PoolId: 53, + TokenOutDenom: "epochTwo", + }, +} + +// Tests reducing the binary search range +var clPoolRoute = poolmanagertypes.SwapAmountInRoutes{ + poolmanagertypes.SwapAmountInRoute{ + PoolId: 49, + TokenOutDenom: "uosmo", + }, + poolmanagertypes.SwapAmountInRoute{ + PoolId: 52, + TokenOutDenom: "epochTwo", + }, +} + // EstimateMultiHopSwap Panic catching test var panicRoute = poolmanagertypes.SwapAmountInRoutes{ poolmanagertypes.SwapAmountInRoute{ @@ -290,6 +328,36 @@ func (s *KeeperTestSuite) TestFindMaxProfitRoute() { }, expectPass: false, }, + { + name: "CL Route (extended range)", // This will search up to 131072 * stepsize + param: param{ + route: clPoolRouteExtended, + expectedAmtIn: sdk.NewInt(131_072_000_000), + expectedProfit: sdk.NewInt(295_125_808), + routePoolPoints: 7, + }, + expectPass: true, + }, + { + name: "CL Route", // This will search up to 131072 * stepsize + param: param{ + route: clPoolRoute, + expectedAmtIn: sdk.NewInt(13_159_000_000), + expectedProfit: sdk.NewInt(18_055_586), + routePoolPoints: 7, + }, + expectPass: true, + }, + { + name: "CL Route Multi", // This will search up to 131072 * stepsize + param: param{ + route: clPoolRouteMulti, + expectedAmtIn: sdk.NewInt(414_000_000), + expectedProfit: sdk.NewInt(171_555_698), + routePoolPoints: 12, + }, + expectPass: true, + }, } for _, test := range tests { @@ -667,3 +735,106 @@ func (s *KeeperTestSuite) TestRemainingPoolPointsForTx() { }) } } + +func (s *KeeperTestSuite) TestUpdateSearchRangeIfNeeded() { + s.Run("Extended search on stable pools", func() { + route := keeper.RouteMetaData{ + Route: extendedRangeRoute, + StepSize: sdk.NewInt(1_000_000), + } + + curLeft, curRight, err := s.App.ProtoRevKeeper.UpdateSearchRangeIfNeeded( + s.Ctx, + route, + "usdx", + sdk.OneInt(), + types.MaxInputAmount, + ) + s.Require().NoError(err) + s.Require().Equal(types.MaxInputAmount, curLeft) + s.Require().Equal(types.ExtendedMaxInputAmount, curRight) + }) + + s.Run("Extended search on CL pools", func() { + // Create two massive CL pools with a massive arb + clPool := s.PrepareCustomConcentratedPool(s.TestAccs[0], "atom", "uosmo", apptesting.DefaultTickSpacing, sdk.ZeroDec()) + fundCoins := sdk.NewCoins(sdk.NewCoin("atom", sdk.NewInt(10_000_000_000_000)), sdk.NewCoin("uosmo", sdk.NewInt(10_000_000_000_000))) + s.FundAcc(s.TestAccs[0], fundCoins) + s.CreateFullRangePosition(clPool, fundCoins) + + clPool2 := s.PrepareCustomConcentratedPool(s.TestAccs[0], "atom", "uosmo", apptesting.DefaultTickSpacing, sdk.ZeroDec()) + fundCoins = sdk.NewCoins(sdk.NewCoin("atom", sdk.NewInt(20_000_000_000_000)), sdk.NewCoin("uosmo", sdk.NewInt(10_000_000_000_000))) + s.FundAcc(s.TestAccs[0], fundCoins) + s.CreateFullRangePosition(clPool2, fundCoins) + + route := keeper.RouteMetaData{ + Route: poolmanagertypes.SwapAmountInRoutes{ + poolmanagertypes.SwapAmountInRoute{ + PoolId: clPool.GetId(), + TokenOutDenom: "uosmo", + }, + poolmanagertypes.SwapAmountInRoute{ + PoolId: clPool2.GetId(), + TokenOutDenom: "atom", + }, + }, + StepSize: sdk.NewInt(1_000_000), + } + + curLeft, curRight, err := s.App.ProtoRevKeeper.UpdateSearchRangeIfNeeded( + s.Ctx, + route, + "atom", + sdk.OneInt(), + types.MaxInputAmount, + ) + s.Require().NoError(err) + s.Require().Equal(types.MaxInputAmount, curLeft) + s.Require().Equal(types.ExtendedMaxInputAmount, curRight) + }) + + s.Run("Reduced search on CL pools", func() { + stablePool := s.createStableswapPool( + sdk.NewCoins( + sdk.NewCoin("uosmo", sdk.NewInt(25_000_000_000)), + sdk.NewCoin("eth", sdk.NewInt(20_000_000_000)), + ), + stableswap.PoolParams{ + SwapFee: sdk.NewDecWithPrec(0, 2), + ExitFee: sdk.NewDecWithPrec(0, 2), + }, + []uint64{1, 1}, + ) + + // Create two massive CL pools with a massive arb + clPool := s.PrepareCustomConcentratedPool(s.TestAccs[0], "eth", "uosmo", apptesting.DefaultTickSpacing, sdk.ZeroDec()) + fundCoins := sdk.NewCoins(sdk.NewCoin("eth", sdk.NewInt(10_000_000_000_000)), sdk.NewCoin("uosmo", sdk.NewInt(10_000_000_000_000))) + s.FundAcc(s.TestAccs[0], fundCoins) + s.CreateFullRangePosition(clPool, fundCoins) + + route := keeper.RouteMetaData{ + Route: poolmanagertypes.SwapAmountInRoutes{ + poolmanagertypes.SwapAmountInRoute{ + PoolId: stablePool, + TokenOutDenom: "eth", + }, + poolmanagertypes.SwapAmountInRoute{ + PoolId: clPool.GetId(), + TokenOutDenom: "uosmo", + }, + }, + StepSize: sdk.NewInt(1_000_000), + } + + curLeft, curRight, err := s.App.ProtoRevKeeper.UpdateSearchRangeIfNeeded( + s.Ctx, + route, + "uosmo", + sdk.OneInt(), + types.MaxInputAmount, + ) + s.Require().NoError(err) + s.Require().Equal(sdk.OneInt(), curLeft) + s.Require().Equal(sdk.NewInt(5141), curRight) + }) +} diff --git a/x/protorev/keeper/routes_test.go b/x/protorev/keeper/routes_test.go index 296b52d3a2f..70ac96276a0 100644 --- a/x/protorev/keeper/routes_test.go +++ b/x/protorev/keeper/routes_test.go @@ -349,13 +349,13 @@ func (s *KeeperTestSuite) TestCalculateRoutePoolPoints() { }, { description: "Valid route with a cosmwasm pool", - route: []poolmanagertypes.SwapAmountInRoute{{PoolId: 1, TokenOutDenom: ""}, {PoolId: 50, TokenOutDenom: ""}, {PoolId: 2, TokenOutDenom: ""}}, + route: []poolmanagertypes.SwapAmountInRoute{{PoolId: 1, TokenOutDenom: ""}, {PoolId: 51, TokenOutDenom: ""}, {PoolId: 2, TokenOutDenom: ""}}, expectedRoutePoolPoints: 8, expectedPass: true, }, { description: "Valid route with cw pool, balancer, stable swap and cl pool", - route: []poolmanagertypes.SwapAmountInRoute{{PoolId: 1, TokenOutDenom: ""}, {PoolId: 50, TokenOutDenom: ""}, {PoolId: 40, TokenOutDenom: ""}, {PoolId: 49, TokenOutDenom: ""}}, + route: []poolmanagertypes.SwapAmountInRoute{{PoolId: 1, TokenOutDenom: ""}, {PoolId: 51, TokenOutDenom: ""}, {PoolId: 40, TokenOutDenom: ""}, {PoolId: 50, TokenOutDenom: ""}}, expectedRoutePoolPoints: 10, expectedPass: true, }, diff --git a/x/protorev/protorev.md b/x/protorev/protorev.md index f63e824841c..f1b023b6c79 100644 --- a/x/protorev/protorev.md +++ b/x/protorev/protorev.md @@ -314,7 +314,7 @@ IterateRoutes iterates through a list of routes, determining the route and input ### FindMaxProfitForRoute -This will take in a route and determine the optimal amount to swap in to maximize profits, given the reserves of all of the pools that are swapped against in the route. +This will take in a route and determine the optimal amount to swap in to maximize profits, given the reserves of all of the pools that are swapped against in the route. The bounds of the binary search are dynamic and update per route (see `UpdateSearchRangeIfNeeded`) based on how computationally expensive (in terms of gas) swapping can be on that route. For instance, moving across several ticks on a concentrated pool is relatively expensive, so the bounds of the binary search with a route that includes that pool type may be smaller than a route that does not include that pool type. ### ExecuteTrade diff --git a/x/protorev/types/constants.go b/x/protorev/types/constants.go index 254eefb8013..ffdc56c2a7f 100644 --- a/x/protorev/types/constants.go +++ b/x/protorev/types/constants.go @@ -27,6 +27,10 @@ const MaxPoolPointsPerTx uint64 = 50 // to the maximum execution time (in ms) of protorev per block const MaxPoolPointsPerBlock uint64 = 200 +// Max number of ticks we can move in a concentrated pool swap. This will be parameterized in a +// follow up PR. +const MaxTicksCrossed uint64 = 5 + // ---------------- Module Profit Splitting Constants ---------------- // // Year 1 (20% of total profit) diff --git a/x/protorev/types/expected_keepers.go b/x/protorev/types/expected_keepers.go index 03b7ba41eb3..4e80c5acdd2 100644 --- a/x/protorev/types/expected_keepers.go +++ b/x/protorev/types/expected_keepers.go @@ -44,6 +44,11 @@ type PoolManagerKeeper interface { tokenIn sdk.Coin, ) (tokenOutAmount sdk.Int, err error) + MultihopEstimateInGivenExactAmountOut( + ctx sdk.Context, + routes []poolmanagertypes.SwapAmountOutRoute, + tokenOut sdk.Coin) (tokenInAmount sdk.Int, err error) + AllPools( ctx sdk.Context, ) ([]poolmanagertypes.PoolI, error) @@ -61,3 +66,14 @@ type PoolManagerKeeper interface { type EpochKeeper interface { GetEpochInfo(ctx sdk.Context, identifier string) epochtypes.EpochInfo } + +// ConcentratedLiquidityKeeper defines the ConcentratedLiquidity contract that must be fulfilled when +// creating a x/protorev keeper. +type ConcentratedLiquidityKeeper interface { + ComputeMaxInAmtGivenMaxTicksCrossed( + ctx sdk.Context, + poolId uint64, + tokenInDenom string, + maxTicksCrossed uint64, + ) (maxTokenIn, resultingTokenOut sdk.Coin, err error) +} diff --git a/x/tokenfactory/keeper/admins_test.go b/x/tokenfactory/keeper/admins_test.go index 30582a094e2..043e385f5b6 100644 --- a/x/tokenfactory/keeper/admins_test.go +++ b/x/tokenfactory/keeper/admins_test.go @@ -129,6 +129,15 @@ func (s *KeeperTestSuite) TestMintDenom() { ), expectPass: true, }, + { + desc: "error: try minting non-tokenfactory denom", + mintMsg: *types.NewMsgMintTo( + s.TestAccs[0].String(), + sdk.NewInt64Coin("uosmo", 10), + s.TestAccs[1].String(), + ), + expectPass: false, + }, } { s.Run(fmt.Sprintf("Case %s", tc.desc), func() { _, err := s.msgServer.Mint(sdk.WrapSDKContext(s.Ctx), &tc.mintMsg) @@ -217,6 +226,15 @@ func (s *KeeperTestSuite) TestBurnDenom() { ), expectPass: false, }, + { + desc: "fail case - burn non-tokenfactory denom", + burnMsg: *types.NewMsgBurnFrom( + s.TestAccs[0].String(), + sdk.NewInt64Coin("uosmo", 10), + moduleAdress.String(), + ), + expectPass: false, + }, } { s.Run(fmt.Sprintf("Case %s", tc.desc), func() { _, err := s.msgServer.Burn(sdk.WrapSDKContext(s.Ctx), &tc.burnMsg) diff --git a/x/tokenfactory/types/denoms.go b/x/tokenfactory/types/denoms.go index c705a9b95c5..658399856ef 100644 --- a/x/tokenfactory/types/denoms.go +++ b/x/tokenfactory/types/denoms.go @@ -1,12 +1,10 @@ package types import ( - fmt "fmt" "strings" errorsmod "cosmossdk.io/errors" sdk "github.com/cosmos/cosmos-sdk/types" - bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" ) const ( @@ -68,17 +66,3 @@ func DeconstructDenom(denom string) (creator string, subdenom string, err error) return creatorAddr.String(), subdenom, nil } - -// NewTokenFactoryDenomMintCoinsRestriction creates and returns a BankMintingRestrictionFn that only allows minting of -// valid tokenfactory denoms -func NewTokenFactoryDenomMintCoinsRestriction() bankkeeper.BankMintingRestrictionFn { - return func(ctx sdk.Context, coinsToMint sdk.Coins) error { - for _, coin := range coinsToMint { - _, _, err := DeconstructDenom(coin.Denom) - if err != nil { - return fmt.Errorf("does not have permission to mint %s", coin.Denom) - } - } - return nil - } -}