From d6e800e2971185bb3cca1519dcf36bf3efb2763b Mon Sep 17 00:00:00 2001 From: Roman Date: Sun, 23 Apr 2023 22:33:10 -0400 Subject: [PATCH] feat: CL permissionless pool creation param (#4952) * feat: CL permissionless pool creation param and gov prop * create pool * expose query for getting balancer and cl link * fix e2e test to update the new param * basic e2e test for canonical pool * updates * doc update * typos in e2e * updates * fix * updates * Update tests/e2e/e2e_test.go Co-authored-by: Adam Tucker * rename to ValidatePermissionlessPoolCreationEnabled * updates * Update x/gamm/keeper/keeper.go Co-authored-by: Matt, Park <45252226+mattverse@users.noreply.github.com> * updates * update localosmosis --------- Co-authored-by: Adam Tucker Co-authored-by: Matt, Park <45252226+mattverse@users.noreply.github.com> --- app/apptesting/concentrated_liquidity.go | 6 +- app/apptesting/test_suite.go | 2 +- app/upgrades/v16/concentrated_pool.go | 2 +- app/upgrades/v16/export_test.go | 5 - app/upgrades/v16/upgrades.go | 16 +- app/upgrades/v16/upgrades_test.go | 3 + .../concentrated-liquidity/params.proto | 9 + proto/osmosis/gamm/v1beta1/query.proto | 18 + tests/cl-genesis-positions/go.mod | 2 +- tests/cl-genesis-positions/go.sum | 4 +- tests/e2e/configurer/chain/commands.go | 8 +- tests/e2e/configurer/chain/queries.go | 13 + tests/e2e/e2e_test.go | 159 +++-- tests/e2e/scripts/daiosmov16.json | 2 +- tests/localosmosis/scripts/setup.sh | 3 + tests/mocks/pool_module.go | 28 + x/concentrated-liquidity/README.md | 8 + x/concentrated-liquidity/keeper.go | 9 + x/concentrated-liquidity/types/errors.go | 9 +- x/concentrated-liquidity/types/params.go | 37 +- x/concentrated-liquidity/types/params.pb.go | 102 ++- x/gamm/keeper/grpc_query.go | 18 + x/gamm/keeper/keeper.go | 6 + x/gamm/types/query.pb.go | 595 ++++++++++++++---- x/gamm/types/query.pb.gw.go | 101 +++ x/poolmanager/create_pool.go | 12 + x/poolmanager/create_pool_test.go | 81 ++- x/poolmanager/types/routes.go | 4 + 28 files changed, 1003 insertions(+), 259 deletions(-) diff --git a/app/apptesting/concentrated_liquidity.go b/app/apptesting/concentrated_liquidity.go index d2bbbf8bab7..aa532bbfa25 100644 --- a/app/apptesting/concentrated_liquidity.go +++ b/app/apptesting/concentrated_liquidity.go @@ -105,12 +105,14 @@ func (s *KeeperTestHelper) WithdrawFullRangePosition(pool types.ConcentratedPool s.Require().NoError(err) } -// SetupDefaultConcentratedLiquidityAuthorizedQuoteDenoms sets up the default authorized quote denoms. +// SetupConcentratedLiquidityDenomsAndPoolCreation sets up the default authorized quote denoms. +// Additionally, enables permissionless pool creation. // This is to overwrite the default params set in concentrated liquidity genesis to account for the test cases that // used various denoms before the authorized quote denoms were introduced. -func (s *KeeperTestHelper) SetupDefaultConcentratedLiquidityAuthorizedQuoteDenoms() { +func (s *KeeperTestHelper) SetupConcentratedLiquidityDenomsAndPoolCreation() { // modify authorized quote denoms to include test denoms. defaultParams := types.DefaultParams() + defaultParams.IsPermissionlessPoolCreationEnabled = true defaultParams.AuthorizedQuoteDenoms = append(defaultParams.AuthorizedQuoteDenoms, ETH, USDC, BAR, BAZ, FOO, UOSMO, STAKE) s.App.ConcentratedLiquidityKeeper.SetParams(s.Ctx, defaultParams) } diff --git a/app/apptesting/test_suite.go b/app/apptesting/test_suite.go index 1ca0cd2d2ef..e84228585db 100644 --- a/app/apptesting/test_suite.go +++ b/app/apptesting/test_suite.go @@ -65,7 +65,7 @@ func (s *KeeperTestHelper) Setup() { s.SetEpochStartTime() s.TestAccs = CreateRandomAccounts(3) - s.SetupDefaultConcentratedLiquidityAuthorizedQuoteDenoms() + s.SetupConcentratedLiquidityDenomsAndPoolCreation() } func (s *KeeperTestHelper) SetupTestForInitGenesis() { diff --git a/app/upgrades/v16/concentrated_pool.go b/app/upgrades/v16/concentrated_pool.go index bde0e3fa7d6..98859e8cbcc 100644 --- a/app/upgrades/v16/concentrated_pool.go +++ b/app/upgrades/v16/concentrated_pool.go @@ -48,7 +48,7 @@ func createConcentratedPoolFromCFMM(ctx sdk.Context, cfmmPoolIdToLinkWith uint64 swapFee := cfmmPool.GetSwapFee(ctx) - createPoolMsg := clmodel.NewMsgCreateConcentratedPool(poolCreatorAddress, desiredDenom0, denom1, tickSpacing, swapFee) + createPoolMsg := clmodel.NewMsgCreateConcentratedPool(poolCreatorAddress, desiredDenom0, denom1, TickSpacing, swapFee) concentratedPool, err := poolmanagerKeeper.CreateConcentratedPoolAsPoolManager(ctx, createPoolMsg) if err != nil { return nil, err diff --git a/app/upgrades/v16/export_test.go b/app/upgrades/v16/export_test.go index 1bbb9b5e81f..c970579f9a4 100644 --- a/app/upgrades/v16/export_test.go +++ b/app/upgrades/v16/export_test.go @@ -10,11 +10,6 @@ import ( poolmanagertypes "github.com/osmosis-labs/osmosis/v15/x/poolmanager/types" ) -const ( - DaiOsmoPoolId = daiOsmoPoolId - DesiredDenom0 = desiredDenom0 -) - var ( AuthorizedQuoteDenoms = authorizedQuoteDenoms ) diff --git a/app/upgrades/v16/upgrades.go b/app/upgrades/v16/upgrades.go index d138e8bc346..1c3a468e623 100644 --- a/app/upgrades/v16/upgrades.go +++ b/app/upgrades/v16/upgrades.go @@ -14,13 +14,20 @@ const ( // https://app.osmosis.zone/pool/674 // Note, new concentrated liquidity pool // swap fee is initialized to be the same as the balancers pool swap fee of 0.2%. - daiOsmoPoolId = uint64(674) + DaiOsmoPoolId = uint64(674) // Denom0 translates to a base asset while denom1 to a quote asset // We want quote asset to be DAI so that when the limit orders on ticks // are implemented, we have tick spacing in terms of DAI as the quote. - desiredDenom0 = "uosmo" + DesiredDenom0 = "uosmo" // TODO: confirm pre-launch. - tickSpacing = 1 + TickSpacing = 1 + + // isPermissionlessPoolCreationEnabledCL is a boolean that determines if + // concentrated liquidity pools can be created via message. At launch, + // we consider allowing only governance to create pools, and then later + // allowing permissionless pool creation by switching this flag to true + // with a governance proposal. + IsPermissionlessPoolCreationEnabledCL = false ) var ( @@ -57,9 +64,10 @@ func CreateUpgradeHandler( // for visibility of the final configuration. defaultConcentratedLiquidityParams := keepers.ConcentratedLiquidityKeeper.GetParams(ctx) defaultConcentratedLiquidityParams.AuthorizedQuoteDenoms = authorizedQuoteDenoms + defaultConcentratedLiquidityParams.IsPermissionlessPoolCreationEnabled = IsPermissionlessPoolCreationEnabledCL keepers.ConcentratedLiquidityKeeper.SetParams(ctx, defaultConcentratedLiquidityParams) - if err := createCanonicalConcentratedLiquidityPoolAndMigrationLink(ctx, daiOsmoPoolId, desiredDenom0, keepers); err != nil { + if err := createCanonicalConcentratedLiquidityPoolAndMigrationLink(ctx, DaiOsmoPoolId, DesiredDenom0, keepers); err != nil { return nil, err } diff --git a/app/upgrades/v16/upgrades_test.go b/app/upgrades/v16/upgrades_test.go index fb387cb6923..3b3637f6fad 100644 --- a/app/upgrades/v16/upgrades_test.go +++ b/app/upgrades/v16/upgrades_test.go @@ -99,6 +99,9 @@ func (suite *UpgradeTestSuite) TestUpgrade() { // Check authorized denoms are set correctly. params := suite.App.ConcentratedLiquidityKeeper.GetParams(suite.Ctx) suite.Require().EqualValues(params.AuthorizedQuoteDenoms, v16.AuthorizedQuoteDenoms) + + // Permissionless pool creation is disabled. + suite.Require().False(params.IsPermissionlessPoolCreationEnabled) }, func() { }, diff --git a/proto/osmosis/concentrated-liquidity/params.proto b/proto/osmosis/concentrated-liquidity/params.proto index c3b830b621c..dbd50fabc81 100644 --- a/proto/osmosis/concentrated-liquidity/params.proto +++ b/proto/osmosis/concentrated-liquidity/params.proto @@ -36,4 +36,13 @@ message Params { // prices in terms of token1 (quote asset) that are easy to reason about. repeated string authorized_quote_denoms = 4 [ (gogoproto.moretags) = "yaml:\"authorized_quote_denoms\"" ]; + + // is_permissionless_pool_creation_enabled is a boolean that determines if + // concentrated liquidity pools can be created via message. At launch, + // we consider allowing only governance to create pools, and then later + // allowing permissionless pool creation by switching this flag to true + // with a governance proposal. + bool is_permissionless_pool_creation_enabled = 5 + [ (gogoproto.moretags) = + "yaml:\"is_permissionless_pool_creation_enabled\"" ]; } diff --git a/proto/osmosis/gamm/v1beta1/query.proto b/proto/osmosis/gamm/v1beta1/query.proto index 39985fad0b0..146c6a13c2d 100644 --- a/proto/osmosis/gamm/v1beta1/query.proto +++ b/proto/osmosis/gamm/v1beta1/query.proto @@ -104,6 +104,15 @@ service Query { option (google.api.http).get = "/osmosis/gamm/v1beta1/{pool_id}/estimate/swap_exact_amount_out"; } + + // ConcentratedPoolIdLinkFromBalancer returns the pool id of the concentrated + // pool that is linked with the given CFMM pool. + rpc ConcentratedPoolIdLinkFromCFMM(QueryConcentratedPoolIdLinkFromCFMMRequest) + returns (QueryConcentratedPoolIdLinkFromCFMMResponse) { + option (google.api.http).get = + "/osmosis/gamm/v1beta1/concentrated_pool_id_link_from_cfmm/" + "{cfmm_pool_id}"; + } } //=============================== Pool @@ -318,3 +327,12 @@ message QueryTotalLiquidityResponse { (gogoproto.nullable) = false ]; } + +//=============================== QueryConcentratedPoolIdLinkFromCFMM +message QueryConcentratedPoolIdLinkFromCFMMRequest { + uint64 cfmm_pool_id = 1 [ (gogoproto.moretags) = "yaml:\"cfmm_pool_id\"" ]; +} + +message QueryConcentratedPoolIdLinkFromCFMMResponse { + uint64 concentrated_pool_id = 1; +} diff --git a/tests/cl-genesis-positions/go.mod b/tests/cl-genesis-positions/go.mod index b507d099ebe..d390f0b40e8 100644 --- a/tests/cl-genesis-positions/go.mod +++ b/tests/cl-genesis-positions/go.mod @@ -6,7 +6,7 @@ require ( github.com/cosmos/cosmos-sdk v0.47.1 github.com/ignite/cli v0.23.0 github.com/osmosis-labs/osmosis/osmomath v0.0.3-dev.0.20230328024000-175ec88e4304 - github.com/osmosis-labs/osmosis/v15 v15.0.0-20230421191321-d8c055983934 + github.com/osmosis-labs/osmosis/v15 v15.0.0-20230424012707-075958555f2f github.com/tendermint/tendermint v0.34.26 ) diff --git a/tests/cl-genesis-positions/go.sum b/tests/cl-genesis-positions/go.sum index 924c52ee117..cf951ac2904 100644 --- a/tests/cl-genesis-positions/go.sum +++ b/tests/cl-genesis-positions/go.sum @@ -697,8 +697,8 @@ github.com/osmosis-labs/osmosis/osmomath v0.0.3-dev.0.20230328024000-175ec88e430 github.com/osmosis-labs/osmosis/osmomath v0.0.3-dev.0.20230328024000-175ec88e4304/go.mod h1:/h3CZIo25kMrM4Ojm7qBgMxKofTVwOycVWSa4rhEsaM= github.com/osmosis-labs/osmosis/osmoutils v0.0.0-20230411200859-ae3065d0ca05 h1:fqVGxZPgUWuYWxVcMxHz5vrDV/aoxGJ7Kt0J4Vu/bsY= github.com/osmosis-labs/osmosis/osmoutils v0.0.0-20230411200859-ae3065d0ca05/go.mod h1:zyBrzl2rsZWGbOU+/1hzA+xoQlCshzZuHe/5mzdb/zo= -github.com/osmosis-labs/osmosis/v15 v15.0.0-20230421191321-d8c055983934 h1:wfL4T0LZ4cFezim6L/NsOjD892pKwC09peCo7+Ub30g= -github.com/osmosis-labs/osmosis/v15 v15.0.0-20230421191321-d8c055983934/go.mod h1:qME1XII3skASTWVguqUbkTUiQw4R5Mr6r1NvZeA59H8= +github.com/osmosis-labs/osmosis/v15 v15.0.0-20230424012707-075958555f2f h1:4/JA+dnV06Lytpar7Bc6QB3q/F52pJIDNjLwqIGlX+o= +github.com/osmosis-labs/osmosis/v15 v15.0.0-20230424012707-075958555f2f/go.mod h1:DuLI8JcQ1zy2gImOve1G+HjHiqQmfbSM4qDg93aUM5Y= 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-20230331072320-5d6f6cfa2627 h1:A0SwZgp4bmJFbivYJc8mmVhMjrr3EdUZluBYFke11+w= diff --git a/tests/e2e/configurer/chain/commands.go b/tests/e2e/configurer/chain/commands.go index 5fbac3795bb..5ebbe755cd9 100644 --- a/tests/e2e/configurer/chain/commands.go +++ b/tests/e2e/configurer/chain/commands.go @@ -69,16 +69,18 @@ func (n *NodeConfig) CollectFees(from, positionIds string) { // CreateConcentratedPool creates a concentrated pool. // Returns pool id of newly created pool on success -func (n *NodeConfig) CreateConcentratedPool(from, denom1, denom2 string, tickSpacing uint64, swapFee string) uint64 { +func (n *NodeConfig) CreateConcentratedPool(from, denom1, denom2 string, tickSpacing uint64, swapFee string) (uint64, error) { n.LogActionF("creating concentrated pool") cmd := []string{"osmosisd", "tx", "concentratedliquidity", "create-concentrated-pool", denom1, denom2, fmt.Sprintf("%d", tickSpacing), swapFee, fmt.Sprintf("--from=%s", from)} _, _, err := n.containerManager.ExecTxCmd(n.t, n.chainId, n.Name, cmd) - require.NoError(n.t, err) + if err != nil { + return 0, err + } poolID := n.QueryNumPools() n.LogActionF("successfully created concentrated pool with ID %d", poolID) - return poolID + return poolID, nil } // CreateConcentratedPosition creates a concentrated position from [lowerTick; upperTick] in pool with id of poolId diff --git a/tests/e2e/configurer/chain/queries.go b/tests/e2e/configurer/chain/queries.go index f1fff842ae7..ce9c9be9915 100644 --- a/tests/e2e/configurer/chain/queries.go +++ b/tests/e2e/configurer/chain/queries.go @@ -471,6 +471,19 @@ func (n *NodeConfig) QueryCurrentEpoch(identifier string) int64 { return response.CurrentEpoch } +func (n *NodeConfig) QueryConcentratedPooIdLinkFromCFMM(cfmmPoolId uint64) uint64 { + path := fmt.Sprintf("/osmosis/gamm/v1beta1/concentrated_pool_id_link_from_cfmm/%d", cfmmPoolId) + + bz, err := n.QueryGRPCGateway(path) + require.NoError(n.t, err) + + //nolint:staticcheck + var response gammtypes.QueryConcentratedPoolIdLinkFromCFMMResponse + err = util.Cdc.UnmarshalJSON(bz, &response) + require.NoError(n.t, err) + return response.ConcentratedPoolId +} + func (n *NodeConfig) QueryArithmeticTwapToNow(poolId uint64, baseAsset, quoteAsset string, startTime time.Time) (sdk.Dec, error) { path := "osmosis/twap/v1beta1/ArithmeticTwapToNow" diff --git a/tests/e2e/e2e_test.go b/tests/e2e/e2e_test.go index 0b08902b114..ae21dd04607 100644 --- a/tests/e2e/e2e_test.go +++ b/tests/e2e/e2e_test.go @@ -20,12 +20,14 @@ import ( ibchookskeeper "github.com/osmosis-labs/osmosis/x/ibc-hooks/keeper" ibcratelimittypes "github.com/osmosis-labs/osmosis/v15/x/ibc-rate-limit/types" + poolmanagertypes "github.com/osmosis-labs/osmosis/v15/x/poolmanager/types" sdk "github.com/cosmos/cosmos-sdk/types" coretypes "github.com/tendermint/tendermint/rpc/core/types" "github.com/osmosis-labs/osmosis/osmoutils/osmoassert" appparams "github.com/osmosis-labs/osmosis/v15/app/params" + v16 "github.com/osmosis-labs/osmosis/v15/app/upgrades/v16" "github.com/osmosis-labs/osmosis/v15/tests/e2e/configurer/config" "github.com/osmosis-labs/osmosis/v15/tests/e2e/initialization" cl "github.com/osmosis-labs/osmosis/v15/x/concentrated-liquidity" @@ -186,7 +188,7 @@ func (s *IntegrationTestSuite) CheckBalance(node *chain.NodeConfig, addr, denom func (s *IntegrationTestSuite) TestConcentratedLiquidity() { chainA := s.configurer.GetChainConfig(0) - node, err := chainA.GetDefaultNode() + chainANode, err := chainA.GetDefaultNode() s.Require().NoError(err) var ( @@ -197,9 +199,26 @@ func (s *IntegrationTestSuite) TestConcentratedLiquidity() { swapFeeDec sdk.Dec = sdk.MustNewDecFromStr("0.01") ) - poolID := node.CreateConcentratedPool(initialization.ValidatorWalletName, denom0, denom1, tickSpacing, swapFee) + // Get the permisionless pool creation parameter. + isPermisionlessCreationEnabledStr := chainANode.QueryParams(cltypes.ModuleName, string(cltypes.KeyIsPermisionlessPoolCreationEnabled)) + if !strings.EqualFold(isPermisionlessCreationEnabledStr, "false") { + s.T().Fatal("concentrated liquidity pool creation is enabled when should not have been") + } + + // Change the parameter to enable permisionless pool creation. + chainA.SubmitParamChangeProposal("concentratedliquidity", string(cltypes.KeyIsPermisionlessPoolCreationEnabled), []byte("true")) + + // Confirm that the parameter has been changed. + isPermisionlessCreationEnabledStr = chainANode.QueryParams(cltypes.ModuleName, string(cltypes.KeyIsPermisionlessPoolCreationEnabled)) + if !strings.EqualFold(isPermisionlessCreationEnabledStr, "true") { + s.T().Fatal("concentrated liquidity pool creation is not enabled") + } + + // Create concentrated liquidity pool when permisionless pool creation is enabled. + poolID, err := chainANode.CreateConcentratedPool(initialization.ValidatorWalletName, denom0, denom1, tickSpacing, swapFee) + s.Require().NoError(err) - concentratedPool := s.updatedPool(node, poolID) + concentratedPool := s.updatedPool(chainANode, poolID) // Sanity check that pool initialized with valid parameters (the ones that we haven't explicitly specified) s.Require().Equal(concentratedPool.GetCurrentTick(), sdk.ZeroInt()) @@ -217,27 +236,27 @@ func (s *IntegrationTestSuite) TestConcentratedLiquidity() { fundTokens := []string{"100000000uosmo", "100000000uion", "100000000stake"} // Get 3 addresses to create positions - address1 := node.CreateWalletAndFund("addr1", fundTokens) - address2 := node.CreateWalletAndFund("addr2", fundTokens) - address3 := node.CreateWalletAndFund("addr3", fundTokens) + address1 := chainANode.CreateWalletAndFund("addr1", fundTokens) + address2 := chainANode.CreateWalletAndFund("addr2", fundTokens) + address3 := chainANode.CreateWalletAndFund("addr3", fundTokens) // Create 2 positions for address1: overlap together, overlap with 2 address3 positions - node.CreateConcentratedPosition(address1, "[-120000]", "40000", fmt.Sprintf("10000000%s", denom0), fmt.Sprintf("10000000%s", denom1), 0, 0, poolID) - node.CreateConcentratedPosition(address1, "[-40000]", "120000", fmt.Sprintf("10000000%s", denom0), fmt.Sprintf("10000000%s", denom1), 0, 0, poolID) + chainANode.CreateConcentratedPosition(address1, "[-120000]", "40000", fmt.Sprintf("10000000%s", denom0), fmt.Sprintf("10000000%s", denom1), 0, 0, poolID) + chainANode.CreateConcentratedPosition(address1, "[-40000]", "120000", fmt.Sprintf("10000000%s", denom0), fmt.Sprintf("10000000%s", denom1), 0, 0, poolID) // Create 1 position for address2: does not overlap with anything, ends at maximum - node.CreateConcentratedPosition(address2, "220000", fmt.Sprintf("%d", cltypes.MaxTick), fmt.Sprintf("10000000%s", denom0), fmt.Sprintf("10000000%s", denom1), 0, 0, poolID) + chainANode.CreateConcentratedPosition(address2, "220000", fmt.Sprintf("%d", cltypes.MaxTick), fmt.Sprintf("10000000%s", denom0), fmt.Sprintf("10000000%s", denom1), 0, 0, poolID) // Create 2 positions for address3: overlap together, overlap with 2 address1 positions, one position starts from minimum - node.CreateConcentratedPosition(address3, "[-160000]", "[-20000]", fmt.Sprintf("10000000%s", denom0), fmt.Sprintf("10000000%s", denom1), 0, 0, poolID) - node.CreateConcentratedPosition(address3, fmt.Sprintf("[%d]", cltypes.MinTick), "140000", fmt.Sprintf("10000000%s", denom0), fmt.Sprintf("10000000%s", denom1), 0, 0, poolID) + chainANode.CreateConcentratedPosition(address3, "[-160000]", "[-20000]", fmt.Sprintf("10000000%s", denom0), fmt.Sprintf("10000000%s", denom1), 0, 0, poolID) + chainANode.CreateConcentratedPosition(address3, fmt.Sprintf("[%d]", cltypes.MinTick), "140000", fmt.Sprintf("10000000%s", denom0), fmt.Sprintf("10000000%s", denom1), 0, 0, poolID) // Get newly created positions - positionsAddress1 := node.QueryConcentratedPositions(address1) - positionsAddress2 := node.QueryConcentratedPositions(address2) - positionsAddress3 := node.QueryConcentratedPositions(address3) + positionsAddress1 := chainANode.QueryConcentratedPositions(address1) + positionsAddress2 := chainANode.QueryConcentratedPositions(address2) + positionsAddress3 := chainANode.QueryConcentratedPositions(address3) - concentratedPool = s.updatedPool(node, poolID) + concentratedPool = s.updatedPool(chainANode, poolID) // Assert number of positions per address s.Require().Equal(len(positionsAddress1), 2) @@ -283,7 +302,7 @@ func (s *IntegrationTestSuite) TestConcentratedLiquidity() { uosmoIn_Swap1 = fmt.Sprintf("%suosmo", uosmoInDec_Swap1.String()) ) // Perform swap (not crossing initialized ticks) - node.SwapExactAmountIn(uosmoIn_Swap1, outMinAmt, fmt.Sprintf("%d", poolID), denom0, initialization.ValidatorWalletName) + chainANode.SwapExactAmountIn(uosmoIn_Swap1, outMinAmt, fmt.Sprintf("%d", poolID), denom0, initialization.ValidatorWalletName) // Calculate and track global fee growth for swap 1 feeGrowthGlobal.AddMut(calculateFeeGrowthGlobal(uosmoInDec_Swap1, swapFeeDec, concentratedPool.GetLiquidity())) @@ -291,7 +310,7 @@ func (s *IntegrationTestSuite) TestConcentratedLiquidity() { liquidityBeforeSwap := concentratedPool.GetLiquidity() sqrtPriceBeforeSwap := concentratedPool.GetCurrentSqrtPrice() - concentratedPool = s.updatedPool(node, poolID) + concentratedPool = s.updatedPool(chainANode, poolID) liquidityAfterSwap := concentratedPool.GetLiquidity() sqrtPriceAfterSwap := concentratedPool.GetCurrentSqrtPrice() @@ -309,9 +328,9 @@ func (s *IntegrationTestSuite) TestConcentratedLiquidity() { // Collect Fees: Swap 1 // Track balances for address1 position1 - addr1BalancesBefore := s.addrBalance(node, address1) - node.CollectFees(address1, fmt.Sprint(positionsAddress1[0].Position.PositionId)) - addr1BalancesAfter := s.addrBalance(node, address1) + addr1BalancesBefore := s.addrBalance(chainANode, address1) + chainANode.CollectFees(address1, fmt.Sprint(positionsAddress1[0].Position.PositionId)) + addr1BalancesAfter := s.addrBalance(chainANode, address1) // Assert that the balance changed only for tokenIn (uosmo) s.assertBalancesInvariants(addr1BalancesBefore, addr1BalancesAfter, false, true) @@ -381,13 +400,13 @@ func (s *IntegrationTestSuite) TestConcentratedLiquidity() { feeGrowthGlobal_Swap1 = feeGrowthGlobal.Clone() ) // Perform a swap - node.SwapExactAmountIn(uosmoIn_Swap2, outMinAmt, fmt.Sprintf("%d", poolID), denom0, initialization.ValidatorWalletName) + chainANode.SwapExactAmountIn(uosmoIn_Swap2, outMinAmt, fmt.Sprintf("%d", poolID), denom0, initialization.ValidatorWalletName) // Calculate the amount of liquidity of the position that was kicked out during swap (address1 position1) liquidityOfKickedOutPosition := positionsAddress1[0].Position.Liquidity // Update pool and track pool's liquidity - concentratedPool = s.updatedPool(node, poolID) + concentratedPool = s.updatedPool(chainANode, poolID) liquidityAfterSwap = concentratedPool.GetLiquidity() @@ -420,9 +439,9 @@ func (s *IntegrationTestSuite) TestConcentratedLiquidity() { // Assert that address1 position1 earned fees only from first swap step // Track balances for address1 position1 - addr1BalancesBefore = s.addrBalance(node, address1) - node.CollectFees(address1, fmt.Sprint(positionsAddress1[0].Position.PositionId)) - addr1BalancesAfter = s.addrBalance(node, address1) + addr1BalancesBefore = s.addrBalance(chainANode, address1) + chainANode.CollectFees(address1, fmt.Sprint(positionsAddress1[0].Position.PositionId)) + addr1BalancesAfter = s.addrBalance(chainANode, address1) // Assert that the balance changed only for tokenIn (uosmo) s.assertBalancesInvariants(addr1BalancesBefore, addr1BalancesAfter, false, true) @@ -445,9 +464,9 @@ func (s *IntegrationTestSuite) TestConcentratedLiquidity() { // Assert that address3 position2 earned rewards from first and second swaps // Track balance off address3 position2: check that position that has not been kicked out earned full rewards - addr3BalancesBefore := s.addrBalance(node, address3) - node.CollectFees(address3, fmt.Sprint(positionsAddress3[1].Position.PositionId)) - addr3BalancesAfter := s.addrBalance(node, address3) + addr3BalancesBefore := s.addrBalance(chainANode, address3) + chainANode.CollectFees(address3, fmt.Sprint(positionsAddress3[1].Position.PositionId)) + addr3BalancesAfter := s.addrBalance(chainANode, address3) // Calculate uncollected fees for address3 position2 earned from Swap 1 feesUncollectedAddress3Position2_Swap1 := calculateUncollectedFees( @@ -525,21 +544,21 @@ func (s *IntegrationTestSuite) TestConcentratedLiquidity() { feeGrowthInsideAddress1Position1Last = feeGrowthGlobal_Swap1.Add(feeCharge_Swap2_Step1) ) // Collect fees for address1 position1 to avoid overhead computations (swap2 already asserted fees are aggregated correctly from multiple swaps) - node.CollectFees(address1, fmt.Sprint(positionsAddress1[0].Position.PositionId)) + chainANode.CollectFees(address1, fmt.Sprint(positionsAddress1[0].Position.PositionId)) // Perform a swap - node.SwapExactAmountIn(uionIn_Swap3, outMinAmt, fmt.Sprintf("%d", poolID), denom1, initialization.ValidatorWalletName) + chainANode.SwapExactAmountIn(uionIn_Swap3, outMinAmt, fmt.Sprintf("%d", poolID), denom1, initialization.ValidatorWalletName) // Assert liquidity of kicked in position was successfully added to the pool - concentratedPool = s.updatedPool(node, poolID) + concentratedPool = s.updatedPool(chainANode, poolID) liquidityAfterSwap = concentratedPool.GetLiquidity() s.Require().Equal(liquidityBeforeSwap.Add(positionsAddress1[0].Position.Liquidity), liquidityAfterSwap) // Track balance of address1 - addr1BalancesBefore = s.addrBalance(node, address1) - node.CollectFees(address1, fmt.Sprint(positionsAddress1[0].Position.PositionId)) - addr1BalancesAfter = s.addrBalance(node, address1) + addr1BalancesBefore = s.addrBalance(chainANode, address1) + chainANode.CollectFees(address1, fmt.Sprint(positionsAddress1[0].Position.PositionId)) + addr1BalancesAfter = s.addrBalance(chainANode, address1) // Assert that the balance changed only for tokenIn (uion) s.assertBalancesInvariants(addr1BalancesBefore, addr1BalancesAfter, true, false) @@ -583,9 +602,9 @@ func (s *IntegrationTestSuite) TestConcentratedLiquidity() { // Assert position that was active thoughout the whole swap: // Track balance of address3 - addr3BalancesBefore = s.addrBalance(node, address3) - node.CollectFees(address3, fmt.Sprint(positionsAddress3[1].Position.PositionId)) - addr3BalancesAfter = s.addrBalance(node, address3) + addr3BalancesBefore = s.addrBalance(chainANode, address3) + chainANode.CollectFees(address3, fmt.Sprint(positionsAddress3[1].Position.PositionId)) + addr3BalancesAfter = s.addrBalance(chainANode, address3) // Assert that the balance changed only for tokenIn (uion) s.assertBalancesInvariants(addr3BalancesBefore, addr3BalancesAfter, true, false) @@ -624,17 +643,17 @@ func (s *IntegrationTestSuite) TestConcentratedLiquidity() { // Assert that positions, which were not included in swaps, were not affected // Address3 Position1: [-160000; -20000] - addr3BalancesBefore = s.addrBalance(node, address3) - node.CollectFees(address3, fmt.Sprint(positionsAddress3[0].Position.PositionId)) - addr3BalancesAfter = s.addrBalance(node, address3) + addr3BalancesBefore = s.addrBalance(chainANode, address3) + chainANode.CollectFees(address3, fmt.Sprint(positionsAddress3[0].Position.PositionId)) + addr3BalancesAfter = s.addrBalance(chainANode, address3) // Assert that balances did not change for any token s.assertBalancesInvariants(addr3BalancesBefore, addr3BalancesAfter, true, true) // Address2's only position: [220000; 342000] - addr2BalancesBefore := s.addrBalance(node, address2) - node.CollectFees(address2, fmt.Sprint(positionsAddress2[0].Position.PositionId)) - addr2BalancesAfter := s.addrBalance(node, address2) + addr2BalancesBefore := s.addrBalance(chainANode, address2) + chainANode.CollectFees(address2, fmt.Sprint(positionsAddress2[0].Position.PositionId)) + addr2BalancesAfter := s.addrBalance(chainANode, address2) // Assert the balances did not change for every token s.assertBalancesInvariants(addr2BalancesBefore, addr2BalancesAfter, true, true) @@ -651,36 +670,36 @@ func (s *IntegrationTestSuite) TestConcentratedLiquidity() { // Assert removing some liquidity // address1: check removing some amount of liquidity address1position1liquidityBefore := positionsAddress1[0].Position.Liquidity - node.WithdrawPosition(address1, defaultLiquidityRemoval, positionsAddress1[0].Position.PositionId) + chainANode.WithdrawPosition(address1, defaultLiquidityRemoval, positionsAddress1[0].Position.PositionId) // assert - positionsAddress1 = node.QueryConcentratedPositions(address1) + positionsAddress1 = chainANode.QueryConcentratedPositions(address1) s.Require().Equal(address1position1liquidityBefore, positionsAddress1[0].Position.Liquidity.Add(sdk.MustNewDecFromStr(defaultLiquidityRemoval))) // address2: check removing some amount of liquidity address2position1liquidityBefore := positionsAddress2[0].Position.Liquidity - node.WithdrawPosition(address2, defaultLiquidityRemoval, positionsAddress2[0].Position.PositionId) + chainANode.WithdrawPosition(address2, defaultLiquidityRemoval, positionsAddress2[0].Position.PositionId) // assert - positionsAddress2 = node.QueryConcentratedPositions(address2) + positionsAddress2 = chainANode.QueryConcentratedPositions(address2) s.Require().Equal(address2position1liquidityBefore, positionsAddress2[0].Position.Liquidity.Add(sdk.MustNewDecFromStr(defaultLiquidityRemoval))) // address3: check removing some amount of liquidity address3position1liquidityBefore := positionsAddress3[0].Position.Liquidity - node.WithdrawPosition(address3, defaultLiquidityRemoval, positionsAddress3[0].Position.PositionId) + chainANode.WithdrawPosition(address3, defaultLiquidityRemoval, positionsAddress3[0].Position.PositionId) // assert - positionsAddress3 = node.QueryConcentratedPositions(address3) + positionsAddress3 = chainANode.QueryConcentratedPositions(address3) s.Require().Equal(address3position1liquidityBefore, positionsAddress3[0].Position.Liquidity.Add(sdk.MustNewDecFromStr(defaultLiquidityRemoval))) // Assert removing all liquidity // address2: no more positions left allLiquidityAddress2Position1 := positionsAddress2[0].Position.Liquidity - node.WithdrawPosition(address2, allLiquidityAddress2Position1.String(), positionsAddress2[0].Position.PositionId) - positionsAddress2 = node.QueryConcentratedPositions(address2) + chainANode.WithdrawPosition(address2, allLiquidityAddress2Position1.String(), positionsAddress2[0].Position.PositionId) + positionsAddress2 = chainANode.QueryConcentratedPositions(address2) s.Require().Empty(positionsAddress2) // address1: one position left allLiquidityAddress1Position1 := positionsAddress1[0].Position.Liquidity - node.WithdrawPosition(address1, allLiquidityAddress1Position1.String(), positionsAddress1[0].Position.PositionId) - positionsAddress1 = node.QueryConcentratedPositions(address1) + chainANode.WithdrawPosition(address1, allLiquidityAddress1Position1.String(), positionsAddress1[0].Position.PositionId) + positionsAddress1 = chainANode.QueryConcentratedPositions(address1) s.Require().Equal(len(positionsAddress1), 1) } @@ -1457,3 +1476,37 @@ func (s *IntegrationTestSuite) TestGeometricTWAP() { // quote assset supply / base asset supply = 1_000_000 / 2_000_000 = 0.5 osmoassert.DecApproxEq(s.T(), sdk.NewDecWithPrec(5, 1), afterSwapTwapBOverA, sdk.NewDecWithPrec(1, 2)) } + +// Tests that v16 upgrade correctly creates the canonical OSMO-DAI pool in the upgrade. +// Prefixed with "A" to run before TestConcentratedLiquidity that resets the pool creation +// parameter. +func (s *IntegrationTestSuite) TestAConcentratedLiquidity_CanonicalPool_And_Parameters() { + if s.skipUpgrade { + s.T().Skip("Skipping v16 canonical pool creation test because upgrade is not enabled") + } + + var ( + // Taken from: https://app.osmosis.zone/pool/674 + expectedFee = sdk.MustNewDecFromStr("0.002") + ) + + chainA := s.configurer.GetChainConfig(0) + chainANode, err := chainA.GetDefaultNode() + s.Require().NoError(err) + + concentratedPoolId := chainANode.QueryConcentratedPooIdLinkFromCFMM(config.DaiOsmoPoolIdv16) + + concentratedPool := s.updatedPool(chainANode, concentratedPoolId) + + s.Require().Equal(poolmanagertypes.Concentrated, concentratedPool.GetType()) + s.Require().Equal(v16.DesiredDenom0, concentratedPool.GetToken0()) + s.Require().Equal(v16.DAIIBCDenom, concentratedPool.GetToken1()) + s.Require().Equal(uint64(v16.TickSpacing), concentratedPool.GetTickSpacing()) + s.Require().Equal(expectedFee.String(), concentratedPool.GetSwapFee(sdk.Context{}).String()) + + // Get the permisionless pool creation parameter. + isPermisionlessCreationEnabledStr := chainANode.QueryParams(cltypes.ModuleName, string(cltypes.KeyIsPermisionlessPoolCreationEnabled)) + if !strings.EqualFold(isPermisionlessCreationEnabledStr, "false") { + s.T().Fatal("concentrated liquidity pool creation is enabled when should not have been after v16 upgrade") + } +} diff --git a/tests/e2e/scripts/daiosmov16.json b/tests/e2e/scripts/daiosmov16.json index 5bb669bca42..0cd1f756e89 100644 --- a/tests/e2e/scripts/daiosmov16.json +++ b/tests/e2e/scripts/daiosmov16.json @@ -1,7 +1,7 @@ { "weights": "5ibc/0CD3A0285E1341859B5E86B6AB7682F023D03E97607CCC1DC95706411D866DF7,5uosmo", "initial-deposit": "5000000000ibc/0CD3A0285E1341859B5E86B6AB7682F023D03E97607CCC1DC95706411D866DF7,5000000000uosmo", - "swap-fee": "0.01", + "swap-fee": "0.002", "exit-fee": "0.00", "future-governor": "" } diff --git a/tests/localosmosis/scripts/setup.sh b/tests/localosmosis/scripts/setup.sh index e6945bd010f..12065e6d5c1 100755 --- a/tests/localosmosis/scripts/setup.sh +++ b/tests/localosmosis/scripts/setup.sh @@ -80,6 +80,9 @@ edit_genesis () { # Update wasm permission (Nobody or Everybody) dasel put string -f $GENESIS '.app_state.wasm.params.code_upload_access.permission' "Everybody" + + # Update concentrated-liquidity (enable pool creation) + dasel put bool -f $GENESIS '.app_state.concentratedliquidity.params.is_permissionless_pool_creation_enabled' true } add_genesis_accounts () { diff --git a/tests/mocks/pool_module.go b/tests/mocks/pool_module.go index 871f12f2df6..8badde0452e 100644 --- a/tests/mocks/pool_module.go +++ b/tests/mocks/pool_module.go @@ -51,6 +51,20 @@ func (mr *MockAccountIMockRecorder) GetAccount(ctx, addr interface{}) *gomock.Ca return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAccount", reflect.TypeOf((*MockAccountI)(nil).GetAccount), ctx, addr) } +// GetModuleAccount mocks base method. +func (m *MockAccountI) GetModuleAccount(ctx types.Context, moduleName string) types0.ModuleAccountI { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetModuleAccount", ctx, moduleName) + ret0, _ := ret[0].(types0.ModuleAccountI) + return ret0 +} + +// GetModuleAccount indicates an expected call of GetModuleAccount. +func (mr *MockAccountIMockRecorder) GetModuleAccount(ctx, moduleName interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetModuleAccount", reflect.TypeOf((*MockAccountI)(nil).GetModuleAccount), ctx, moduleName) +} + // NewAccount mocks base method. func (m *MockAccountI) NewAccount(arg0 types.Context, arg1 types0.AccountI) types0.AccountI { m.ctrl.T.Helper() @@ -335,6 +349,20 @@ func (mr *MockPoolModuleIMockRecorder) SwapExactAmountOut(ctx, sender, pool, tok return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SwapExactAmountOut", reflect.TypeOf((*MockPoolModuleI)(nil).SwapExactAmountOut), ctx, sender, pool, tokenInDenom, tokenInMaxAmount, tokenOut, swapFee) } +// ValidatePermissionlessPoolCreationEnabled mocks base method. +func (m *MockPoolModuleI) ValidatePermissionlessPoolCreationEnabled(ctx types.Context) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ValidatePermissionlessPoolCreationEnabled", ctx) + ret0, _ := ret[0].(error) + return ret0 +} + +// ValidatePermissionlessPoolCreationEnabled indicates an expected call of ValidatePermissionlessPoolCreationEnabled. +func (mr *MockPoolModuleIMockRecorder) ValidatePermissionlessPoolCreationEnabled(ctx interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ValidatePermissionlessPoolCreationEnabled", reflect.TypeOf((*MockPoolModuleI)(nil).ValidatePermissionlessPoolCreationEnabled), ctx) +} + // MockPoolIncentivesKeeperI is a mock of PoolIncentivesKeeperI interface. type MockPoolIncentivesKeeperI struct { ctrl *gomock.Controller diff --git a/x/concentrated-liquidity/README.md b/x/concentrated-liquidity/README.md index 426bd3e0ea0..4bc52756f2d 100644 --- a/x/concentrated-liquidity/README.md +++ b/x/concentrated-liquidity/README.md @@ -1168,6 +1168,14 @@ to only a few denoms. Our list at launch is expected to consist of OSMO, DAI and USDC. These are set in the v16 upgrade handler. +- `IsPermisionlessPoolCreationEnabled` bool + +The flag indicating whether permissionless pool creation is enabled or not. For launch, we have +decided to disable permissionless pool creation. It will still be enabled via governance. +This is because we want to limit the number of pools for risk management and want to avoid +fragmenting liquidity for major denom pairs with configurations of tick spacing that are +not ideal. + ## Listeners ### `AfterConcentratedPoolCreated` diff --git a/x/concentrated-liquidity/keeper.go b/x/concentrated-liquidity/keeper.go index 8ce8cdf3861..4d258a92014 100644 --- a/x/concentrated-liquidity/keeper.go +++ b/x/concentrated-liquidity/keeper.go @@ -99,3 +99,12 @@ func (k *Keeper) SetListeners(listeners types.ConcentratedLiquidityListeners) *K return k } + +// ValidatePermissionlessPoolCreationEnabled returns nil if permissionless pool creation in the module is enabled. +// Otherwise, returns an error. +func (k Keeper) ValidatePermissionlessPoolCreationEnabled(ctx sdk.Context) error { + if !k.GetParams(ctx).IsPermissionlessPoolCreationEnabled { + return types.ErrPermissionlessPoolCreationDisabled + } + return nil +} diff --git a/x/concentrated-liquidity/types/errors.go b/x/concentrated-liquidity/types/errors.go index 06a1d58e46c..031dfb65c14 100644 --- a/x/concentrated-liquidity/types/errors.go +++ b/x/concentrated-liquidity/types/errors.go @@ -9,10 +9,11 @@ import ( ) var ( - ErrKeyNotFound = errors.New("key not found") - ErrValueParse = errors.New("value parse error") - ErrPositionNotFound = errors.New("position not found") - ErrZeroPositionId = errors.New("invalid position id, cannot be 0") + ErrKeyNotFound = errors.New("key not found") + ErrValueParse = errors.New("value parse error") + ErrPositionNotFound = errors.New("position not found") + ErrZeroPositionId = errors.New("invalid position id, cannot be 0") + ErrPermissionlessPoolCreationDisabled = errors.New("permissionless pool creation is disabled for the concentrated liquidity module") ) // x/concentrated-liquidity module sentinel errors. diff --git a/x/concentrated-liquidity/types/params.go b/x/concentrated-liquidity/types/params.go index 335dc201bbe..da46e0bd0c7 100644 --- a/x/concentrated-liquidity/types/params.go +++ b/x/concentrated-liquidity/types/params.go @@ -9,10 +9,11 @@ import ( // Parameter store keys. var ( - KeyAuthorizedTickSpacing = []byte("AuthorizedTickSpacing") - KeyAuthorizedSwapFees = []byte("AuthorizedSwapFees") - KeyDiscountRate = []byte("DiscountRate") - KeyAuthorizedQuoteDenoms = []byte("AuthorizedQuoteDenoms") + KeyAuthorizedTickSpacing = []byte("AuthorizedTickSpacing") + KeyAuthorizedSwapFees = []byte("AuthorizedSwapFees") + KeyDiscountRate = []byte("DiscountRate") + KeyAuthorizedQuoteDenoms = []byte("AuthorizedQuoteDenoms") + KeyIsPermisionlessPoolCreationEnabled = []byte("IsPermisionlessPoolCreationEnabled") _ paramtypes.ParamSet = &Params{} ) @@ -22,12 +23,13 @@ func ParamKeyTable() paramtypes.KeyTable { return paramtypes.NewKeyTable().RegisterParamSet(&Params{}) } -func NewParams(authorizedTickSpacing []uint64, authorizedSwapFees []sdk.Dec, discountRate sdk.Dec, authorizedQuoteDenoms []string) Params { +func NewParams(authorizedTickSpacing []uint64, authorizedSwapFees []sdk.Dec, discountRate sdk.Dec, authorizedQuoteDenoms []string, isPermissionlessPoolCreationEnabled bool) Params { return Params{ - AuthorizedTickSpacing: authorizedTickSpacing, - AuthorizedSwapFees: authorizedSwapFees, - AuthorizedQuoteDenoms: authorizedQuoteDenoms, - BalancerSharesRewardDiscount: discountRate, + AuthorizedTickSpacing: authorizedTickSpacing, + AuthorizedSwapFees: authorizedSwapFees, + AuthorizedQuoteDenoms: authorizedQuoteDenoms, + BalancerSharesRewardDiscount: discountRate, + IsPermissionlessPoolCreationEnabled: isPermissionlessPoolCreationEnabled, } } @@ -49,7 +51,8 @@ func DefaultParams() Params { "ibc/0CD3A0285E1341859B5E86B6AB7682F023D03E97607CCC1DC95706411D866DF7", // DAI "ibc/D189335C6E4A68B513C10AB227BF1C1D38C746766278BA3EEB4FB14124F1D858", // USDC }, - BalancerSharesRewardDiscount: DefaultBalancerSharesDiscount, + IsPermissionlessPoolCreationEnabled: false, + BalancerSharesRewardDiscount: DefaultBalancerSharesDiscount, } } @@ -64,6 +67,9 @@ func (p Params) Validate() error { if err := validateAuthorizedQuoteDenoms(p.AuthorizedQuoteDenoms); err != nil { return err } + if err := validateIsPermissionLessPoolCreationEnabled(p.IsPermissionlessPoolCreationEnabled); err != nil { + return err + } if err := validateBalancerSharesDiscount(p.BalancerSharesRewardDiscount); err != nil { return err } @@ -76,6 +82,7 @@ func (p *Params) ParamSetPairs() paramtypes.ParamSetPairs { paramtypes.NewParamSetPair(KeyAuthorizedTickSpacing, &p.AuthorizedTickSpacing, validateTicks), paramtypes.NewParamSetPair(KeyAuthorizedSwapFees, &p.AuthorizedSwapFees, validateSwapFees), paramtypes.NewParamSetPair(KeyAuthorizedQuoteDenoms, &p.AuthorizedQuoteDenoms, validateAuthorizedQuoteDenoms), + paramtypes.NewParamSetPair(KeyIsPermisionlessPoolCreationEnabled, &p.IsPermissionlessPoolCreationEnabled, validateIsPermissionLessPoolCreationEnabled), paramtypes.NewParamSetPair(KeyDiscountRate, &p.BalancerSharesRewardDiscount, validateBalancerSharesDiscount), } } @@ -133,6 +140,16 @@ func validateAuthorizedQuoteDenoms(i interface{}) error { return nil } +// validateIsPermissionLessPoolCreationEnabled validates that the given parameter is a bool. +func validateIsPermissionLessPoolCreationEnabled(i interface{}) error { + _, ok := i.(bool) + if !ok { + return fmt.Errorf("invalid parameter type for is permissionless pool creation enabled flag: %T", i) + } + + return nil +} + // validateBalancerSharesDiscount validates that the given parameter is a sdk.Dec. Returns error if the parameter is not of the correct type. func validateBalancerSharesDiscount(i interface{}) error { // Convert the given parameter to sdk.Dec. diff --git a/x/concentrated-liquidity/types/params.pb.go b/x/concentrated-liquidity/types/params.pb.go index fa4b22ac291..0b9cd2c33f8 100644 --- a/x/concentrated-liquidity/types/params.pb.go +++ b/x/concentrated-liquidity/types/params.pb.go @@ -45,6 +45,12 @@ type Params struct { // desirable property in terms of UX as to allow users to set limit orders at // prices in terms of token1 (quote asset) that are easy to reason about. AuthorizedQuoteDenoms []string `protobuf:"bytes,4,rep,name=authorized_quote_denoms,json=authorizedQuoteDenoms,proto3" json:"authorized_quote_denoms,omitempty" yaml:"authorized_quote_denoms"` + // is_permissionless_pool_creation_enabled is a boolean that determines if + // concentrated liquidity pools can be created via message. At launch, + // we consider allowing only governance to create pools, and then later + // allowing permissionless pool creation by switching this flag to true + // with a governance proposal. + IsPermissionlessPoolCreationEnabled bool `protobuf:"varint,5,opt,name=is_permissionless_pool_creation_enabled,json=isPermissionlessPoolCreationEnabled,proto3" json:"is_permissionless_pool_creation_enabled,omitempty" yaml:"is_permissionless_pool_creation_enabled"` } func (m *Params) Reset() { *m = Params{} } @@ -94,6 +100,13 @@ func (m *Params) GetAuthorizedQuoteDenoms() []string { return nil } +func (m *Params) GetIsPermissionlessPoolCreationEnabled() bool { + if m != nil { + return m.IsPermissionlessPoolCreationEnabled + } + return false +} + func init() { proto.RegisterType((*Params)(nil), "osmosis.concentratedliquidity.Params") } @@ -103,32 +116,36 @@ func init() { } var fileDescriptor_cd3784445b6f6ba7 = []byte{ - // 399 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x92, 0xc1, 0xae, 0x93, 0x40, - 0x14, 0x86, 0x41, 0x9a, 0x26, 0x65, 0x49, 0x6a, 0xc4, 0xaa, 0xd0, 0xb0, 0x68, 0x9a, 0x98, 0x42, - 0x8c, 0x71, 0xe3, 0x92, 0x34, 0xee, 0x4c, 0x94, 0xba, 0x30, 0x8d, 0xc9, 0x64, 0x18, 0x46, 0x3a, - 0x29, 0x30, 0x74, 0x66, 0xb0, 0xd6, 0x8d, 0xaf, 0xe0, 0x1b, 0xf8, 0x3a, 0x5d, 0x76, 0x69, 0x5c, - 0x10, 0x53, 0xde, 0xa0, 0x4f, 0x60, 0x3a, 0xd0, 0x16, 0xbd, 0xb7, 0xb9, 0xb9, 0x2b, 0x38, 0xe7, - 0xff, 0xce, 0xe1, 0xe7, 0xcf, 0xd1, 0x9f, 0x53, 0x9e, 0x52, 0x4e, 0xb8, 0x87, 0x68, 0x86, 0x70, - 0x26, 0x18, 0x14, 0x38, 0x9a, 0x24, 0x64, 0x55, 0x90, 0x88, 0x88, 0x8d, 0x97, 0x43, 0x06, 0x53, - 0xee, 0xe6, 0x8c, 0x0a, 0x6a, 0x3c, 0x6b, 0x60, 0xb7, 0x0d, 0x9f, 0xd9, 0x41, 0x3f, 0xa6, 0x31, - 0x95, 0xa4, 0x77, 0x7c, 0xab, 0x87, 0x06, 0x8f, 0x91, 0x9c, 0x02, 0xb5, 0x50, 0x17, 0xb5, 0xe4, - 0x54, 0x9a, 0xde, 0x7d, 0x27, 0x3f, 0x60, 0xcc, 0xf5, 0x47, 0xb0, 0x10, 0x0b, 0xca, 0xc8, 0x37, - 0x1c, 0x01, 0x41, 0xd0, 0x12, 0xf0, 0x1c, 0x22, 0x92, 0xc5, 0xa6, 0x3a, 0xd4, 0xc6, 0x1d, 0xdf, - 0x39, 0x94, 0xb6, 0xb5, 0x81, 0x69, 0xf2, 0xda, 0xb9, 0x02, 0x3a, 0xc1, 0xc3, 0x8b, 0xf2, 0x81, - 0xa0, 0xe5, 0xac, 0xee, 0x1b, 0xdf, 0xf5, 0x7e, 0x6b, 0x84, 0xaf, 0x61, 0x0e, 0x3e, 0x63, 0xcc, - 0xcd, 0x07, 0x43, 0x6d, 0xdc, 0xf3, 0xdf, 0x6e, 0x4b, 0x5b, 0xf9, 0x5d, 0xda, 0xa3, 0x98, 0x88, - 0x45, 0x11, 0xba, 0x88, 0xa6, 0x8d, 0xcb, 0xe6, 0x31, 0xe1, 0xd1, 0xd2, 0x13, 0x9b, 0x1c, 0x73, - 0x77, 0x8a, 0xd1, 0xa1, 0xb4, 0x9f, 0xdc, 0xb0, 0x71, 0xde, 0xe9, 0x04, 0xc6, 0xa5, 0x3d, 0x5b, - 0xc3, 0xfc, 0x0d, 0xc6, 0xdc, 0xf8, 0xa9, 0xea, 0x76, 0x08, 0x13, 0x98, 0x21, 0xcc, 0x00, 0x5f, - 0x40, 0x86, 0x39, 0x60, 0x78, 0x0d, 0x59, 0x04, 0x22, 0xc2, 0x11, 0x2d, 0x32, 0x61, 0x6a, 0x43, - 0x75, 0xdc, 0xf3, 0x3f, 0xde, 0xdb, 0xcc, 0xa8, 0x36, 0x73, 0xc7, 0x7a, 0x27, 0x78, 0x7a, 0x22, - 0x66, 0x12, 0x08, 0xa4, 0x3e, 0x6d, 0xe4, 0xff, 0xe2, 0x5f, 0x15, 0x54, 0x60, 0x10, 0xe1, 0x8c, - 0xa6, 0xdc, 0xec, 0xc8, 0x94, 0x6e, 0x8f, 0xbf, 0x0d, 0xfe, 0x13, 0xff, 0xfb, 0xa3, 0x30, 0x95, - 0x7d, 0xff, 0xd3, 0x76, 0x6f, 0xa9, 0xbb, 0xbd, 0xa5, 0xfe, 0xd9, 0x5b, 0xea, 0x8f, 0xca, 0x52, - 0x76, 0x95, 0xa5, 0xfc, 0xaa, 0x2c, 0x65, 0xee, 0xb7, 0xfe, 0xb2, 0x39, 0xad, 0x49, 0x02, 0x43, - 0x7e, 0x2a, 0xbc, 0x2f, 0x2f, 0x5e, 0x79, 0x5f, 0xaf, 0x9d, 0xa6, 0x4c, 0x21, 0xec, 0xca, 0x53, - 0x7a, 0xf9, 0x37, 0x00, 0x00, 0xff, 0xff, 0xd6, 0x6e, 0xd0, 0xa3, 0xc9, 0x02, 0x00, 0x00, + // 463 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x93, 0xb1, 0x6f, 0xd3, 0x40, + 0x14, 0xc6, 0x63, 0x1a, 0x2a, 0xea, 0xd1, 0x2a, 0xc2, 0x14, 0xb0, 0x23, 0x23, 0x95, 0x48, 0x28, + 0xb6, 0x00, 0xb1, 0x30, 0x9a, 0xc0, 0x86, 0x14, 0x1c, 0x06, 0x54, 0x21, 0x9d, 0xce, 0xe7, 0x47, + 0x72, 0x8a, 0xed, 0xe7, 0xde, 0x3b, 0x13, 0xc2, 0xc2, 0xca, 0xc8, 0x7f, 0xc0, 0xbf, 0xd3, 0xb1, + 0x23, 0x62, 0xb0, 0x50, 0xb2, 0x33, 0xe4, 0x2f, 0x40, 0xb5, 0xdd, 0x36, 0x05, 0x2a, 0x60, 0xb2, + 0xef, 0x7d, 0xbf, 0xef, 0xee, 0xd3, 0xe7, 0xb3, 0x79, 0x1f, 0x29, 0x43, 0x92, 0x14, 0x08, 0xcc, + 0x05, 0xe4, 0x5a, 0x71, 0x0d, 0xc9, 0x20, 0x95, 0x87, 0xa5, 0x4c, 0xa4, 0x5e, 0x04, 0x05, 0x57, + 0x3c, 0x23, 0xbf, 0x50, 0xa8, 0xd1, 0xba, 0xd3, 0xc2, 0xfe, 0x26, 0x7c, 0xc6, 0xee, 0xed, 0x4e, + 0x70, 0x82, 0x35, 0x19, 0x9c, 0xbc, 0x35, 0xa6, 0xbd, 0x9b, 0xa2, 0x76, 0xb1, 0x46, 0x68, 0x16, + 0x8d, 0xe4, 0xfd, 0xe8, 0x9a, 0xdb, 0xa3, 0xfa, 0x00, 0xeb, 0xc0, 0xbc, 0xc1, 0x4b, 0x3d, 0x45, + 0x25, 0x3f, 0x40, 0xc2, 0xb4, 0x14, 0x33, 0x46, 0x05, 0x17, 0x32, 0x9f, 0xd8, 0x46, 0x6f, 0xab, + 0xdf, 0x0d, 0xbd, 0x75, 0xe5, 0x3a, 0x0b, 0x9e, 0xa5, 0x4f, 0xbc, 0x4b, 0x40, 0x2f, 0xba, 0x7e, + 0xae, 0xbc, 0x92, 0x62, 0x36, 0x6e, 0xe6, 0xd6, 0x47, 0x73, 0x77, 0xc3, 0x42, 0x73, 0x5e, 0xb0, + 0xb7, 0x00, 0x64, 0x5f, 0xe9, 0x6d, 0xf5, 0x77, 0xc2, 0x17, 0x47, 0x95, 0xdb, 0xf9, 0x56, 0xb9, + 0xfb, 0x13, 0xa9, 0xa7, 0x65, 0xec, 0x0b, 0xcc, 0xda, 0x94, 0xed, 0x63, 0x40, 0xc9, 0x2c, 0xd0, + 0x8b, 0x02, 0xc8, 0x1f, 0x82, 0x58, 0x57, 0xee, 0xad, 0xdf, 0x62, 0x9c, 0xed, 0xe9, 0x45, 0xd6, + 0xf9, 0x78, 0x3c, 0xe7, 0xc5, 0x73, 0x00, 0xb2, 0xbe, 0x18, 0xa6, 0x1b, 0xf3, 0x94, 0xe7, 0x02, + 0x14, 0xa3, 0x29, 0x57, 0x40, 0x4c, 0xc1, 0x9c, 0xab, 0x84, 0x25, 0x92, 0x04, 0x96, 0xb9, 0xb6, + 0xb7, 0x7a, 0x46, 0x7f, 0x27, 0x7c, 0xfd, 0xdf, 0x61, 0xf6, 0x9b, 0x30, 0x7f, 0xd9, 0xde, 0x8b, + 0x6e, 0x9f, 0x12, 0xe3, 0x1a, 0x88, 0x6a, 0x7d, 0xd8, 0xca, 0xbf, 0xd4, 0x7f, 0x58, 0xa2, 0x06, + 0x96, 0x40, 0x8e, 0x19, 0xd9, 0xdd, 0xba, 0xa5, 0x3f, 0xd7, 0xbf, 0x09, 0x5e, 0xa8, 0xff, 0xe5, + 0x89, 0x30, 0xac, 0xe7, 0xd6, 0x27, 0xc3, 0xbc, 0x27, 0x89, 0x15, 0xa0, 0x32, 0x49, 0x24, 0x31, + 0x4f, 0x81, 0x88, 0x15, 0x88, 0x29, 0x13, 0x0a, 0xb8, 0x96, 0x98, 0x33, 0xc8, 0x79, 0x9c, 0x42, + 0x62, 0x5f, 0xed, 0x19, 0xfd, 0x6b, 0xe1, 0xc3, 0x75, 0xe5, 0xfa, 0xcd, 0x61, 0xff, 0x68, 0xf4, + 0xa2, 0xbb, 0x92, 0x46, 0x17, 0xc0, 0x11, 0x62, 0xfa, 0xb4, 0xc5, 0x9e, 0x35, 0x54, 0xf8, 0xe6, + 0x68, 0xe9, 0x18, 0xc7, 0x4b, 0xc7, 0xf8, 0xbe, 0x74, 0x8c, 0xcf, 0x2b, 0xa7, 0x73, 0xbc, 0x72, + 0x3a, 0x5f, 0x57, 0x4e, 0xe7, 0x20, 0xdc, 0x28, 0xbc, 0xbd, 0xe5, 0x83, 0x94, 0xc7, 0x74, 0xba, + 0x08, 0xde, 0x3d, 0x78, 0x1c, 0xbc, 0xbf, 0xec, 0x2f, 0xa9, 0x3f, 0x48, 0xbc, 0x5d, 0xdf, 0xea, + 0x47, 0x3f, 0x03, 0x00, 0x00, 0xff, 0xff, 0x1a, 0xf9, 0x5a, 0xc1, 0x54, 0x03, 0x00, 0x00, } func (m *Params) Marshal() (dAtA []byte, err error) { @@ -151,6 +168,16 @@ func (m *Params) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if m.IsPermissionlessPoolCreationEnabled { + i-- + if m.IsPermissionlessPoolCreationEnabled { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x28 + } if len(m.AuthorizedQuoteDenoms) > 0 { for iNdEx := len(m.AuthorizedQuoteDenoms) - 1; iNdEx >= 0; iNdEx-- { i -= len(m.AuthorizedQuoteDenoms[iNdEx]) @@ -243,6 +270,9 @@ func (m *Params) Size() (n int) { n += 1 + l + sovParams(uint64(l)) } } + if m.IsPermissionlessPoolCreationEnabled { + n += 2 + } return n } @@ -459,6 +489,26 @@ func (m *Params) Unmarshal(dAtA []byte) error { } m.AuthorizedQuoteDenoms = append(m.AuthorizedQuoteDenoms, string(dAtA[iNdEx:postIndex])) iNdEx = postIndex + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field IsPermissionlessPoolCreationEnabled", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.IsPermissionlessPoolCreationEnabled = bool(v != 0) default: iNdEx = preIndex skippy, err := skipParams(dAtA[iNdEx:]) diff --git a/x/gamm/keeper/grpc_query.go b/x/gamm/keeper/grpc_query.go index 869f0b281e3..3184316f559 100644 --- a/x/gamm/keeper/grpc_query.go +++ b/x/gamm/keeper/grpc_query.go @@ -477,3 +477,21 @@ func (q Querier) EstimateSwapExactAmountOut(ctx context.Context, req *types.Quer TokenInAmount: tokenInAmount, }, nil } + +// ConcentratedPoolIdLinkFromCFMM queries the concentrated pool id linked to a cfmm pool id. +func (q Querier) ConcentratedPoolIdLinkFromCFMM(ctx context.Context, req *types.QueryConcentratedPoolIdLinkFromCFMMRequest) (*types.QueryConcentratedPoolIdLinkFromCFMMResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "empty request") + } + if req.CfmmPoolId == 0 { + return nil, status.Error(codes.InvalidArgument, "invalid cfmm pool id") + } + poolIdEntering, err := q.Keeper.GetLinkedConcentratedPoolID(sdk.UnwrapSDKContext(ctx), req.CfmmPoolId) + if err != nil { + return nil, err + } + + return &types.QueryConcentratedPoolIdLinkFromCFMMResponse{ + ConcentratedPoolId: poolIdEntering, + }, nil +} diff --git a/x/gamm/keeper/keeper.go b/x/gamm/keeper/keeper.go index 036847b6d04..a31826571e6 100644 --- a/x/gamm/keeper/keeper.go +++ b/x/gamm/keeper/keeper.go @@ -88,3 +88,9 @@ func (k Keeper) GetParams(ctx sdk.Context) (params types.Params) { func (k Keeper) setParams(ctx sdk.Context, params types.Params) { k.paramSpace.SetParamSet(ctx, ¶ms) } + +// ValidatePermissionlessPoolCreationEnabled returns nil if permissionless pool creation in the module is enabled. +// Pools in gamm module have permissionless pool creation enabled, thus always return nil. +func (k Keeper) ValidatePermissionlessPoolCreationEnabled(ctx sdk.Context) error { + return nil +} diff --git a/x/gamm/types/query.pb.go b/x/gamm/types/query.pb.go index a52949f1230..9496169128d 100644 --- a/x/gamm/types/query.pb.go +++ b/x/gamm/types/query.pb.go @@ -1485,6 +1485,103 @@ func (m *QueryTotalLiquidityResponse) GetLiquidity() github_com_cosmos_cosmos_sd return nil } +// =============================== QueryConcentratedPoolIdLinkFromCFMM +type QueryConcentratedPoolIdLinkFromCFMMRequest struct { + CfmmPoolId uint64 `protobuf:"varint,1,opt,name=cfmm_pool_id,json=cfmmPoolId,proto3" json:"cfmm_pool_id,omitempty" yaml:"cfmm_pool_id"` +} + +func (m *QueryConcentratedPoolIdLinkFromCFMMRequest) Reset() { + *m = QueryConcentratedPoolIdLinkFromCFMMRequest{} +} +func (m *QueryConcentratedPoolIdLinkFromCFMMRequest) String() string { + return proto.CompactTextString(m) +} +func (*QueryConcentratedPoolIdLinkFromCFMMRequest) ProtoMessage() {} +func (*QueryConcentratedPoolIdLinkFromCFMMRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_d9a717df9ca609ef, []int{30} +} +func (m *QueryConcentratedPoolIdLinkFromCFMMRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryConcentratedPoolIdLinkFromCFMMRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryConcentratedPoolIdLinkFromCFMMRequest.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 *QueryConcentratedPoolIdLinkFromCFMMRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryConcentratedPoolIdLinkFromCFMMRequest.Merge(m, src) +} +func (m *QueryConcentratedPoolIdLinkFromCFMMRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryConcentratedPoolIdLinkFromCFMMRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryConcentratedPoolIdLinkFromCFMMRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryConcentratedPoolIdLinkFromCFMMRequest proto.InternalMessageInfo + +func (m *QueryConcentratedPoolIdLinkFromCFMMRequest) GetCfmmPoolId() uint64 { + if m != nil { + return m.CfmmPoolId + } + return 0 +} + +type QueryConcentratedPoolIdLinkFromCFMMResponse struct { + ConcentratedPoolId uint64 `protobuf:"varint,1,opt,name=concentrated_pool_id,json=concentratedPoolId,proto3" json:"concentrated_pool_id,omitempty"` +} + +func (m *QueryConcentratedPoolIdLinkFromCFMMResponse) Reset() { + *m = QueryConcentratedPoolIdLinkFromCFMMResponse{} +} +func (m *QueryConcentratedPoolIdLinkFromCFMMResponse) String() string { + return proto.CompactTextString(m) +} +func (*QueryConcentratedPoolIdLinkFromCFMMResponse) ProtoMessage() {} +func (*QueryConcentratedPoolIdLinkFromCFMMResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_d9a717df9ca609ef, []int{31} +} +func (m *QueryConcentratedPoolIdLinkFromCFMMResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryConcentratedPoolIdLinkFromCFMMResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryConcentratedPoolIdLinkFromCFMMResponse.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 *QueryConcentratedPoolIdLinkFromCFMMResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryConcentratedPoolIdLinkFromCFMMResponse.Merge(m, src) +} +func (m *QueryConcentratedPoolIdLinkFromCFMMResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryConcentratedPoolIdLinkFromCFMMResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryConcentratedPoolIdLinkFromCFMMResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryConcentratedPoolIdLinkFromCFMMResponse proto.InternalMessageInfo + +func (m *QueryConcentratedPoolIdLinkFromCFMMResponse) GetConcentratedPoolId() uint64 { + if m != nil { + return m.ConcentratedPoolId + } + return 0 +} + func init() { proto.RegisterType((*QueryPoolRequest)(nil), "osmosis.gamm.v1beta1.QueryPoolRequest") proto.RegisterType((*QueryPoolResponse)(nil), "osmosis.gamm.v1beta1.QueryPoolResponse") @@ -1516,127 +1613,137 @@ func init() { proto.RegisterType((*QuerySwapExactAmountOutResponse)(nil), "osmosis.gamm.v1beta1.QuerySwapExactAmountOutResponse") proto.RegisterType((*QueryTotalLiquidityRequest)(nil), "osmosis.gamm.v1beta1.QueryTotalLiquidityRequest") proto.RegisterType((*QueryTotalLiquidityResponse)(nil), "osmosis.gamm.v1beta1.QueryTotalLiquidityResponse") + proto.RegisterType((*QueryConcentratedPoolIdLinkFromCFMMRequest)(nil), "osmosis.gamm.v1beta1.QueryConcentratedPoolIdLinkFromCFMMRequest") + proto.RegisterType((*QueryConcentratedPoolIdLinkFromCFMMResponse)(nil), "osmosis.gamm.v1beta1.QueryConcentratedPoolIdLinkFromCFMMResponse") } func init() { proto.RegisterFile("osmosis/gamm/v1beta1/query.proto", fileDescriptor_d9a717df9ca609ef) } var fileDescriptor_d9a717df9ca609ef = []byte{ - // 1840 bytes of a gzipped FileDescriptorProto + // 1964 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x58, 0x4d, 0x6c, 0x1c, 0x49, - 0x15, 0x76, 0x8d, 0x7f, 0xd6, 0x53, 0x5e, 0xff, 0xd5, 0x3a, 0x9b, 0xc9, 0xd8, 0x99, 0x09, 0xc5, - 0xae, 0xed, 0x4d, 0xec, 0x1e, 0xdb, 0x71, 0x04, 0x32, 0x64, 0x77, 0x6d, 0xaf, 0x9d, 0x8c, 0x95, - 0xc4, 0xa6, 0x13, 0x81, 0x00, 0xc1, 0xa8, 0x6d, 0x77, 0xc6, 0x9d, 0xcc, 0x74, 0xb5, 0xa7, 0xab, - 0x63, 0x5b, 0x28, 0x8a, 0x94, 0x53, 0xe0, 0x12, 0x24, 0x20, 0x08, 0x84, 0x80, 0x03, 0x42, 0x88, - 0x33, 0x82, 0x13, 0x07, 0x84, 0x90, 0x22, 0x4e, 0x91, 0xe0, 0x80, 0x38, 0x0c, 0x28, 0x81, 0x1b, - 0x27, 0x5f, 0xb8, 0xa2, 0xaa, 0x7a, 0xfd, 0x33, 0xff, 0x3f, 0x10, 0x29, 0x9c, 0xec, 0xa9, 0x7a, - 0x3f, 0xdf, 0xfb, 0xde, 0xab, 0xd7, 0xaf, 0x0a, 0x5f, 0x60, 0x6e, 0x91, 0xb9, 0x96, 0x9b, 0xc9, - 0x1b, 0xc5, 0x62, 0xe6, 0xc1, 0xe2, 0xae, 0xc9, 0x8d, 0xc5, 0xcc, 0xa1, 0x67, 0x96, 0x4e, 0x34, - 0xa7, 0xc4, 0x38, 0x23, 0x13, 0x20, 0xa1, 0x09, 0x09, 0x0d, 0x24, 0x92, 0x13, 0x79, 0x96, 0x67, - 0x52, 0x20, 0x23, 0xfe, 0x53, 0xb2, 0xc9, 0xf3, 0x75, 0xad, 0xf1, 0x63, 0xd8, 0x9e, 0xf3, 0xb7, - 0x1d, 0xc6, 0x0a, 0x45, 0xc3, 0x36, 0xf2, 0x66, 0x29, 0x90, 0x72, 0x8f, 0x0c, 0x27, 0x57, 0x62, - 0x1e, 0x37, 0x41, 0x3a, 0xb5, 0x27, 0xc5, 0x33, 0xbb, 0x86, 0x6b, 0x06, 0x52, 0x7b, 0xcc, 0xb2, - 0x61, 0xff, 0x62, 0x74, 0x5f, 0x22, 0x0e, 0xa4, 0x1c, 0x23, 0x6f, 0xd9, 0x06, 0xb7, 0x98, 0x2f, - 0x3b, 0x95, 0x67, 0x2c, 0x5f, 0x30, 0x33, 0x86, 0x63, 0x65, 0x0c, 0xdb, 0x66, 0x5c, 0x6e, 0xba, - 0xb0, 0x7b, 0x0e, 0x76, 0xe5, 0xaf, 0x5d, 0xef, 0x6e, 0xc6, 0xb0, 0x4f, 0xfc, 0x2d, 0xe5, 0x24, - 0xa7, 0x42, 0x55, 0x3f, 0xd4, 0x16, 0x5d, 0xc7, 0x63, 0x5f, 0x10, 0x5e, 0x77, 0x18, 0x2b, 0xe8, - 0xe6, 0xa1, 0x67, 0xba, 0x9c, 0x5c, 0xc2, 0x6f, 0x89, 0xd8, 0x72, 0xd6, 0x7e, 0x02, 0x5d, 0x40, - 0xb3, 0x7d, 0x6b, 0xe4, 0xb4, 0x9c, 0x1e, 0x39, 0x31, 0x8a, 0x85, 0x15, 0x0a, 0x1b, 0x54, 0x1f, - 0x10, 0xff, 0x65, 0xf7, 0x57, 0x62, 0x09, 0x44, 0x6f, 0xe0, 0xf1, 0x88, 0x11, 0xd7, 0x61, 0xb6, - 0x6b, 0x92, 0xcb, 0xb8, 0x4f, 0x88, 0x48, 0x13, 0x43, 0x4b, 0x13, 0x9a, 0x82, 0xa7, 0xf9, 0xf0, - 0xb4, 0x55, 0xfb, 0x64, 0x2d, 0xfe, 0xc7, 0x5f, 0xcd, 0xf7, 0x0b, 0xad, 0xac, 0x2e, 0x85, 0xa5, - 0xb5, 0xaf, 0x46, 0xac, 0xb9, 0x3e, 0xa6, 0x4d, 0x8c, 0x43, 0x3e, 0x12, 0x31, 0x69, 0x73, 0x5a, - 0x83, 0x50, 0x04, 0x79, 0x9a, 0x4a, 0x37, 0x90, 0xa7, 0xed, 0x18, 0x79, 0x13, 0x74, 0xf5, 0x88, - 0x26, 0xfd, 0x2e, 0xc2, 0x24, 0x6a, 0x1d, 0xc0, 0x5e, 0xc1, 0xfd, 0xc2, 0xbf, 0x9b, 0x40, 0x17, - 0x7a, 0xdb, 0x41, 0xab, 0xa4, 0xc9, 0xb5, 0x3a, 0xa8, 0x66, 0x5a, 0xa2, 0x52, 0x3e, 0x2b, 0x60, - 0x25, 0xf1, 0x84, 0x44, 0x75, 0xcb, 0x2b, 0x46, 0xc3, 0x96, 0x7c, 0xdc, 0xc2, 0x67, 0xaa, 0xf6, - 0x00, 0xf4, 0x22, 0x8e, 0xdb, 0x5e, 0x31, 0xe7, 0x03, 0x17, 0x99, 0x9a, 0x38, 0x2d, 0xa7, 0xc7, - 0x54, 0xa6, 0x82, 0x2d, 0xaa, 0x0f, 0xda, 0xa0, 0x2a, 0xed, 0xad, 0x83, 0x2f, 0xb1, 0x72, 0xe7, - 0xc4, 0x31, 0xbb, 0x49, 0x3b, 0xdd, 0x02, 0x50, 0xa1, 0x91, 0x10, 0x94, 0x14, 0xe6, 0x27, 0x8e, - 0x29, 0xed, 0xc4, 0xa3, 0xa0, 0x82, 0x2d, 0xaa, 0x0f, 0x3a, 0xa0, 0x4a, 0x7f, 0x83, 0x70, 0x4a, - 0x1a, 0x5b, 0x37, 0x0a, 0x7b, 0x5b, 0xcc, 0xb2, 0x85, 0xd1, 0xdb, 0x07, 0x46, 0xc9, 0x74, 0xbb, - 0xc1, 0x46, 0x0e, 0x70, 0x9c, 0xb3, 0xfb, 0xa6, 0xed, 0xe6, 0x2c, 0x91, 0x14, 0x91, 0xd0, 0x73, - 0x15, 0x49, 0xf1, 0xd3, 0xb1, 0xce, 0x2c, 0x7b, 0x6d, 0xe1, 0x79, 0x39, 0xdd, 0xf3, 0xcb, 0xbf, - 0xa5, 0x67, 0xf3, 0x16, 0x3f, 0xf0, 0x76, 0xb5, 0x3d, 0x56, 0x84, 0x23, 0x02, 0x7f, 0xe6, 0xdd, - 0xfd, 0xfb, 0x19, 0x81, 0xd9, 0x95, 0x0a, 0xae, 0x3e, 0xa8, 0xac, 0x67, 0x6d, 0xfa, 0x38, 0x86, - 0xd3, 0x0d, 0x91, 0x03, 0x21, 0x2e, 0x1e, 0x73, 0xc5, 0x4a, 0x8e, 0x79, 0x3c, 0x67, 0x14, 0x99, - 0x67, 0x73, 0xe0, 0x25, 0x2b, 0x3c, 0xff, 0xb5, 0x9c, 0x9e, 0x6e, 0xc3, 0x73, 0xd6, 0xe6, 0xa7, - 0xe5, 0xf4, 0x59, 0x15, 0x71, 0xb5, 0x3d, 0xaa, 0x8f, 0xc8, 0xa5, 0x6d, 0x8f, 0xaf, 0xca, 0x05, - 0x72, 0x0f, 0x63, 0xa0, 0x80, 0x79, 0xfc, 0x75, 0x70, 0x00, 0x0c, 0x6f, 0x7b, 0x9c, 0xfe, 0x10, - 0xe1, 0x99, 0x80, 0x84, 0x8d, 0x63, 0x8b, 0x0b, 0x12, 0xa4, 0xd4, 0x66, 0x89, 0x15, 0x2b, 0xf3, - 0x78, 0xb6, 0x2a, 0x8f, 0x41, 0xce, 0xbe, 0x88, 0x47, 0x55, 0x54, 0x96, 0xed, 0x93, 0x14, 0x93, - 0x24, 0x69, 0x9d, 0x91, 0xa4, 0x0f, 0x4b, 0x33, 0x59, 0x5b, 0x11, 0x41, 0x9f, 0x21, 0x3c, 0xdb, - 0x1a, 0x1c, 0xa4, 0xaa, 0x92, 0x35, 0xf4, 0x5a, 0x59, 0xdb, 0xc0, 0xef, 0x06, 0x07, 0x68, 0xc7, - 0x28, 0x19, 0xc5, 0xae, 0x6a, 0x9d, 0x5e, 0xc3, 0x67, 0x6b, 0xcc, 0x40, 0x34, 0x73, 0x78, 0xc0, - 0x91, 0x2b, 0xcd, 0x5a, 0xb0, 0x0e, 0x32, 0xf4, 0x26, 0x9c, 0xc1, 0x3b, 0x8c, 0x1b, 0x05, 0x61, - 0xed, 0x86, 0x75, 0xe8, 0x59, 0xfb, 0x16, 0x3f, 0xe9, 0x0a, 0xd7, 0x4f, 0x11, 0x9c, 0x8c, 0x7a, - 0xf6, 0x00, 0xe0, 0x43, 0x1c, 0x2f, 0xf8, 0x8b, 0xad, 0xd9, 0xfe, 0x44, 0xb0, 0x1d, 0x76, 0x92, - 0x40, 0x93, 0x76, 0x96, 0x81, 0x50, 0x6f, 0x13, 0xa8, 0x93, 0x08, 0xbb, 0x6f, 0x37, 0xd4, 0xc3, - 0x89, 0x5a, 0x3b, 0x10, 0xe2, 0x97, 0xf1, 0xdb, 0x5c, 0x2c, 0xe7, 0x64, 0x55, 0xfa, 0x99, 0x68, - 0x12, 0xe5, 0x24, 0x44, 0xf9, 0x8e, 0x72, 0x16, 0x55, 0xa6, 0xfa, 0x10, 0x0f, 0x5d, 0xd0, 0xdf, - 0x22, 0xfc, 0x5e, 0x4d, 0xef, 0xb9, 0xc5, 0x6e, 0x1f, 0x19, 0xce, 0xff, 0x45, 0xef, 0xfc, 0x37, - 0xc2, 0xef, 0xb7, 0xc0, 0x0f, 0x24, 0x3e, 0xea, 0xec, 0x58, 0x6e, 0x00, 0x85, 0xe3, 0x3e, 0x85, - 0xbe, 0x2a, 0xed, 0xf2, 0xac, 0x92, 0x9b, 0x18, 0xab, 0x14, 0x40, 0x37, 0xed, 0xa6, 0x2f, 0xc5, - 0x95, 0x05, 0x71, 0xf4, 0xff, 0x85, 0xe0, 0xe3, 0x79, 0xdb, 0x61, 0x7c, 0xa7, 0x64, 0xed, 0x75, - 0xf5, 0x09, 0x26, 0x1b, 0x78, 0x4c, 0x04, 0x9f, 0x33, 0x5c, 0xd7, 0xe4, 0xb9, 0x7d, 0xd3, 0x66, - 0x45, 0xc0, 0x36, 0x19, 0x7e, 0x2a, 0xaa, 0x25, 0xa8, 0x3e, 0x22, 0x96, 0x56, 0xc5, 0xca, 0x27, - 0x62, 0x81, 0x5c, 0xc7, 0xe3, 0x87, 0x1e, 0xe3, 0x95, 0x76, 0x7a, 0xa5, 0x9d, 0xa9, 0xd3, 0x72, - 0x3a, 0xa1, 0xec, 0xd4, 0x88, 0x50, 0x7d, 0x54, 0xae, 0x85, 0x96, 0xc4, 0x70, 0xb1, 0xd5, 0x37, - 0xd8, 0x37, 0xd6, 0xaf, 0x0f, 0x1d, 0x59, 0xfc, 0x40, 0x64, 0x72, 0xd3, 0x34, 0xe9, 0xef, 0x10, - 0x9e, 0x0c, 0x47, 0xae, 0x2f, 0x59, 0xfc, 0x60, 0xd3, 0x2a, 0x70, 0xb3, 0xe4, 0x07, 0x7d, 0x15, - 0x0f, 0x17, 0x2d, 0x3b, 0x17, 0x6d, 0x05, 0xc2, 0x79, 0xe2, 0xb4, 0x9c, 0x9e, 0x50, 0xce, 0x2b, - 0xb6, 0xa9, 0xfe, 0x76, 0xd1, 0xb2, 0x83, 0x6e, 0x42, 0x26, 0xa3, 0x03, 0x87, 0x8c, 0x3f, 0x1c, - 0x2d, 0xaa, 0xc6, 0xc6, 0xde, 0xae, 0xc7, 0xc6, 0x1f, 0x23, 0x3c, 0x55, 0x3f, 0x86, 0x37, 0x64, - 0x80, 0xd4, 0xe1, 0x73, 0x12, 0x29, 0x29, 0x40, 0xb6, 0x8c, 0xb1, 0xeb, 0x30, 0x9e, 0x73, 0xc4, - 0x2a, 0x70, 0x7b, 0x26, 0x3c, 0x1e, 0xe1, 0x1e, 0xd5, 0xe3, 0xae, 0xaf, 0x2d, 0x07, 0xc5, 0x6f, - 0xc5, 0xf0, 0x79, 0x65, 0xf4, 0xc8, 0x70, 0x36, 0x8e, 0x8d, 0x3d, 0x98, 0x2e, 0xb2, 0xb6, 0x9f, - 0xba, 0x0f, 0xf0, 0x80, 0x6b, 0xda, 0xfb, 0x66, 0x09, 0xec, 0x8e, 0x9f, 0x96, 0xd3, 0xc3, 0x60, - 0x57, 0xae, 0x53, 0x1d, 0x04, 0xa2, 0xa5, 0x1d, 0x6b, 0x59, 0xda, 0x1a, 0x56, 0x7d, 0x42, 0x34, - 0x21, 0x55, 0x8a, 0xef, 0x9c, 0x96, 0xd3, 0xa3, 0x91, 0x03, 0x9d, 0xb3, 0x6c, 0xaa, 0xbf, 0x25, - 0xff, 0xcd, 0xda, 0xe4, 0x6b, 0x78, 0x40, 0x5e, 0xba, 0xdc, 0x44, 0x9f, 0xa4, 0x5f, 0xd3, 0xfc, - 0xfb, 0x5e, 0xe4, 0x92, 0x16, 0x90, 0x28, 0xc2, 0x09, 0x22, 0x11, 0x6a, 0x6b, 0x67, 0xa0, 0x65, - 0x00, 0x76, 0x65, 0x8b, 0xea, 0x60, 0x54, 0x92, 0xf1, 0x03, 0x7f, 0x48, 0xad, 0x43, 0x46, 0x38, - 0xe9, 0x29, 0x6c, 0xff, 0xbb, 0x49, 0xaf, 0xda, 0x1e, 0xd5, 0x47, 0xe4, 0x52, 0x30, 0xe9, 0x49, - 0x6c, 0x4f, 0x63, 0xf5, 0xb1, 0x6d, 0x7b, 0xfc, 0x75, 0x67, 0xea, 0xeb, 0x01, 0xf3, 0xbd, 0x92, - 0xf9, 0x4c, 0x9b, 0xcc, 0x0b, 0x68, 0x6d, 0x50, 0x2f, 0xae, 0x13, 0x01, 0x07, 0x89, 0xbe, 0xea, - 0xeb, 0x44, 0xb0, 0x45, 0xe1, 0xc3, 0xb2, 0xed, 0x29, 0x46, 0xbe, 0xef, 0x8f, 0x1f, 0xf5, 0x18, - 0x81, 0x74, 0x39, 0x78, 0xd4, 0x2f, 0xa5, 0xca, 0x6c, 0x5d, 0xef, 0x38, 0x5b, 0xef, 0x56, 0x56, - 0x66, 0x90, 0xac, 0x61, 0x28, 0xd0, 0x48, 0xae, 0xa6, 0x70, 0x32, 0x9c, 0x16, 0xaa, 0x67, 0x2c, - 0xfa, 0x23, 0xbf, 0x57, 0x56, 0x6f, 0xbf, 0x11, 0x23, 0xd3, 0xd2, 0xaf, 0x27, 0x70, 0xbf, 0x84, - 0x47, 0x1e, 0x61, 0xd9, 0xc8, 0x5c, 0x32, 0xa3, 0xd5, 0x7b, 0x5a, 0xd1, 0x6a, 0x6e, 0xf0, 0xc9, - 0xd9, 0xd6, 0x82, 0x2a, 0x48, 0xfa, 0xe9, 0xc7, 0x7f, 0xfa, 0xc7, 0x77, 0x62, 0xe7, 0xc9, 0x64, - 0xa6, 0xee, 0x4b, 0x8c, 0xea, 0x9c, 0x4f, 0x11, 0x1e, 0xf4, 0x6f, 0xc4, 0xe4, 0x62, 0x13, 0xdb, - 0x55, 0x57, 0xea, 0xe4, 0xa5, 0xb6, 0x64, 0x01, 0xca, 0x45, 0x09, 0xe5, 0x53, 0x24, 0x5d, 0x1f, - 0x4a, 0x70, 0xc7, 0x7e, 0x12, 0x43, 0xe4, 0x67, 0x08, 0x8f, 0x54, 0xa6, 0x8d, 0x2c, 0x34, 0xf1, - 0x55, 0xb7, 0x00, 0x92, 0x8b, 0x1d, 0x68, 0x00, 0xc6, 0x79, 0x89, 0x71, 0x86, 0xbc, 0x5f, 0x1f, - 0xa3, 0x1a, 0x21, 0x83, 0x1c, 0x92, 0x9f, 0x23, 0x3c, 0x5a, 0xf5, 0x15, 0x23, 0x8b, 0xad, 0x72, - 0x53, 0xf3, 0xd5, 0x4e, 0x2e, 0x75, 0xa2, 0x02, 0x48, 0xe7, 0x24, 0xd2, 0x69, 0xf2, 0x5e, 0x7d, - 0xa4, 0x77, 0xa5, 0xb4, 0xb9, 0xaf, 0x28, 0x25, 0xdf, 0x44, 0xb8, 0x4f, 0x58, 0x22, 0xd3, 0x2d, - 0x5c, 0xf9, 0x90, 0x66, 0x5a, 0xca, 0x01, 0x8e, 0x85, 0xe6, 0x8c, 0x49, 0xf7, 0x99, 0x6f, 0x40, - 0xaf, 0x7b, 0x28, 0x72, 0xfb, 0x0c, 0xe1, 0x41, 0xff, 0xa9, 0xa3, 0x69, 0xb5, 0x55, 0x3d, 0xaa, - 0x34, 0xad, 0xb6, 0xea, 0xb7, 0x13, 0xba, 0x28, 0x71, 0x5d, 0x22, 0x1f, 0x34, 0xc6, 0x25, 0xc7, - 0x9c, 0x10, 0x1b, 0xf9, 0x1e, 0xc2, 0x89, 0x46, 0x03, 0x34, 0x59, 0x69, 0xe2, 0xbc, 0xc5, 0xad, - 0x21, 0xf9, 0xb9, 0xae, 0x74, 0x21, 0x90, 0x1e, 0xf2, 0x7b, 0x84, 0x49, 0xed, 0xa3, 0x08, 0x59, - 0x6e, 0xd3, 0x6a, 0x25, 0x96, 0x2b, 0x1d, 0x6a, 0x01, 0x8a, 0x8f, 0x25, 0x9d, 0x2b, 0xe4, 0xb3, - 0x6d, 0xa5, 0x39, 0x73, 0x8f, 0x59, 0x76, 0x4e, 0x3e, 0xe0, 0x9a, 0xe2, 0x83, 0x91, 0xb3, 0x6c, - 0xf2, 0x4f, 0x84, 0x27, 0x9b, 0x3c, 0x1c, 0x90, 0xab, 0x2d, 0x80, 0x35, 0x7f, 0x0d, 0x49, 0x7e, - 0xd8, 0xad, 0x3a, 0x04, 0x78, 0x4d, 0x06, 0xb8, 0x4a, 0x3e, 0x6a, 0x2f, 0x40, 0xf3, 0xd8, 0xe2, - 0x2a, 0x40, 0xf5, 0xd4, 0xa2, 0xbe, 0x52, 0x22, 0xce, 0x9f, 0x20, 0x8c, 0xc3, 0x17, 0x04, 0x32, - 0xd7, 0xa2, 0x68, 0x2b, 0xde, 0x2b, 0x92, 0xf3, 0x6d, 0x4a, 0x03, 0xe8, 0x65, 0x09, 0x5a, 0x23, - 0x73, 0xed, 0x81, 0x56, 0xcf, 0x13, 0xe4, 0x0f, 0x08, 0x93, 0xda, 0xa7, 0x84, 0xa6, 0xf5, 0xd4, - 0xf0, 0x25, 0xa3, 0x69, 0x3d, 0x35, 0x7e, 0xaf, 0xa0, 0x6b, 0x12, 0xf9, 0xe7, 0xc9, 0x4a, 0x7b, - 0xc8, 0x55, 0xe3, 0x95, 0x3f, 0xc3, 0xee, 0xfb, 0x0b, 0x84, 0x87, 0x22, 0x0f, 0x05, 0x64, 0xbe, - 0x15, 0x94, 0xca, 0x8a, 0xd1, 0xda, 0x15, 0x07, 0xc8, 0x2b, 0x12, 0xf2, 0x32, 0x59, 0xea, 0x04, - 0xb2, 0xba, 0xa9, 0x8a, 0xa2, 0x88, 0x07, 0xd7, 0x09, 0xd2, 0xac, 0x91, 0x55, 0xdf, 0x63, 0x93, - 0x73, 0xed, 0x09, 0x03, 0xc8, 0xcf, 0x74, 0x58, 0x11, 0x42, 0x59, 0x7e, 0x71, 0x5f, 0x20, 0x7c, - 0x6e, 0xc3, 0xe5, 0x56, 0xd1, 0xe0, 0x66, 0xcd, 0x58, 0x4e, 0x2e, 0x37, 0x03, 0xd1, 0xe0, 0x46, - 0x93, 0x5c, 0xee, 0x4c, 0x09, 0x22, 0xb8, 0x2e, 0x23, 0xf8, 0x88, 0x5c, 0xad, 0x1f, 0x41, 0xe4, - 0x08, 0x02, 0xda, 0x4c, 0xa4, 0xcf, 0x04, 0xc7, 0x50, 0x84, 0xf4, 0x67, 0x84, 0x93, 0x0d, 0x42, - 0xda, 0xf6, 0x38, 0xe9, 0x00, 0x5e, 0x38, 0xfc, 0x37, 0xad, 0xf7, 0xc6, 0x03, 0x32, 0xcd, 0xca, - 0xa8, 0x3e, 0x26, 0x1f, 0xfe, 0x17, 0x51, 0x31, 0x8f, 0x3f, 0x89, 0xa1, 0xb5, 0xad, 0xe7, 0x2f, - 0x53, 0xe8, 0xc5, 0xcb, 0x14, 0xfa, 0xfb, 0xcb, 0x14, 0xfa, 0xf6, 0xab, 0x54, 0xcf, 0x8b, 0x57, - 0xa9, 0x9e, 0xbf, 0xbc, 0x4a, 0xf5, 0x7c, 0x65, 0x21, 0x32, 0x87, 0x82, 0x9b, 0xf9, 0x82, 0xb1, - 0xeb, 0x06, 0x3e, 0x1f, 0x2c, 0x5e, 0xc9, 0x1c, 0x2b, 0xcf, 0x72, 0x2a, 0xdd, 0x1d, 0x90, 0x77, - 0xea, 0xcb, 0xff, 0x09, 0x00, 0x00, 0xff, 0xff, 0xb6, 0x55, 0xbd, 0xca, 0xf6, 0x1b, 0x00, 0x00, + 0xf5, 0x77, 0x4f, 0x1c, 0xaf, 0xfd, 0x92, 0xd8, 0x4e, 0xad, 0x93, 0x4c, 0xc6, 0xc9, 0x4c, 0xfe, + 0xf5, 0xdf, 0x8d, 0xb3, 0x89, 0xdd, 0x63, 0x27, 0x8e, 0x00, 0x43, 0x76, 0x63, 0x7b, 0xed, 0x64, + 0xac, 0x24, 0x36, 0x9d, 0x15, 0x08, 0x10, 0xb4, 0xda, 0xe3, 0xce, 0xb8, 0x37, 0xd3, 0x5d, 0x93, + 0xe9, 0xea, 0x8d, 0xad, 0x55, 0xb4, 0xd2, 0x9e, 0x80, 0xcb, 0x22, 0x01, 0x8b, 0x40, 0x08, 0x38, + 0x20, 0x84, 0x38, 0x71, 0x40, 0xe2, 0xc4, 0x01, 0x21, 0xa4, 0x15, 0xa7, 0x48, 0x70, 0x40, 0x1c, + 0x06, 0x94, 0xc0, 0x8d, 0x93, 0x2f, 0x7b, 0x45, 0x55, 0xf5, 0xfa, 0x63, 0x3e, 0xdc, 0xf3, 0xb1, + 0x44, 0x5a, 0x4e, 0x33, 0x5d, 0xf5, 0x3e, 0x7e, 0xef, 0xa3, 0x5e, 0xbd, 0x7a, 0x70, 0x81, 0xf9, + 0x2e, 0xf3, 0x1d, 0xbf, 0x58, 0xb1, 0x5c, 0xb7, 0xf8, 0xce, 0xc2, 0xb6, 0xcd, 0xad, 0x85, 0xe2, + 0xa3, 0xc0, 0xae, 0xef, 0xeb, 0xb5, 0x3a, 0xe3, 0x8c, 0x4c, 0x21, 0x85, 0x2e, 0x28, 0x74, 0xa4, + 0xc8, 0x4d, 0x55, 0x58, 0x85, 0x49, 0x82, 0xa2, 0xf8, 0xa7, 0x68, 0x73, 0xe7, 0x3b, 0x4a, 0xe3, + 0x7b, 0xb8, 0x3d, 0x1b, 0x6e, 0xd7, 0x18, 0xab, 0xba, 0x96, 0x67, 0x55, 0xec, 0x7a, 0x44, 0xe5, + 0x3f, 0xb6, 0x6a, 0x66, 0x9d, 0x05, 0xdc, 0x46, 0xea, 0x7c, 0x59, 0x92, 0x17, 0xb7, 0x2d, 0xdf, + 0x8e, 0xa8, 0xca, 0xcc, 0xf1, 0x70, 0xff, 0x72, 0x72, 0x5f, 0x22, 0x8e, 0xa8, 0x6a, 0x56, 0xc5, + 0xf1, 0x2c, 0xee, 0xb0, 0x90, 0xf6, 0x5c, 0x85, 0xb1, 0x4a, 0xd5, 0x2e, 0x5a, 0x35, 0xa7, 0x68, + 0x79, 0x1e, 0xe3, 0x72, 0xd3, 0xc7, 0xdd, 0xb3, 0xb8, 0x2b, 0xbf, 0xb6, 0x83, 0x07, 0x45, 0xcb, + 0xdb, 0x0f, 0xb7, 0x94, 0x12, 0x53, 0x99, 0xaa, 0x3e, 0xd4, 0x16, 0x5d, 0x85, 0xc9, 0x2f, 0x0a, + 0xad, 0x5b, 0x8c, 0x55, 0x0d, 0xfb, 0x51, 0x60, 0xfb, 0x9c, 0x5c, 0x81, 0x97, 0x84, 0x6d, 0xa6, + 0xb3, 0x93, 0xd5, 0x2e, 0x68, 0x97, 0x86, 0x57, 0xc8, 0x41, 0xa3, 0x30, 0xbe, 0x6f, 0xb9, 0xd5, + 0x25, 0x8a, 0x1b, 0xd4, 0x18, 0x11, 0xff, 0x4a, 0x3b, 0x4b, 0x99, 0xac, 0x46, 0xef, 0xc0, 0xc9, + 0x84, 0x10, 0xbf, 0xc6, 0x3c, 0xdf, 0x26, 0xd7, 0x60, 0x58, 0x90, 0x48, 0x11, 0xc7, 0xae, 0x4e, + 0xe9, 0x0a, 0x9e, 0x1e, 0xc2, 0xd3, 0x97, 0xbd, 0xfd, 0x95, 0xb1, 0x3f, 0xfd, 0x66, 0xee, 0xa8, + 0xe0, 0x2a, 0x19, 0x92, 0x58, 0x4a, 0xfb, 0x5a, 0x42, 0x9a, 0x1f, 0x62, 0x5a, 0x07, 0x88, 0xfd, + 0x91, 0xcd, 0x48, 0x99, 0x17, 0x75, 0x34, 0x45, 0x38, 0x4f, 0x57, 0xe1, 0x46, 0xe7, 0xe9, 0x5b, + 0x56, 0xc5, 0x46, 0x5e, 0x23, 0xc1, 0x49, 0xbf, 0xa7, 0x01, 0x49, 0x4a, 0x47, 0xb0, 0xd7, 0xe1, + 0xa8, 0xd0, 0xef, 0x67, 0xb5, 0x0b, 0x47, 0x7a, 0x41, 0xab, 0xa8, 0xc9, 0xad, 0x0e, 0xa8, 0x66, + 0xba, 0xa2, 0x52, 0x3a, 0x9b, 0x60, 0xe5, 0x60, 0x4a, 0xa2, 0xba, 0x17, 0xb8, 0x49, 0xb3, 0xa5, + 0x3f, 0xee, 0xc1, 0xa9, 0x96, 0x3d, 0x04, 0xbd, 0x00, 0x63, 0x5e, 0xe0, 0x9a, 0x21, 0x70, 0x11, + 0xa9, 0xa9, 0x83, 0x46, 0x61, 0x52, 0x45, 0x2a, 0xda, 0xa2, 0xc6, 0xa8, 0x87, 0xac, 0x52, 0xde, + 0x2a, 0xea, 0x12, 0x2b, 0x6f, 0xed, 0xd7, 0xec, 0x41, 0xc2, 0x4e, 0x37, 0x10, 0x54, 0x2c, 0x24, + 0x06, 0x25, 0x89, 0xf9, 0x7e, 0xcd, 0x96, 0x72, 0xc6, 0x92, 0xa0, 0xa2, 0x2d, 0x6a, 0x8c, 0xd6, + 0x90, 0x95, 0xfe, 0x56, 0x83, 0xbc, 0x14, 0xb6, 0x6a, 0x55, 0xcb, 0x1b, 0xcc, 0xf1, 0x84, 0xd0, + 0xfb, 0xbb, 0x56, 0xdd, 0xf6, 0x07, 0xc1, 0x46, 0x76, 0x61, 0x8c, 0xb3, 0x87, 0xb6, 0xe7, 0x9b, + 0x8e, 0x08, 0x8a, 0x08, 0xe8, 0xd9, 0xa6, 0xa0, 0x84, 0xe1, 0x58, 0x65, 0x8e, 0xb7, 0x32, 0xff, + 0x51, 0xa3, 0x30, 0xf4, 0xab, 0xbf, 0x17, 0x2e, 0x55, 0x1c, 0xbe, 0x1b, 0x6c, 0xeb, 0x65, 0xe6, + 0xe2, 0x11, 0xc1, 0x9f, 0x39, 0x7f, 0xe7, 0x61, 0x51, 0x60, 0xf6, 0x25, 0x83, 0x6f, 0x8c, 0x2a, + 0xe9, 0x25, 0x8f, 0xbe, 0x9f, 0x81, 0xc2, 0xa1, 0xc8, 0xd1, 0x21, 0x3e, 0x4c, 0xfa, 0x62, 0xc5, + 0x64, 0x01, 0x37, 0x2d, 0x97, 0x05, 0x1e, 0x47, 0xbf, 0x94, 0x84, 0xe6, 0xbf, 0x35, 0x0a, 0x17, + 0x7b, 0xd0, 0x5c, 0xf2, 0xf8, 0x41, 0xa3, 0x70, 0x46, 0x59, 0xdc, 0x2a, 0x8f, 0x1a, 0xe3, 0x72, + 0x69, 0x33, 0xe0, 0xcb, 0x72, 0x81, 0xbc, 0x0d, 0x80, 0x2e, 0x60, 0x01, 0x7f, 0x11, 0x3e, 0x40, + 0x0f, 0x6f, 0x06, 0x9c, 0xfe, 0x48, 0x83, 0x99, 0xc8, 0x09, 0x6b, 0x7b, 0x0e, 0x17, 0x4e, 0x90, + 0x54, 0xeb, 0x75, 0xe6, 0x36, 0xc7, 0xf1, 0x4c, 0x4b, 0x1c, 0xa3, 0x98, 0x7d, 0x09, 0x26, 0x94, + 0x55, 0x8e, 0x17, 0x3a, 0x29, 0x23, 0x9d, 0xa4, 0xf7, 0xe7, 0x24, 0xe3, 0x84, 0x14, 0x53, 0xf2, + 0x94, 0x23, 0xe8, 0x87, 0x1a, 0x5c, 0xea, 0x0e, 0x0e, 0x43, 0xd5, 0xec, 0x35, 0xed, 0x85, 0x7a, + 0x6d, 0x0d, 0x4e, 0x47, 0x07, 0x68, 0xcb, 0xaa, 0x5b, 0xee, 0x40, 0xb9, 0x4e, 0x6f, 0xc1, 0x99, + 0x36, 0x31, 0x68, 0xcd, 0x2c, 0x8c, 0xd4, 0xe4, 0x4a, 0x5a, 0x09, 0x36, 0x90, 0x86, 0xde, 0xc5, + 0x33, 0xf8, 0x16, 0xe3, 0x56, 0x55, 0x48, 0xbb, 0xe3, 0x3c, 0x0a, 0x9c, 0x1d, 0x87, 0xef, 0x0f, + 0x84, 0xeb, 0x67, 0x1a, 0x9e, 0x8c, 0x4e, 0xf2, 0x10, 0xe0, 0x13, 0x18, 0xab, 0x86, 0x8b, 0xdd, + 0xbd, 0xfd, 0xa6, 0xf0, 0x76, 0x5c, 0x49, 0x22, 0x4e, 0xda, 0x5f, 0x04, 0x62, 0xbe, 0x75, 0x74, + 0x9d, 0x44, 0x38, 0x78, 0xb9, 0xa1, 0x01, 0x64, 0xdb, 0xe5, 0xa0, 0x89, 0x5f, 0x81, 0xe3, 0x5c, + 0x2c, 0x9b, 0x32, 0x2b, 0xc3, 0x48, 0xa4, 0x58, 0x39, 0x8d, 0x56, 0xbe, 0xac, 0x94, 0x25, 0x99, + 0xa9, 0x71, 0x8c, 0xc7, 0x2a, 0xe8, 0xef, 0x34, 0x78, 0xa5, 0xad, 0xf6, 0xdc, 0x63, 0xf7, 0x1f, + 0x5b, 0xb5, 0xff, 0x89, 0xda, 0xf9, 0xb1, 0x06, 0xaf, 0x76, 0xc1, 0x8f, 0x4e, 0x7c, 0xaf, 0xbf, + 0x63, 0xb9, 0x86, 0x2e, 0x3c, 0x19, 0xba, 0x30, 0x64, 0xa5, 0x03, 0x9e, 0x55, 0x72, 0x17, 0x40, + 0x85, 0x00, 0xab, 0xe9, 0x20, 0x75, 0x69, 0x4c, 0x49, 0x10, 0x47, 0xff, 0xdf, 0x1a, 0x5e, 0x9e, + 0xf7, 0x6b, 0x8c, 0x6f, 0xd5, 0x9d, 0xf2, 0x40, 0x57, 0x30, 0x59, 0x83, 0x49, 0x61, 0xbc, 0x69, + 0xf9, 0xbe, 0xcd, 0xcd, 0x1d, 0xdb, 0x63, 0x2e, 0x62, 0x9b, 0x8e, 0xaf, 0x8a, 0x56, 0x0a, 0x6a, + 0x8c, 0x8b, 0xa5, 0x65, 0xb1, 0xf2, 0xa6, 0x58, 0x20, 0xb7, 0xe1, 0xe4, 0xa3, 0x80, 0xf1, 0x66, + 0x39, 0x47, 0xa4, 0x9c, 0x73, 0x07, 0x8d, 0x42, 0x56, 0xc9, 0x69, 0x23, 0xa1, 0xc6, 0x84, 0x5c, + 0x8b, 0x25, 0x89, 0xe6, 0x62, 0x63, 0x78, 0x74, 0x78, 0xf2, 0xa8, 0x71, 0xec, 0xb1, 0xc3, 0x77, + 0x45, 0x24, 0xd7, 0x6d, 0x9b, 0xfe, 0x5e, 0x83, 0xe9, 0xb8, 0xe5, 0xfa, 0xb2, 0xc3, 0x77, 0xd7, + 0x9d, 0x2a, 0xb7, 0xeb, 0xa1, 0xd1, 0x37, 0xe0, 0x84, 0xeb, 0x78, 0x66, 0xb2, 0x14, 0x08, 0xe5, + 0xd9, 0x83, 0x46, 0x61, 0x4a, 0x29, 0x6f, 0xda, 0xa6, 0xc6, 0x71, 0xd7, 0xf1, 0xa2, 0x6a, 0x42, + 0xa6, 0x93, 0x0d, 0x87, 0xb4, 0x3f, 0x6e, 0x2d, 0x5a, 0xda, 0xc6, 0x23, 0x03, 0xb7, 0x8d, 0x3f, + 0xd1, 0xe0, 0x5c, 0x67, 0x1b, 0x3e, 0x25, 0x0d, 0xa4, 0x81, 0xd7, 0x49, 0x22, 0xa5, 0x10, 0xd9, + 0x22, 0x80, 0x5f, 0x63, 0xdc, 0xac, 0x89, 0x55, 0xf4, 0xed, 0xa9, 0xf8, 0x78, 0xc4, 0x7b, 0xd4, + 0x18, 0xf3, 0x43, 0x6e, 0xd9, 0x28, 0x7e, 0x3b, 0x03, 0xe7, 0x95, 0xd0, 0xc7, 0x56, 0x6d, 0x6d, + 0xcf, 0x2a, 0x63, 0x77, 0x51, 0xf2, 0xc2, 0xd0, 0xbd, 0x06, 0x23, 0xbe, 0xed, 0xed, 0xd8, 0x75, + 0x94, 0x7b, 0xf2, 0xa0, 0x51, 0x38, 0x81, 0x72, 0xe5, 0x3a, 0x35, 0x90, 0x20, 0x99, 0xda, 0x99, + 0xae, 0xa9, 0xad, 0x83, 0xaa, 0x13, 0xa2, 0x08, 0xa9, 0x54, 0x7c, 0xf9, 0xa0, 0x51, 0x98, 0x48, + 0x1c, 0x68, 0xd3, 0xf1, 0xa8, 0xf1, 0x92, 0xfc, 0x5b, 0xf2, 0xc8, 0xd7, 0x61, 0x44, 0x3e, 0xba, + 0xfc, 0xec, 0xb0, 0x74, 0xbf, 0xae, 0x87, 0xef, 0xbd, 0xc4, 0x23, 0x2d, 0x72, 0xa2, 0x30, 0x27, + 0xb2, 0x44, 0xb0, 0xad, 0x9c, 0xc2, 0x92, 0x81, 0xd8, 0x95, 0x2c, 0x6a, 0xa0, 0x50, 0xe9, 0x8c, + 0x1f, 0x86, 0x4d, 0x6a, 0x07, 0x67, 0xc4, 0x9d, 0x9e, 0xc2, 0xf6, 0xdf, 0xeb, 0xf4, 0x5a, 0xe5, + 0x51, 0x63, 0x5c, 0x2e, 0x45, 0x9d, 0x9e, 0xc4, 0xf6, 0x41, 0xa6, 0x33, 0xb6, 0xcd, 0x80, 0xbf, + 0xe8, 0x48, 0x7d, 0x23, 0xf2, 0xfc, 0x11, 0xe9, 0xf9, 0x62, 0x8f, 0x9e, 0x17, 0xd0, 0x7a, 0x70, + 0xbd, 0x78, 0x4e, 0x44, 0x3e, 0xc8, 0x0e, 0xb7, 0x3e, 0x27, 0xa2, 0x2d, 0x8a, 0x17, 0xcb, 0x66, + 0xa0, 0x3c, 0xf2, 0x83, 0xb0, 0xfd, 0xe8, 0xe4, 0x11, 0x0c, 0x57, 0x0d, 0x26, 0xc2, 0x54, 0x6a, + 0x8e, 0xd6, 0xed, 0xbe, 0xa3, 0x75, 0xba, 0x39, 0x33, 0xa3, 0x60, 0x9d, 0xc0, 0x04, 0x4d, 0xc4, + 0xea, 0x1c, 0xe4, 0xe2, 0x6e, 0xa1, 0xb5, 0xc7, 0xa2, 0x3f, 0x0e, 0x6b, 0x65, 0xeb, 0xf6, 0xa7, + 0xa3, 0x65, 0xaa, 0xc0, 0x65, 0x75, 0x65, 0x33, 0xaf, 0x6c, 0x7b, 0xbc, 0x6e, 0x71, 0x7b, 0x47, + 0xd6, 0xb3, 0x9d, 0x3b, 0x8e, 0xf7, 0x50, 0x74, 0xd4, 0xab, 0xeb, 0x77, 0xef, 0x86, 0x39, 0xf7, + 0x39, 0x38, 0x5e, 0x7e, 0xe0, 0xaa, 0x57, 0x68, 0x7c, 0xa5, 0x9d, 0x89, 0xbb, 0x9b, 0xe4, 0x2e, + 0x35, 0x40, 0x7c, 0x2a, 0x69, 0xd4, 0x84, 0x2b, 0x3d, 0x29, 0x42, 0xb7, 0xcc, 0xc3, 0x54, 0x39, + 0x41, 0xd9, 0xac, 0xd1, 0x20, 0xe5, 0x36, 0x29, 0x57, 0x7f, 0x7d, 0x1a, 0x8e, 0x4a, 0x0d, 0xe4, + 0x3d, 0x90, 0x25, 0xd9, 0x27, 0x33, 0x7a, 0xa7, 0x21, 0x91, 0xde, 0x36, 0x8b, 0xc8, 0x5d, 0xea, + 0x4e, 0xa8, 0x70, 0xd1, 0xff, 0x7f, 0xff, 0xcf, 0xff, 0xfc, 0x6e, 0xe6, 0x3c, 0x99, 0x2e, 0x76, + 0x9c, 0x29, 0xa9, 0x3b, 0xe0, 0x03, 0x0d, 0x46, 0xc3, 0xb7, 0x3d, 0xb9, 0x9c, 0x22, 0xbb, 0x65, + 0x38, 0x90, 0xbb, 0xd2, 0x13, 0x2d, 0x42, 0xb9, 0x2c, 0xa1, 0xfc, 0x1f, 0x29, 0x74, 0x86, 0x12, + 0x4d, 0x0b, 0xbe, 0x99, 0xd1, 0xc8, 0xcf, 0x35, 0x18, 0x6f, 0x4e, 0x40, 0x32, 0x9f, 0xa2, 0xab, + 0x63, 0x2a, 0xe7, 0x16, 0xfa, 0xe0, 0x40, 0x8c, 0x73, 0x12, 0xe3, 0x0c, 0x79, 0xb5, 0x33, 0x46, + 0xd5, 0x0c, 0x47, 0xd9, 0x48, 0x7e, 0xa1, 0xc1, 0x44, 0xcb, 0x7d, 0x4c, 0x16, 0xba, 0xc5, 0xa6, + 0xad, 0xff, 0xc8, 0x5d, 0xed, 0x87, 0x05, 0x91, 0xce, 0x4a, 0xa4, 0x17, 0xc9, 0x2b, 0x9d, 0x91, + 0x3e, 0x90, 0xd4, 0x98, 0x88, 0x3e, 0xf9, 0x96, 0x06, 0xc3, 0x42, 0x12, 0xb9, 0xd8, 0x45, 0x55, + 0x08, 0x69, 0xa6, 0x2b, 0x1d, 0xe2, 0x98, 0x4f, 0xf7, 0x98, 0x54, 0x5f, 0x7c, 0x17, 0x8f, 0xc3, + 0x13, 0x11, 0xdb, 0x0f, 0x35, 0x18, 0x0d, 0x87, 0x36, 0xa9, 0xd9, 0xd6, 0x32, 0x1e, 0x4a, 0xcd, + 0xb6, 0xd6, 0x29, 0x10, 0x5d, 0x90, 0xb8, 0xae, 0x90, 0xd7, 0x0e, 0xc7, 0x25, 0x1b, 0xb6, 0x18, + 0x1b, 0xf9, 0xbe, 0x06, 0xd9, 0xc3, 0x9e, 0x02, 0x64, 0x29, 0x45, 0x79, 0x97, 0xf7, 0x4f, 0xee, + 0xf3, 0x03, 0xf1, 0xa2, 0x21, 0x43, 0xe4, 0x0f, 0x1a, 0x90, 0xf6, 0xf1, 0x0e, 0x59, 0xec, 0x51, + 0x6a, 0x33, 0x96, 0xeb, 0x7d, 0x72, 0x21, 0x8a, 0x9b, 0xd2, 0x9d, 0x4b, 0xe4, 0xb3, 0x3d, 0x85, + 0xb9, 0xf8, 0x36, 0x73, 0x3c, 0x53, 0x8e, 0xa2, 0x6d, 0x71, 0xf5, 0x99, 0x8e, 0x47, 0xfe, 0xa5, + 0xc1, 0x74, 0xca, 0x08, 0x84, 0xdc, 0xe8, 0x02, 0x2c, 0x7d, 0xae, 0x93, 0x7b, 0x7d, 0x50, 0x76, + 0x34, 0xf0, 0x96, 0x34, 0x70, 0x99, 0xbc, 0xd1, 0x9b, 0x81, 0xf6, 0x9e, 0xc3, 0x95, 0x81, 0x6a, + 0x68, 0xa4, 0xee, 0x5b, 0x61, 0xe7, 0x4f, 0x35, 0x80, 0x78, 0x16, 0x42, 0x66, 0xbb, 0x24, 0x6d, + 0xd3, 0xe4, 0x25, 0x37, 0xd7, 0x23, 0x35, 0x82, 0x5e, 0x94, 0xa0, 0x75, 0x32, 0xdb, 0x1b, 0x68, + 0x35, 0x68, 0x21, 0x7f, 0xd4, 0x80, 0xb4, 0x0f, 0x45, 0x52, 0xf3, 0xe9, 0xd0, 0x99, 0x4c, 0x6a, + 0x3e, 0x1d, 0x3e, 0x79, 0xa1, 0x2b, 0x12, 0xf9, 0x17, 0xc8, 0x52, 0x6f, 0xc8, 0x55, 0xe1, 0x95, + 0x9f, 0x71, 0xf5, 0xfd, 0xa5, 0x06, 0xc7, 0x12, 0x23, 0x0f, 0x32, 0xd7, 0x0d, 0x4a, 0x73, 0xc6, + 0xe8, 0xbd, 0x92, 0x23, 0xe4, 0x25, 0x09, 0x79, 0x91, 0x5c, 0xed, 0x07, 0xb2, 0x7a, 0x73, 0x8b, + 0xa4, 0x18, 0x8b, 0x1e, 0x46, 0x24, 0xad, 0x90, 0xb5, 0xbe, 0xc8, 0x73, 0xb3, 0xbd, 0x11, 0x23, + 0xc8, 0xcf, 0xf4, 0x99, 0x11, 0x82, 0x59, 0xde, 0xb8, 0x4f, 0x35, 0x38, 0xbb, 0xe6, 0x73, 0xc7, + 0xb5, 0xb8, 0xdd, 0xf6, 0xc0, 0x20, 0xd7, 0xd2, 0x40, 0x1c, 0xf2, 0x36, 0xcb, 0x2d, 0xf6, 0xc7, + 0x84, 0x16, 0xdc, 0x96, 0x16, 0xbc, 0x41, 0x6e, 0x74, 0xb6, 0x20, 0x71, 0x04, 0x11, 0x6d, 0x31, + 0x51, 0x67, 0xa2, 0x63, 0x28, 0x4c, 0xfa, 0x8b, 0x06, 0xb9, 0x43, 0x4c, 0xda, 0x0c, 0x38, 0xe9, + 0x03, 0x5e, 0xfc, 0x8c, 0x49, 0xcd, 0xf7, 0xc3, 0x5b, 0x7d, 0x5a, 0x92, 0x56, 0xdd, 0x24, 0xaf, + 0x7f, 0x02, 0xab, 0x58, 0xc0, 0x85, 0x59, 0x1f, 0x6b, 0x90, 0x4f, 0xef, 0x4a, 0xc9, 0xcd, 0xb4, + 0x62, 0xd8, 0x4b, 0xe7, 0x9c, 0x5b, 0xfe, 0x04, 0x12, 0xd0, 0xe4, 0x2d, 0x69, 0xf2, 0x06, 0xb9, + 0xdd, 0xd9, 0xe4, 0x4e, 0xed, 0xb2, 0x59, 0x75, 0xbc, 0x87, 0xe6, 0x83, 0x3a, 0x73, 0x4d, 0xd1, + 0x8a, 0x17, 0xdf, 0x4d, 0xf6, 0xe7, 0x4f, 0x56, 0x36, 0x3e, 0x7a, 0x96, 0xd7, 0x9e, 0x3e, 0xcb, + 0x6b, 0xff, 0x78, 0x96, 0xd7, 0xbe, 0xf3, 0x3c, 0x3f, 0xf4, 0xf4, 0x79, 0x7e, 0xe8, 0xaf, 0xcf, + 0xf3, 0x43, 0x5f, 0x9d, 0x4f, 0xbc, 0x25, 0x50, 0xdb, 0x5c, 0xd5, 0xda, 0xf6, 0x23, 0xd5, 0xef, + 0x2c, 0x5c, 0x2f, 0xee, 0x29, 0x00, 0xf2, 0x65, 0xb1, 0x3d, 0x22, 0xe7, 0x22, 0xd7, 0xfe, 0x13, + 0x00, 0x00, 0xff, 0xff, 0x50, 0x77, 0xa1, 0x93, 0xba, 0x1d, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -1679,6 +1786,9 @@ type QueryClient interface { EstimateSwapExactAmountIn(ctx context.Context, in *QuerySwapExactAmountInRequest, opts ...grpc.CallOption) (*QuerySwapExactAmountInResponse, error) // Deprecated: please use the alternative in x/poolmanager EstimateSwapExactAmountOut(ctx context.Context, in *QuerySwapExactAmountOutRequest, opts ...grpc.CallOption) (*QuerySwapExactAmountOutResponse, error) + // ConcentratedPoolIdLinkFromBalancer returns the pool id of the concentrated + // pool that is linked with the given CFMM pool. + ConcentratedPoolIdLinkFromCFMM(ctx context.Context, in *QueryConcentratedPoolIdLinkFromCFMMRequest, opts ...grpc.CallOption) (*QueryConcentratedPoolIdLinkFromCFMMResponse, error) } type queryClient struct { @@ -1829,6 +1939,15 @@ func (c *queryClient) EstimateSwapExactAmountOut(ctx context.Context, in *QueryS return out, nil } +func (c *queryClient) ConcentratedPoolIdLinkFromCFMM(ctx context.Context, in *QueryConcentratedPoolIdLinkFromCFMMRequest, opts ...grpc.CallOption) (*QueryConcentratedPoolIdLinkFromCFMMResponse, error) { + out := new(QueryConcentratedPoolIdLinkFromCFMMResponse) + err := c.cc.Invoke(ctx, "/osmosis.gamm.v1beta1.Query/ConcentratedPoolIdLinkFromCFMM", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // QueryServer is the server API for Query service. type QueryServer interface { Pools(context.Context, *QueryPoolsRequest) (*QueryPoolsResponse, error) @@ -1859,6 +1978,9 @@ type QueryServer interface { EstimateSwapExactAmountIn(context.Context, *QuerySwapExactAmountInRequest) (*QuerySwapExactAmountInResponse, error) // Deprecated: please use the alternative in x/poolmanager EstimateSwapExactAmountOut(context.Context, *QuerySwapExactAmountOutRequest) (*QuerySwapExactAmountOutResponse, error) + // ConcentratedPoolIdLinkFromBalancer returns the pool id of the concentrated + // pool that is linked with the given CFMM pool. + ConcentratedPoolIdLinkFromCFMM(context.Context, *QueryConcentratedPoolIdLinkFromCFMMRequest) (*QueryConcentratedPoolIdLinkFromCFMMResponse, error) } // UnimplementedQueryServer can be embedded to have forward compatible implementations. @@ -1910,6 +2032,9 @@ func (*UnimplementedQueryServer) EstimateSwapExactAmountIn(ctx context.Context, func (*UnimplementedQueryServer) EstimateSwapExactAmountOut(ctx context.Context, req *QuerySwapExactAmountOutRequest) (*QuerySwapExactAmountOutResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method EstimateSwapExactAmountOut not implemented") } +func (*UnimplementedQueryServer) ConcentratedPoolIdLinkFromCFMM(ctx context.Context, req *QueryConcentratedPoolIdLinkFromCFMMRequest) (*QueryConcentratedPoolIdLinkFromCFMMResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ConcentratedPoolIdLinkFromCFMM not implemented") +} func RegisterQueryServer(s grpc1.Server, srv QueryServer) { s.RegisterService(&_Query_serviceDesc, srv) @@ -2185,6 +2310,24 @@ func _Query_EstimateSwapExactAmountOut_Handler(srv interface{}, ctx context.Cont return interceptor(ctx, in, info, handler) } +func _Query_ConcentratedPoolIdLinkFromCFMM_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryConcentratedPoolIdLinkFromCFMMRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).ConcentratedPoolIdLinkFromCFMM(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/osmosis.gamm.v1beta1.Query/ConcentratedPoolIdLinkFromCFMM", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).ConcentratedPoolIdLinkFromCFMM(ctx, req.(*QueryConcentratedPoolIdLinkFromCFMMRequest)) + } + return interceptor(ctx, in, info, handler) +} + var _Query_serviceDesc = grpc.ServiceDesc{ ServiceName: "osmosis.gamm.v1beta1.Query", HandlerType: (*QueryServer)(nil), @@ -2249,6 +2392,10 @@ var _Query_serviceDesc = grpc.ServiceDesc{ MethodName: "EstimateSwapExactAmountOut", Handler: _Query_EstimateSwapExactAmountOut_Handler, }, + { + MethodName: "ConcentratedPoolIdLinkFromCFMM", + Handler: _Query_ConcentratedPoolIdLinkFromCFMM_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "osmosis/gamm/v1beta1/query.proto", @@ -3360,6 +3507,62 @@ func (m *QueryTotalLiquidityResponse) MarshalToSizedBuffer(dAtA []byte) (int, er return len(dAtA) - i, nil } +func (m *QueryConcentratedPoolIdLinkFromCFMMRequest) 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 *QueryConcentratedPoolIdLinkFromCFMMRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryConcentratedPoolIdLinkFromCFMMRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.CfmmPoolId != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.CfmmPoolId)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *QueryConcentratedPoolIdLinkFromCFMMResponse) 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 *QueryConcentratedPoolIdLinkFromCFMMResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryConcentratedPoolIdLinkFromCFMMResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.ConcentratedPoolId != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.ConcentratedPoolId)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + func encodeVarintQuery(dAtA []byte, offset int, v uint64) int { offset -= sovQuery(v) base := offset @@ -3819,6 +4022,30 @@ func (m *QueryTotalLiquidityResponse) Size() (n int) { return n } +func (m *QueryConcentratedPoolIdLinkFromCFMMRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.CfmmPoolId != 0 { + n += 1 + sovQuery(uint64(m.CfmmPoolId)) + } + return n +} + +func (m *QueryConcentratedPoolIdLinkFromCFMMResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.ConcentratedPoolId != 0 { + n += 1 + sovQuery(uint64(m.ConcentratedPoolId)) + } + return n +} + func sovQuery(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -6666,6 +6893,144 @@ func (m *QueryTotalLiquidityResponse) Unmarshal(dAtA []byte) error { } return nil } +func (m *QueryConcentratedPoolIdLinkFromCFMMRequest) 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 ErrIntOverflowQuery + } + 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: QueryConcentratedPoolIdLinkFromCFMMRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryConcentratedPoolIdLinkFromCFMMRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field CfmmPoolId", wireType) + } + m.CfmmPoolId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.CfmmPoolId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryConcentratedPoolIdLinkFromCFMMResponse) 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 ErrIntOverflowQuery + } + 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: QueryConcentratedPoolIdLinkFromCFMMResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryConcentratedPoolIdLinkFromCFMMResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ConcentratedPoolId", wireType) + } + m.ConcentratedPoolId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.ConcentratedPoolId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipQuery(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 diff --git a/x/gamm/types/query.pb.gw.go b/x/gamm/types/query.pb.gw.go index c1b4f7c7b20..1a44c3acda8 100644 --- a/x/gamm/types/query.pb.gw.go +++ b/x/gamm/types/query.pb.gw.go @@ -771,6 +771,60 @@ func local_request_Query_EstimateSwapExactAmountOut_0(ctx context.Context, marsh } +func request_Query_ConcentratedPoolIdLinkFromCFMM_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryConcentratedPoolIdLinkFromCFMMRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["cfmm_pool_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "cfmm_pool_id") + } + + protoReq.CfmmPoolId, err = runtime.Uint64(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "cfmm_pool_id", err) + } + + msg, err := client.ConcentratedPoolIdLinkFromCFMM(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_ConcentratedPoolIdLinkFromCFMM_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryConcentratedPoolIdLinkFromCFMMRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["cfmm_pool_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "cfmm_pool_id") + } + + protoReq.CfmmPoolId, err = runtime.Uint64(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "cfmm_pool_id", err) + } + + msg, err := server.ConcentratedPoolIdLinkFromCFMM(ctx, &protoReq) + return msg, metadata, err + +} + // RegisterQueryHandlerServer registers the http handlers for service Query to "mux". // UnaryRPC :call QueryServer directly. // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. @@ -1099,6 +1153,29 @@ func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv }) + mux.Handle("GET", pattern_Query_ConcentratedPoolIdLinkFromCFMM_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_ConcentratedPoolIdLinkFromCFMM_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_ConcentratedPoolIdLinkFromCFMM_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + return nil } @@ -1420,6 +1497,26 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie }) + mux.Handle("GET", pattern_Query_ConcentratedPoolIdLinkFromCFMM_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_ConcentratedPoolIdLinkFromCFMM_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_ConcentratedPoolIdLinkFromCFMM_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + return nil } @@ -1451,6 +1548,8 @@ var ( pattern_Query_EstimateSwapExactAmountIn_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3, 2, 4, 2, 5}, []string{"osmosis", "gamm", "v1beta1", "pool_id", "estimate", "swap_exact_amount_in"}, "", runtime.AssumeColonVerbOpt(false))) pattern_Query_EstimateSwapExactAmountOut_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3, 2, 4, 2, 5}, []string{"osmosis", "gamm", "v1beta1", "pool_id", "estimate", "swap_exact_amount_out"}, "", runtime.AssumeColonVerbOpt(false))) + + pattern_Query_ConcentratedPoolIdLinkFromCFMM_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"osmosis", "gamm", "v1beta1", "concentrated_pool_id_link_from_cfmm", "cfmm_pool_id"}, "", runtime.AssumeColonVerbOpt(false))) ) var ( @@ -1481,4 +1580,6 @@ var ( forward_Query_EstimateSwapExactAmountIn_0 = runtime.ForwardResponseMessage forward_Query_EstimateSwapExactAmountOut_0 = runtime.ForwardResponseMessage + + forward_Query_ConcentratedPoolIdLinkFromCFMM_0 = runtime.ForwardResponseMessage ) diff --git a/x/poolmanager/create_pool.go b/x/poolmanager/create_pool.go index 525b46ae0c2..0edba17e6ce 100644 --- a/x/poolmanager/create_pool.go +++ b/x/poolmanager/create_pool.go @@ -40,6 +40,18 @@ func (k Keeper) validateCreatedPool( // - Minting LP shares to pool creator // - Setting metadata for the shares func (k Keeper) CreatePool(ctx sdk.Context, msg types.CreatePoolMsg) (uint64, error) { + // Get pool type. + poolType := msg.GetPoolType() + poolModule, ok := k.routes[poolType] + if !ok { + return 0, types.InvalidPoolTypeError{PoolType: poolType} + } + + // Confirm that permissionless pool creation is enabled for the module. + if err := poolModule.ValidatePermissionlessPoolCreationEnabled(ctx); err != nil { + return 0, err + } + pool, err := k.createPoolZeroLiquidityNoCreationFee(ctx, msg) if err != nil { return 0, err diff --git a/x/poolmanager/create_pool_test.go b/x/poolmanager/create_pool_test.go index a7a310d62ea..a1842b6e4ce 100644 --- a/x/poolmanager/create_pool_test.go +++ b/x/poolmanager/create_pool_test.go @@ -117,62 +117,75 @@ func (suite *KeeperTestSuite) TestPoolCreationFee() { // TestCreatePool tests that all possible pools are created correctly. func (suite *KeeperTestSuite) TestCreatePool() { - validBalancerPoolMsg := balancer.NewMsgCreateBalancerPool(suite.TestAccs[0], balancer.NewPoolParams(sdk.ZeroDec(), sdk.ZeroDec(), nil), []balancer.PoolAsset{ - { - Token: sdk.NewCoin(foo, defaultInitPoolAmount), - Weight: sdk.NewInt(1), - }, - { - Token: sdk.NewCoin(bar, defaultInitPoolAmount), - Weight: sdk.NewInt(1), - }, - }, "") + var ( + validBalancerPoolMsg = balancer.NewMsgCreateBalancerPool(suite.TestAccs[0], balancer.NewPoolParams(sdk.ZeroDec(), sdk.ZeroDec(), nil), []balancer.PoolAsset{ + { + Token: sdk.NewCoin(foo, defaultInitPoolAmount), + Weight: sdk.NewInt(1), + }, + { + Token: sdk.NewCoin(bar, defaultInitPoolAmount), + Weight: sdk.NewInt(1), + }, + }, "") - invalidBalancerPoolMsg := balancer.NewMsgCreateBalancerPool(suite.TestAccs[0], balancer.NewPoolParams(sdk.ZeroDec(), sdk.NewDecWithPrec(1, 2), nil), []balancer.PoolAsset{ - { - Token: sdk.NewCoin(foo, defaultInitPoolAmount), - Weight: sdk.NewInt(1), - }, - { - Token: sdk.NewCoin(bar, defaultInitPoolAmount), - Weight: sdk.NewInt(1), - }, - }, "") + invalidBalancerPoolMsg = balancer.NewMsgCreateBalancerPool(suite.TestAccs[0], balancer.NewPoolParams(sdk.ZeroDec(), sdk.NewDecWithPrec(1, 2), nil), []balancer.PoolAsset{ + { + Token: sdk.NewCoin(foo, defaultInitPoolAmount), + Weight: sdk.NewInt(1), + }, + { + Token: sdk.NewCoin(bar, defaultInitPoolAmount), + Weight: sdk.NewInt(1), + }, + }, "") + + validConcentratedPoolMsg = clmodel.NewMsgCreateConcentratedPool(suite.TestAccs[0], foo, bar, 1, defaultPoolSwapFee) - validConcentratedPoolMsg := clmodel.NewMsgCreateConcentratedPool(suite.TestAccs[0], foo, bar, 1, defaultPoolSwapFee) + defaultFundAmount = sdk.NewCoins(sdk.NewCoin(foo, defaultInitPoolAmount.Mul(sdk.NewInt(2))), sdk.NewCoin(bar, defaultInitPoolAmount.Mul(sdk.NewInt(2)))) + ) tests := []struct { - name string - creatorFundAmount sdk.Coins - msg types.CreatePoolMsg - expectedModuleType reflect.Type - expectError bool + name string + creatorFundAmount sdk.Coins + isPermissionlessPoolCreationDisabled bool + msg types.CreatePoolMsg + expectedModuleType reflect.Type + expectError bool }{ { name: "first balancer pool - success", - creatorFundAmount: sdk.NewCoins(sdk.NewCoin(foo, defaultInitPoolAmount.Mul(sdk.NewInt(2))), sdk.NewCoin(bar, defaultInitPoolAmount.Mul(sdk.NewInt(2)))), + creatorFundAmount: defaultFundAmount, msg: validBalancerPoolMsg, expectedModuleType: gammKeeperType, }, { name: "second balancer pool - success", - creatorFundAmount: sdk.NewCoins(sdk.NewCoin(foo, defaultInitPoolAmount.Mul(sdk.NewInt(2))), sdk.NewCoin(bar, defaultInitPoolAmount.Mul(sdk.NewInt(2)))), + creatorFundAmount: defaultFundAmount, msg: validBalancerPoolMsg, expectedModuleType: gammKeeperType, }, { name: "concentrated pool - success", - creatorFundAmount: sdk.NewCoins(sdk.NewCoin(foo, defaultInitPoolAmount.Mul(sdk.NewInt(2))), sdk.NewCoin(bar, defaultInitPoolAmount.Mul(sdk.NewInt(2)))), + creatorFundAmount: defaultFundAmount, msg: validConcentratedPoolMsg, expectedModuleType: concentratedKeeperType, }, { - name: "pool with non zero exit fee - error", - creatorFundAmount: sdk.NewCoins(sdk.NewCoin(foo, defaultInitPoolAmount.Mul(sdk.NewInt(2))), sdk.NewCoin(bar, defaultInitPoolAmount.Mul(sdk.NewInt(2)))), + name: "error: pool with non zero exit fee", + creatorFundAmount: defaultFundAmount, msg: invalidBalancerPoolMsg, expectedModuleType: gammKeeperType, expectError: true, }, + { + name: "error: pool creation is disabled for concentrated pool via param", + creatorFundAmount: defaultFundAmount, + isPermissionlessPoolCreationDisabled: true, + msg: validConcentratedPoolMsg, + expectedModuleType: concentratedKeeperType, + expectError: true, + }, // TODO: add stableswap test // TODO: add concentrated-liquidity test // TODO: cover errors and edge cases @@ -182,6 +195,12 @@ func (suite *KeeperTestSuite) TestCreatePool() { suite.Run(tc.name, func() { tc := tc + if tc.isPermissionlessPoolCreationDisabled { + params := suite.App.ConcentratedLiquidityKeeper.GetParams(suite.Ctx) + params.IsPermissionlessPoolCreationEnabled = false + suite.App.ConcentratedLiquidityKeeper.SetParams(suite.Ctx, params) + } + poolmanagerKeeper := suite.App.PoolManagerKeeper ctx := suite.Ctx diff --git a/x/poolmanager/types/routes.go b/x/poolmanager/types/routes.go index 54b98065de2..d7163a19432 100644 --- a/x/poolmanager/types/routes.go +++ b/x/poolmanager/types/routes.go @@ -87,6 +87,10 @@ type PoolModuleI interface { // GetTotalPoolLiquidity returns the coins in the pool owned by all LPs GetTotalPoolLiquidity(ctx sdk.Context, poolId uint64) (sdk.Coins, error) + + // ValidatePermissionlessPoolCreationEnabled returns nil if permissionless pool creation in the module is enabled. + // Otherwise, returns an error. + ValidatePermissionlessPoolCreationEnabled(ctx sdk.Context) error } type PoolIncentivesKeeperI interface {