From 4c65a87ef8f135cb9938bec671d140b0057caf98 Mon Sep 17 00:00:00 2001 From: Roman Akhtariev Date: Thu, 8 Jun 2023 01:31:30 +0000 Subject: [PATCH] external incentives --- proto/osmosis/incentives/tx.proto | 5 + proto/osmosis/lockup/lock.proto | 1 + .../msg/transmuter/transmuter_test.go | 2 +- x/incentives/keeper/bench_test.go | 2 +- x/incentives/keeper/distribute.go | 190 +++++----- x/incentives/keeper/distribute_test.go | 330 +++++++----------- x/incentives/keeper/export_test.go | 6 - x/incentives/keeper/gauge.go | 39 ++- x/incentives/keeper/gauge_test.go | 114 +++++- x/incentives/keeper/genesis_test.go | 2 +- x/incentives/keeper/msg_server.go | 2 +- x/incentives/keeper/suite_test.go | 2 +- x/incentives/types/msgs.go | 13 +- x/incentives/types/msgs_test.go | 39 ++- x/incentives/types/tx.pb.go | 121 ++++--- x/lockup/types/lock.pb.go | 86 ++--- x/pool-incentives/keeper/grpc_query_test.go | 6 +- x/pool-incentives/keeper/keeper.go | 16 +- x/pool-incentives/types/expected_keepers.go | 2 +- x/superfluid/keeper/intermediary_account.go | 2 +- x/superfluid/types/expected_keepers.go | 2 +- 21 files changed, 547 insertions(+), 435 deletions(-) diff --git a/proto/osmosis/incentives/tx.proto b/proto/osmosis/incentives/tx.proto index f4652ac7633..98f76bbc3a7 100644 --- a/proto/osmosis/incentives/tx.proto +++ b/proto/osmosis/incentives/tx.proto @@ -45,6 +45,11 @@ message MsgCreateGauge { // num_epochs_paid_over is the number of epochs distribution will be completed // over uint64 num_epochs_paid_over = 6; + + // pool_id is the ID of the pool that the gauge is meant to be associated + // with. if pool_id is set, then the "QueryCondition.LockQueryType" must be + // "NoLock" with all other fields unset. + uint64 pool_id = 7; } message MsgCreateGaugeResponse {} diff --git a/proto/osmosis/lockup/lock.proto b/proto/osmosis/lockup/lock.proto index 879dcfdd68d..322428288e0 100644 --- a/proto/osmosis/lockup/lock.proto +++ b/proto/osmosis/lockup/lock.proto @@ -56,6 +56,7 @@ enum LockQueryType { ByDuration = 0; ByTime = 1; + NoLock = 2; } // QueryCondition is a struct used for querying locks upon different conditions. diff --git a/x/cosmwasmpool/cosmwasm/msg/transmuter/transmuter_test.go b/x/cosmwasmpool/cosmwasm/msg/transmuter/transmuter_test.go index 6bf7b219a9b..b1f17c47016 100644 --- a/x/cosmwasmpool/cosmwasm/msg/transmuter/transmuter_test.go +++ b/x/cosmwasmpool/cosmwasm/msg/transmuter/transmuter_test.go @@ -86,7 +86,7 @@ func (s *TransmuterSuite) TestFunctionalTransmuter() { LockQueryType: lockuptypes.ByDuration, Denom: expectedShareDenom, Duration: lockDuration, - }, s.Ctx.BlockTime(), 1) + }, s.Ctx.BlockTime(), 1, 0) s.Require().NoError(err) gauge, err := s.App.IncentivesKeeper.GetGaugeByID(s.Ctx, gaugeId) s.Require().NoError(err) diff --git a/x/incentives/keeper/bench_test.go b/x/incentives/keeper/bench_test.go index c1f059fe25d..a234326f391 100644 --- a/x/incentives/keeper/bench_test.go +++ b/x/incentives/keeper/bench_test.go @@ -114,7 +114,7 @@ func benchmarkDistributionLogic(b *testing.B, numAccts, numDenoms, numGauges, nu numEpochsPaidOver = uint64(r.Int63n(durationMillisecs/millisecsPerEpoch)) + 1 } - gaugeId, err := app.IncentivesKeeper.CreateGauge(ctx, isPerpetual, addr, rewards, distributeTo, startTime, numEpochsPaidOver) + gaugeId, err := app.IncentivesKeeper.CreateGauge(ctx, isPerpetual, addr, rewards, distributeTo, startTime, numEpochsPaidOver, 0) if err != nil { fmt.Printf("Create Gauge, %v\n", err) b.FailNow() diff --git a/x/incentives/keeper/distribute.go b/x/incentives/keeper/distribute.go index 95108fe6a17..45c758e13e1 100644 --- a/x/incentives/keeper/distribute.go +++ b/x/incentives/keeper/distribute.go @@ -1,7 +1,6 @@ package keeper import ( - "errors" "fmt" "time" @@ -11,7 +10,6 @@ import ( "github.com/osmosis-labs/osmosis/v16/x/incentives/types" lockuptypes "github.com/osmosis-labs/osmosis/v16/x/lockup/types" - poolincentivestypes "github.com/osmosis-labs/osmosis/v16/x/pool-incentives/types" poolmanagertypes "github.com/osmosis-labs/osmosis/v16/x/poolmanager/types" ) @@ -268,29 +266,6 @@ func (k Keeper) distributeSyntheticInternal( return k.distributeInternal(ctx, gauge, sortedAndTrimmedQualifiedLocks, distrInfo) } -// distributeConcentratedLiquidity runs the distribution logic for CL pools only. It creates new incentive record with osmo incentives -// and distributes all the tokens to the dedicated pool -func (k Keeper) distributeConcentratedLiquidity(ctx sdk.Context, poolId uint64, sender sdk.AccAddress, incentiveCoin sdk.Coin, emissionRate sdk.Dec, startTime time.Time, minUptime time.Duration, gauge types.Gauge) error { - _, err := k.clk.CreateIncentive(ctx, - poolId, - sender, - incentiveCoin, - emissionRate, - startTime, - minUptime, - ) - if err != nil { - return err - } - - // updateGaugePostDistribute adds the coins that were just distributed to the gauge's distributed coins field. - err = k.updateGaugePostDistribute(ctx, gauge, sdk.NewCoins(incentiveCoin)) - if err != nil { - return err - } - return nil -} - // distributeInternal runs the distribution logic for a gauge, and adds the sends to // the distrInfo struct. It also updates the gauge for the distribution. // Locks is expected to be the correct set of lock recipients for this gauge. @@ -298,12 +273,6 @@ func (k Keeper) distributeInternal( ctx sdk.Context, gauge types.Gauge, locks []lockuptypes.PeriodLock, distrInfo *distributionInfo, ) (sdk.Coins, error) { totalDistrCoins := sdk.NewCoins() - denom := lockuptypes.NativeDenom(gauge.DistributeTo.Denom) - lockSum := lockuptypes.SumLocksByDenom(locks, denom) - - if lockSum.IsZero() { - return nil, nil - } remainCoins := gauge.Coins.Sub(gauge.DistributedCoins) // if its a perpetual gauge, we set remaining epochs to 1. @@ -313,34 +282,90 @@ func (k Keeper) distributeInternal( remainEpochs = gauge.NumEpochsPaidOver - gauge.FilledEpochs } - for _, lock := range locks { - distrCoins := sdk.Coins{} - for _, coin := range remainCoins { - // distribution amount = gauge_size * denom_lock_amount / (total_denom_lock_amount * remain_epochs) - denomLockAmt := lock.Coins.AmountOfNoDenomValidation(denom) - amt := coin.Amount.Mul(denomLockAmt).Quo(lockSum.Mul(sdk.NewInt(int64(remainEpochs)))) - if amt.IsPositive() { - newlyDistributedCoin := sdk.Coin{Denom: coin.Denom, Amount: amt} - distrCoins = distrCoins.Add(newlyDistributedCoin) - } + // This is a no lock distribution flow that assumes that we have a pool associated with the gauge. + // Currently, this flow is only used for CL pools. Fails if the pool is not found. + // Fails if the pool found is not a CL pool. + if gauge.DistributeTo.LockQueryType == lockuptypes.NoLock { + pool, err := k.GetPoolFromGaugeId(ctx, gauge.Id, gauge.DistributeTo.Duration) + + if err != nil { + return nil, err } - distrCoins = distrCoins.Sort() - if distrCoins.Empty() { - continue + + poolType := pool.GetType() + if poolType != poolmanagertypes.Concentrated { + return nil, fmt.Errorf("pool type %s is not supported for no lock distribution", poolType) } - // update the amount for that address - rewardReceiver := lock.RewardReceiverAddress - // if the reward receiver stored in state is an empty string, it indicates that the owner is the reward receiver. - if rewardReceiver == "" { - rewardReceiver = lock.Owner + // Get distribution epoch duration. This is used to calculate the emission rate. + currentEpoch := k.GetEpochInfo(ctx) + + // only want to run this logic if the gaugeId is associated with CL PoolId + for _, remainCoin := range remainCoins { + remainAmountPerEpoch := remainCoin.Amount.Quo(sdk.NewIntFromUint64(remainEpochs)) + remainCoinPerEpoch := sdk.NewCoin(remainCoin.Denom, remainAmountPerEpoch) + + // emissionRate calculates amount of tokens to emit per second + // for ex: 10000tokens to be distributed over 1day epoch will be 1000 tokens ÷ 86,400 seconds ≈ 0.01157 tokens per second (truncated) + // Note: reason why we do millisecond conversion is because floats are non-deterministic so if someone refactors this and accidentally + // uses the return of currEpoch.Duration.Seconds() in math operations, this will lead to an app hash. + emissionRate := sdk.NewDecFromInt(remainAmountPerEpoch).QuoTruncate(sdk.NewDec(currentEpoch.Duration.Milliseconds()).QuoInt(sdk.NewInt(1000))) + + _, err := k.clk.CreateIncentive(ctx, + pool.GetId(), + k.ak.GetModuleAddress(types.ModuleName), + remainCoinPerEpoch, + emissionRate, + gauge.GetStartTime(), + // Note that the minimum uptime does not affect the distribution of incentives from the gauge and + // thus can be any value authorized by the CL module. + types.DefaultConcentratedUptime, + ) + if err != nil { + return nil, err + } + + totalDistrCoins = totalDistrCoins.Add(remainCoinPerEpoch) } - err := distrInfo.addLockRewards(lock.Owner, rewardReceiver, distrCoins) - if err != nil { - return nil, err + + } else { + // This is a standard lock distribution flow that assumes that we have locks associated with the gauge. + denom := lockuptypes.NativeDenom(gauge.DistributeTo.Denom) + lockSum := lockuptypes.SumLocksByDenom(locks, denom) + + if lockSum.IsZero() { + return nil, nil } - totalDistrCoins = totalDistrCoins.Add(distrCoins...) + for _, lock := range locks { + distrCoins := sdk.Coins{} + for _, coin := range remainCoins { + // distribution amount = gauge_size * denom_lock_amount / (total_denom_lock_amount * remain_epochs) + denomLockAmt := lock.Coins.AmountOfNoDenomValidation(denom) + amt := coin.Amount.Mul(denomLockAmt).Quo(lockSum.Mul(sdk.NewInt(int64(remainEpochs)))) + if amt.IsPositive() { + newlyDistributedCoin := sdk.Coin{Denom: coin.Denom, Amount: amt} + distrCoins = distrCoins.Add(newlyDistributedCoin) + } + } + distrCoins = distrCoins.Sort() + if distrCoins.Empty() { + continue + } + // update the amount for that address + rewardReceiver := lock.RewardReceiverAddress + + // if the reward receiver stored in state is an empty string, it indicates that the owner is the reward receiver. + if rewardReceiver == "" { + rewardReceiver = lock.Owner + } + err := distrInfo.addLockRewards(lock.Owner, rewardReceiver, distrCoins) + if err != nil { + return nil, err + } + + totalDistrCoins = totalDistrCoins.Add(distrCoins...) + } } err := k.updateGaugePostDistribute(ctx, gauge, totalDistrCoins) @@ -384,59 +409,20 @@ func (k Keeper) Distribute(ctx sdk.Context, gauges []types.Gauge) (sdk.Coins, er locksByDenomCache := make(map[string][]lockuptypes.PeriodLock) totalDistributedCoins := sdk.NewCoins() - // get pool Id corresponding to the gaugeId - incentiveParams := k.GetParams(ctx).DistrEpochIdentifier - currentEpoch := k.ek.GetEpochInfo(ctx, incentiveParams) - for _, gauge := range gauges { var gaugeDistributedCoins sdk.Coins - pool, err := k.GetPoolFromGaugeId(ctx, gauge.Id, currentEpoch.Duration) - // Note: getting NoPoolAssociatedWithGaugeError implies that there is no pool associated with the gauge but we still want to distribute. - // This happens with superfluid gauges which are not connected to any specific pool directly but, instead, - // via an intermediary account. - if err != nil && !errors.Is(err, poolincentivestypes.NoPoolAssociatedWithGaugeError{GaugeId: gauge.Id, Duration: currentEpoch.Duration}) { - // TODO: add test case to cover this - return nil, err - } else if pool != nil && pool.GetType() == poolmanagertypes.Concentrated { - // only want to run this logic if the gaugeId is associated with CL PoolId - for _, coin := range gauge.Coins { - // emissionRate calculates amount of tokens to emit per second - // for ex: 10000tokens to be distributed over 1day epoch will be 1000 tokens ÷ 86,400 seconds ≈ 0.01157 tokens per second (truncated) - // Note: reason why we do millisecond conversion is because floats are non-deterministic so if someone refactors this and accidentally - // uses the return of currEpoch.Duration.Seconds() in math operations, this will lead to an app hash. - emissionRate := sdk.NewDecFromInt(coin.Amount).QuoTruncate(sdk.NewDec(currentEpoch.Duration.Milliseconds()).QuoInt(sdk.NewInt(1000))) - err := k.distributeConcentratedLiquidity(ctx, - pool.GetId(), - k.ak.GetModuleAddress(types.ModuleName), - coin, - emissionRate, - gauge.GetStartTime(), - // Note that the minimum uptime does not affect the distribution of incentives from the gauge and - // thus can be any value authorized by the CL module. - types.DefaultConcentratedUptime, - gauge, - ) - if err != nil { - return nil, err - } - gaugeDistributedCoins = gaugeDistributedCoins.Add(coin) - } + filteredLocks := k.getDistributeToBaseLocks(ctx, gauge, locksByDenomCache) + // send based on synthetic lockup coins if it's distributing to synthetic lockups + var err error + if lockuptypes.IsSyntheticDenom(gauge.DistributeTo.Denom) { + gaugeDistributedCoins, err = k.distributeSyntheticInternal(ctx, gauge, filteredLocks, &distrInfo) } else { - // Assume that there is no pool associated with the gauge and attempt to distribute to base locks - filteredLocks := k.getDistributeToBaseLocks(ctx, gauge, locksByDenomCache) - // send based on synthetic lockup coins if it's distributing to synthetic lockups - var err error - if lockuptypes.IsSyntheticDenom(gauge.DistributeTo.Denom) { - // TODO: add test case to cover this - gaugeDistributedCoins, err = k.distributeSyntheticInternal(ctx, gauge, filteredLocks, &distrInfo) - } else { - gaugeDistributedCoins, err = k.distributeInternal(ctx, gauge, filteredLocks, &distrInfo) - } - if err != nil { - // TODO: add test case to cover this - return nil, err - } + gaugeDistributedCoins, err = k.distributeInternal(ctx, gauge, filteredLocks, &distrInfo) + } + if err != nil { + return nil, err } + totalDistributedCoins = totalDistributedCoins.Add(gaugeDistributedCoins...) } diff --git a/x/incentives/keeper/distribute_test.go b/x/incentives/keeper/distribute_test.go index aaade1b54ef..786f7ce8302 100644 --- a/x/incentives/keeper/distribute_test.go +++ b/x/incentives/keeper/distribute_test.go @@ -8,7 +8,6 @@ import ( "github.com/stretchr/testify/suite" appParams "github.com/osmosis-labs/osmosis/v16/app/params" - cltypes "github.com/osmosis-labs/osmosis/v16/x/concentrated-liquidity/types" "github.com/osmosis-labs/osmosis/v16/x/incentives/types" lockuptypes "github.com/osmosis-labs/osmosis/v16/x/lockup/types" poolmanagertypes "github.com/osmosis-labs/osmosis/v16/x/poolmanager/types" @@ -166,7 +165,7 @@ func (s *KeeperTestSuite) TestDistribute() { } } -func (s *KeeperTestSuite) TestDistributeToConcentratedLiquidityPools() { +func (s *KeeperTestSuite) TestDistribute_InternalIncentives_ConcentratedPool() { defaultGauge := perpGaugeDesc{ lockDenom: defaultLPDenom, lockDuration: defaultLockDuration, @@ -189,9 +188,8 @@ func (s *KeeperTestSuite) TestDistributeToConcentratedLiquidityPools() { tokensToAddToGauge sdk.Coins gaugeStartTime time.Time gaugeCoins sdk.Coins - poolType poolmanagertypes.PoolType lockExist bool - authorizedUptimes []time.Duration + isBalancerPool bool // expected expectErr bool @@ -200,73 +198,36 @@ func (s *KeeperTestSuite) TestDistributeToConcentratedLiquidityPools() { "valid case: one poolId and gaugeId": { numPools: 1, gaugeStartTime: defaultGaugeStartTime, - poolType: poolmanagertypes.Concentrated, - gaugeCoins: sdk.NewCoins(sdk.NewCoin(defaultRewardDenom, sdk.NewInt(5000))), - authorizedUptimes: cltypes.SupportedUptimes, + gaugeCoins: sdk.NewCoins(fiveKRewardCoins), expectedDistributions: sdk.NewCoins(fiveKRewardCoins), expectErr: false, }, "valid case: gauge with multiple coins": { numPools: 1, gaugeStartTime: defaultGaugeStartTime, - poolType: poolmanagertypes.Concentrated, - gaugeCoins: sdk.NewCoins(sdk.NewCoin(defaultRewardDenom, sdk.NewInt(5000)), sdk.NewCoin(appParams.BaseCoinUnit, sdk.NewInt(5000))), - authorizedUptimes: cltypes.SupportedUptimes, + gaugeCoins: sdk.NewCoins(fiveKRewardCoins, fiveKRewardCoinsUosmo), expectedDistributions: sdk.NewCoins(fiveKRewardCoins, fiveKRewardCoinsUosmo), expectErr: false, }, "valid case: multiple gaugeId and poolId": { numPools: 3, gaugeStartTime: defaultGaugeStartTime, - poolType: poolmanagertypes.Concentrated, - gaugeCoins: sdk.NewCoins(sdk.NewCoin(defaultRewardDenom, sdk.NewInt(5000))), - authorizedUptimes: cltypes.SupportedUptimes, + gaugeCoins: sdk.NewCoins(fiveKRewardCoins), expectedDistributions: sdk.NewCoins(fifteenKRewardCoins), expectErr: false, }, - "valid case: attempt to create balancer pool": { + "valid case: one poolId and gaugeId, five 5000 coins": { numPools: 1, - poolType: poolmanagertypes.Balancer, - gaugeCoins: sdk.NewCoins(sdk.NewCoin(defaultRewardDenom, sdk.NewInt(5000))), gaugeStartTime: defaultGaugeStartTime, - authorizedUptimes: cltypes.SupportedUptimes, - expectedDistributions: sdk.NewCoins(), - expectErr: false, // still a valid case we just donot update the CL incentive parameters - }, - "valid case: distributing to locks since no pool associated with gauge": { - numPools: 0, - poolType: poolmanagertypes.Balancer, - gaugeCoins: sdk.NewCoins(), - gaugeStartTime: defaultGaugeStartTime, - authorizedUptimes: cltypes.SupportedUptimes, - expectedDistributions: sdk.NewCoins(sdk.NewCoin(defaultRewardDenom, sdk.NewInt(3000))), - lockExist: true, - expectErr: false, // we do not expect error because we run the gauge distribution to lock logic - }, - "valid case: one poolId and gaugeId, limited authorized uptimes": { - numPools: 1, - gaugeStartTime: defaultGaugeStartTime, - poolType: poolmanagertypes.Concentrated, - gaugeCoins: sdk.NewCoins(sdk.NewCoin(defaultRewardDenom, sdk.NewInt(5000))), - authorizedUptimes: []time.Duration{time.Nanosecond, time.Hour * 24}, - expectedDistributions: sdk.NewCoins(fiveKRewardCoins), - expectErr: false, - }, - "valid case: one poolId and gaugeId, default authorized uptimes (1ns)": { - numPools: 1, - gaugeStartTime: defaultGaugeStartTime, - poolType: poolmanagertypes.Concentrated, - gaugeCoins: sdk.NewCoins(sdk.NewCoin(defaultRewardDenom, sdk.NewInt(5000))), + gaugeCoins: sdk.NewCoins(fiveKRewardCoins), expectedDistributions: sdk.NewCoins(fiveKRewardCoins), expectErr: false, }, - "invalid case: attempt to createIncentiveRecord with starttime < currentBlockTime": { - numPools: 1, - poolType: poolmanagertypes.Concentrated, - gaugeCoins: sdk.NewCoins(sdk.NewCoin(defaultRewardDenom, sdk.NewInt(5000))), - gaugeStartTime: defaultGaugeStartTime.Add(-5 * time.Hour), - authorizedUptimes: cltypes.SupportedUptimes, - expectErr: true, + "invalid case: attempt to createIncentiveRecord with start time < currentBlockTime": { + numPools: 1, + gaugeCoins: sdk.NewCoins(sdk.NewCoin(defaultRewardDenom, sdk.NewInt(5000))), + gaugeStartTime: defaultGaugeStartTime.Add(-5 * time.Hour), + expectErr: true, }, } @@ -277,13 +238,6 @@ func (s *KeeperTestSuite) TestDistributeToConcentratedLiquidityPools() { // We fix blocktime to ensure tests are deterministic s.Ctx = s.Ctx.WithBlockTime(defaultGaugeStartTime) - // Set up authorized CL uptimes to robustly test distribution - if tc.authorizedUptimes != nil { - clParams := s.App.ConcentratedLiquidityKeeper.GetParams(s.Ctx) - clParams.AuthorizedUptimes = tc.authorizedUptimes - s.App.ConcentratedLiquidityKeeper.SetParams(s.Ctx, clParams) - } - var gauges []types.Gauge // prepare the minting account @@ -295,24 +249,32 @@ func (s *KeeperTestSuite) TestDistributeToConcentratedLiquidityPools() { err := s.App.BankKeeper.SendCoinsFromAccountToModule(s.Ctx, addr, types.ModuleName, coinsToMint) s.Require().NoError(err) - var poolId uint64 - // prepare a CL Pool that creates gauge at the end of createPool - if tc.poolType == poolmanagertypes.Concentrated { - for i := 0; i < tc.numPools; i++ { + for i := 0; i < tc.numPools; i++ { + var ( + poolId uint64 + duration time.Duration + ) + if tc.isBalancerPool { + poolId = s.PrepareBalancerPool() + + duration = s.App.PoolIncentivesKeeper.GetLockableDurations(s.Ctx)[0] + } else { poolId = s.PrepareConcentratedPool().GetId() - // get the gaugeId corresponding to the CL pool - gaugeId, err := s.App.PoolIncentivesKeeper.GetPoolGaugeId(s.Ctx, poolId, currentEpoch.Duration) - s.Require().NoError(err) + duration = currentEpoch.Duration + } - // get the gauge from the gaudeId - gauge, err := s.App.IncentivesKeeper.GetGaugeByID(s.Ctx, gaugeId) - s.Require().NoError(err) + // get the gaugeId corresponding to the CL pool + gaugeId, err := s.App.PoolIncentivesKeeper.GetPoolGaugeId(s.Ctx, poolId, duration) + s.Require().NoError(err) - gauge.Coins = tc.gaugeCoins - gauge.StartTime = tc.gaugeStartTime - gauges = append(gauges, *gauge) - } + // get the gauge from the gaudeId + gauge, err := s.App.IncentivesKeeper.GetGaugeByID(s.Ctx, gaugeId) + s.Require().NoError(err) + + gauge.Coins = tc.gaugeCoins + gauge.StartTime = tc.gaugeStartTime + gauges = append(gauges, *gauge) } var addrs []sdk.AccAddress @@ -346,7 +308,7 @@ func (s *KeeperTestSuite) TestDistributeToConcentratedLiquidityPools() { s.Require().NoError(err) // this check is specifically for CL pool gauges, because we donot create pools other than CL - if tc.poolType == poolmanagertypes.Concentrated { + if tc.isBalancerPool { // check that gauge is not empty s.Require().NotEqual(len(gauges), 0) @@ -394,6 +356,89 @@ func (s *KeeperTestSuite) TestDistributeToConcentratedLiquidityPools() { } } +// TestDistribute_ExternalIncentives_ConcentratedPool tests the distribution of external incentives +// to concentrated liquidity pools. It creates an external gauge with the correct configuration +// and uses it to attempt to distribute tokens to a concentrated liquidity pool. +func (s *KeeperTestSuite) TestDistribute_ExternalIncentives_ConcentratedPool() { + + const ( + defaultCLPool = uint64(1) + defaultBalancerPool = uint64(2) + ) + + fiveKRewardCoins := sdk.NewInt64Coin(defaultRewardDenom, 5000) + defauBlockTime := time.Unix(123456789, 0) + oneHourAfterDefault := defauBlockTime.Add(time.Hour) + + tests := map[string]struct { + // setup + numPools int + tokensToAddToGauge sdk.Coins + gaugeStartTime time.Time + gaugeCoins sdk.Coins + distrTo lockuptypes.QueryCondition + startTime time.Time + numEpochsPaidOver uint64 + poolId uint64 + + isBalancerPool bool + + // expected + expectErr bool + expectedDistributions sdk.Coins + }{ + "valid case: one poolId and gaugeId": { + gaugeStartTime: defauBlockTime, + gaugeCoins: sdk.NewCoins(fiveKRewardCoins), + distrTo: lockuptypes.QueryCondition{LockQueryType: lockuptypes.NoLock}, + startTime: oneHourAfterDefault, + expectedDistributions: sdk.NewCoins(fiveKRewardCoins), + numEpochsPaidOver: 1, + poolId: defaultCLPool, + expectErr: false, + }, + } + + for name, tc := range tests { + s.Run(name, func() { + // setup test + s.SetupTest() + + // We fix blocktime to ensure tests are deterministic + s.Ctx = s.Ctx.WithBlockTime(defauBlockTime) + + // Create CL and Balancer pools + s.PrepareConcentratedPool() + s.PrepareBalancerPool() + + s.Ctx = s.Ctx.WithBlockTime(oneHourAfterDefault) + + s.FundAcc(s.TestAccs[0], tc.gaugeCoins) + + isPerpetual := false + externalGaugeid, err := s.App.IncentivesKeeper.CreateGauge(s.Ctx, isPerpetual, s.TestAccs[0], tc.gaugeCoins, tc.distrTo, tc.startTime, tc.numEpochsPaidOver, tc.poolId) + s.Require().NoError(err) + + externalGauge, err := s.App.IncentivesKeeper.GetGaugeByID(s.Ctx, externalGaugeid) + s.Require().NoError(err) + + gauges := []types.Gauge{*externalGauge} + + // Distribute tokens from the gauge + totalDistributedCoins, err := s.App.IncentivesKeeper.Distribute(s.Ctx, gauges) + + if tc.expectErr { + s.Require().Error(err) + } else { + s.Require().NoError(err) + + // check the totalAmount of tokens distributed, for both lock gauges and CL pool gauges + s.Require().Equal(tc.expectedDistributions, totalDistributedCoins) + } + }) + } +} + // TestSyntheticDistribute tests that when the distribute command is executed on a provided gauge // the correct amount of rewards is sent to the correct synthetic lock owners. func (s *KeeperTestSuite) TestSyntheticDistribute() { @@ -737,142 +782,3 @@ func (s *KeeperTestSuite) TestGetPoolFromGaugeId() { }) } } - -func (s *KeeperTestSuite) TestDistributeConcentratedLiquidity() { - var ( - timeBeforeBlock = time.Unix(0, 0) - defaultBlockTime = timeBeforeBlock.Add(10 * time.Second) - defaultAmountCoin = sdk.Coins{sdk.NewInt64Coin(defaultRewardDenom, 3000)} - defaultGauge = perpGaugeDesc{ - lockDenom: defaultLPDenom, - lockDuration: defaultLockDuration, - rewardAmount: defaultAmountCoin, - } - withLength = func(gauge perpGaugeDesc, length time.Duration) perpGaugeDesc { - gauge.lockDuration = length - return gauge - } - withAmount = func(gauge perpGaugeDesc, amount sdk.Coins) perpGaugeDesc { - gauge.rewardAmount = amount - return gauge - } - ) - - type distributeConcentratedLiquidityInternalTestCase struct { - name string - poolId uint64 - sender sdk.AccAddress - incentiveDenom string - incentiveAmount sdk.Int - emissionRate sdk.Dec - startTime time.Time - minUptime time.Duration - expectedCoins sdk.Coins - gauge perpGaugeDesc - authorizedUptimes []time.Duration - expectedError bool - } - - testCases := []distributeConcentratedLiquidityInternalTestCase{ - { - name: "valid: valid incentive record with valid gauge", - poolId: 1, - sender: s.TestAccs[0], - incentiveDenom: defaultRewardDenom, - incentiveAmount: sdk.NewInt(100), - emissionRate: sdk.NewDec(1), - startTime: defaultBlockTime, - minUptime: time.Hour * 24, - gauge: defaultGauge, - authorizedUptimes: []time.Duration{time.Hour * 24}, - - expectedCoins: sdk.NewCoins(sdk.NewCoin(defaultRewardDenom, sdk.NewInt(100))), - }, - { - name: "valid: valid incentive record with valid gauge (default authorized uptimes)", - poolId: 1, - sender: s.TestAccs[0], - incentiveDenom: defaultRewardDenom, - incentiveAmount: sdk.NewInt(100), - emissionRate: sdk.NewDec(1), - startTime: defaultBlockTime, - minUptime: time.Nanosecond, - gauge: defaultGauge, - - expectedCoins: sdk.NewCoins(sdk.NewCoin(defaultRewardDenom, sdk.NewInt(100))), - }, - { - name: "valid: valid incentive with double length record with valid gauge", - poolId: 1, - sender: s.TestAccs[0], - incentiveDenom: defaultRewardDenom, - incentiveAmount: sdk.NewInt(100), - emissionRate: sdk.NewDec(1), - startTime: defaultBlockTime, - minUptime: time.Hour * 24, - gauge: withLength(defaultGauge, defaultGauge.lockDuration*2), - authorizedUptimes: []time.Duration{time.Hour * 24}, - - expectedCoins: sdk.NewCoins(sdk.NewCoin(defaultRewardDenom, sdk.NewInt(100))), - }, - { - name: "valid: valid incentive with double amount record and valid gauge", - poolId: 1, - sender: s.TestAccs[0], - incentiveDenom: defaultRewardDenom, - incentiveAmount: sdk.NewInt(100), - emissionRate: sdk.NewDec(1), - startTime: defaultBlockTime, - minUptime: time.Hour * 24, - gauge: withAmount(defaultGauge, defaultAmountCoin.Add(defaultAmountCoin...)), - authorizedUptimes: []time.Duration{time.Hour * 24}, - - expectedCoins: sdk.NewCoins(sdk.NewCoin(defaultRewardDenom, sdk.NewInt(100))), - }, - { - name: "Invalid Case: invalid incentive Record with valid Gauge", - poolId: 1, - sender: s.TestAccs[0], - incentiveDenom: defaultRewardDenom, - incentiveAmount: sdk.NewInt(200), - emissionRate: sdk.NewDec(2), - startTime: timeBeforeBlock, - minUptime: time.Hour * 2, - gauge: defaultGauge, - authorizedUptimes: cltypes.SupportedUptimes, - - expectedError: true, - }, - } - - for _, tc := range testCases { - s.Run(tc.name, func() { - s.SetupTest() - s.Ctx = s.Ctx.WithBlockTime(defaultBlockTime) - - // Set up authorized CL uptimes to robustly test distribution - if tc.authorizedUptimes != nil { - clParams := s.App.ConcentratedLiquidityKeeper.GetParams(s.Ctx) - clParams.AuthorizedUptimes = tc.authorizedUptimes - s.App.ConcentratedLiquidityKeeper.SetParams(s.Ctx, clParams) - } - - s.PrepareConcentratedPool() - - s.FundAcc(tc.sender, sdk.NewCoins(sdk.NewCoin(defaultRewardDenom, sdk.NewInt(10000)))) - gauges := s.SetupGauges([]perpGaugeDesc{tc.gauge}, defaultRewardDenom) - - err := s.App.IncentivesKeeper.DistributeConcentratedLiquidity(s.Ctx, tc.poolId, tc.sender, sdk.NewCoin(tc.incentiveDenom, tc.incentiveAmount), tc.emissionRate, tc.startTime, tc.minUptime, gauges[0]) - if tc.expectedError { - s.Require().Error(err) - } else { - s.Require().NoError(err) - - gauge, err := s.App.IncentivesKeeper.GetGaugeByID(s.Ctx, gauges[0].Id) - s.Require().NoError(err) - - s.Require().Equal(gauge.DistributedCoins, gauges[0].DistributedCoins.Add(tc.expectedCoins...)) - } - }) - } -} diff --git a/x/incentives/keeper/export_test.go b/x/incentives/keeper/export_test.go index 8b6f3a98a6b..6f390fa8ba2 100644 --- a/x/incentives/keeper/export_test.go +++ b/x/incentives/keeper/export_test.go @@ -1,8 +1,6 @@ package keeper import ( - "time" - sdk "github.com/cosmos/cosmos-sdk/types" "github.com/osmosis-labs/osmosis/v16/x/incentives/types" @@ -42,7 +40,3 @@ func (k Keeper) MoveActiveGaugeToFinishedGauge(ctx sdk.Context, gauge types.Gaug func (k Keeper) ChargeFeeIfSufficientFeeDenomBalance(ctx sdk.Context, address sdk.AccAddress, fee sdk.Int, gaugeCoins sdk.Coins) error { return k.chargeFeeIfSufficientFeeDenomBalance(ctx, address, fee, gaugeCoins) } - -func (k Keeper) DistributeConcentratedLiquidity(ctx sdk.Context, poolId uint64, sender sdk.AccAddress, incentiveCoin sdk.Coin, emissionRate sdk.Dec, startTime time.Time, minUptime time.Duration, gauge types.Gauge) error { - return k.distributeConcentratedLiquidity(ctx, poolId, sender, incentiveCoin, emissionRate, startTime, minUptime, gauge) -} diff --git a/x/incentives/keeper/gauge.go b/x/incentives/keeper/gauge.go index ec68d60e6a1..3c876de6de7 100644 --- a/x/incentives/keeper/gauge.go +++ b/x/incentives/keeper/gauge.go @@ -18,6 +18,7 @@ import ( "github.com/osmosis-labs/osmosis/v16/x/incentives/types" lockuptypes "github.com/osmosis-labs/osmosis/v16/x/lockup/types" + poolmanagertypes "github.com/osmosis-labs/osmosis/v16/x/poolmanager/types" epochtypes "github.com/osmosis-labs/osmosis/x/epochs/types" ) @@ -94,7 +95,7 @@ func (k Keeper) SetGaugeWithRefKey(ctx sdk.Context, gauge *types.Gauge) error { } // CreateGauge creates a gauge and sends coins to the gauge. -func (k Keeper) CreateGauge(ctx sdk.Context, isPerpetual bool, owner sdk.AccAddress, coins sdk.Coins, distrTo lockuptypes.QueryCondition, startTime time.Time, numEpochsPaidOver uint64) (uint64, error) { +func (k Keeper) CreateGauge(ctx sdk.Context, isPerpetual bool, owner sdk.AccAddress, coins sdk.Coins, distrTo lockuptypes.QueryCondition, startTime time.Time, numEpochsPaidOver uint64, poolId uint64) (uint64, error) { // Ensure that this gauge's duration is one of the allowed durations on chain durations := k.GetLockableDurations(ctx) if distrTo.LockQueryType == lockuptypes.ByDuration { @@ -110,13 +111,41 @@ func (k Keeper) CreateGauge(ctx sdk.Context, isPerpetual bool, owner sdk.AccAddr } } - // check if denom this gauge pays out to exists on-chain - if !k.bk.HasSupply(ctx, distrTo.Denom) && !strings.Contains(distrTo.Denom, "osmovaloper") { - return 0, fmt.Errorf("denom does not exist: %s", distrTo.Denom) + nextGaugeId := k.GetLastGaugeID(ctx) + 1 + + // For no lock gauges, a pool id must be set. + // A pool with such id must exist and be a concentrated pool. + if distrTo.LockQueryType == lockuptypes.NoLock { + if poolId == 0 { + return 0, fmt.Errorf("no lock gauges must have a pool id") + } + + pool, err := k.pmk.GetPool(ctx, poolId) + if err != nil { + return 0, err + } + + if pool.GetType() != poolmanagertypes.Concentrated { + return 0, fmt.Errorf("no lock gauges must be created for concentrated pools only") + } + + // We assume that external gauges are created with 0 duration, + // while internal gauges are created with an incentive epoch duration. + k.pik.SetPoolGaugeId(ctx, poolId, distrTo.Duration, nextGaugeId) + } else { + // For all other gauges, pool id must be 0. + if poolId != 0 { + return 0, fmt.Errorf("pool id must be 0 for gauges with lock") + } + + // check if denom this gauge pays out to exists on-chain + if !k.bk.HasSupply(ctx, distrTo.Denom) && !strings.Contains(distrTo.Denom, "osmovaloper") { + return 0, fmt.Errorf("denom does not exist: %s", distrTo.Denom) + } } gauge := types.Gauge{ - Id: k.GetLastGaugeID(ctx) + 1, + Id: nextGaugeId, IsPerpetual: isPerpetual, DistributeTo: distrTo, Coins: coins, diff --git a/x/incentives/keeper/gauge_test.go b/x/incentives/keeper/gauge_test.go index f8052258867..26833ca823f 100644 --- a/x/incentives/keeper/gauge_test.go +++ b/x/incentives/keeper/gauge_test.go @@ -24,11 +24,11 @@ func (s *KeeperTestSuite) TestInvalidDurationGaugeCreationValidation() { Denom: defaultLPDenom, Duration: defaultLockDuration / 2, // 0.5 second, invalid duration } - _, err := s.App.IncentivesKeeper.CreateGauge(s.Ctx, false, addrs[0], defaultLiquidTokens, distrTo, time.Time{}, 1) + _, err := s.App.IncentivesKeeper.CreateGauge(s.Ctx, false, addrs[0], defaultLiquidTokens, distrTo, time.Time{}, 1, 0) s.Require().Error(err) distrTo.Duration = defaultLockDuration - _, err = s.App.IncentivesKeeper.CreateGauge(s.Ctx, false, addrs[0], defaultLiquidTokens, distrTo, time.Time{}, 1) + _, err = s.App.IncentivesKeeper.CreateGauge(s.Ctx, false, addrs[0], defaultLiquidTokens, distrTo, time.Time{}, 1, 0) s.Require().NoError(err) } @@ -43,10 +43,10 @@ func (s *KeeperTestSuite) TestNonExistentDenomGaugeCreation() { Denom: defaultLPDenom, Duration: defaultLockDuration, } - _, err := s.App.IncentivesKeeper.CreateGauge(s.Ctx, false, addrNoSupply, defaultLiquidTokens, distrTo, time.Time{}, 1) + _, err := s.App.IncentivesKeeper.CreateGauge(s.Ctx, false, addrNoSupply, defaultLiquidTokens, distrTo, time.Time{}, 1, 0) s.Require().Error(err) - _, err = s.App.IncentivesKeeper.CreateGauge(s.Ctx, false, addrs[0], defaultLiquidTokens, distrTo, time.Time{}, 1) + _, err = s.App.IncentivesKeeper.CreateGauge(s.Ctx, false, addrs[0], defaultLiquidTokens, distrTo, time.Time{}, 1, 0) s.Require().NoError(err) } @@ -426,3 +426,109 @@ func (s *KeeperTestSuite) TestAddToGaugeRewards() { }) } } + +// TestCreateGauge_NoLockGauges tests the CreateGauge function +// specifically focusing on the no lock gauge type and test cases around it. +// It tests the following: +// - For no lock gauges, a CL pool id must be given as well and then pool must exist +// - Otherwise, the given pool id must be zero. Errors if not. +func (s *KeeperTestSuite) TestCreateGauge_NoLockGauges() { + const ( + zeroPoolId = uint64(0) + balancerPool = uint64(1) + concentratedPool = uint64(2) + invalidPool = uint64(3) + // 3 are created for balancer pool and 1 for CL. + // As a result, the next gauge id should be 5. + defaultExpectedGaugeId = uint64(5) + + defaultIsPerpetualParam = false + + defaultNumEpochPaidOver = uint64(10) + ) + + var ( + defaultCoins = sdk.NewCoins( + sdk.NewCoin("uosmo", sdk.NewInt(100000)), + sdk.NewCoin("atom", sdk.NewInt(99999)), + ) + + defaultTime = time.Unix(0, 0) + ) + testCases := []struct { + name string + distrTo lockuptypes.QueryCondition + poolId uint64 + + expectedGaugeId uint64 + expectErr bool + }{ + { + name: "create valid no lock gauge with CL pool", + distrTo: lockuptypes.QueryCondition{ + LockQueryType: lockuptypes.NoLock, + }, + poolId: concentratedPool, + + expectedGaugeId: defaultExpectedGaugeId, + expectErr: false, + }, + { + name: "fail to create no lock gauge with balancer pool", + distrTo: lockuptypes.QueryCondition{ + LockQueryType: lockuptypes.NoLock, + }, + poolId: balancerPool, + + expectErr: true, + }, + { + name: "fail to create no lock gauge with non-existent pool", + distrTo: lockuptypes.QueryCondition{ + LockQueryType: lockuptypes.NoLock, + }, + poolId: invalidPool, + + expectErr: true, + }, + { + name: "fail to create no lock gauge with zero pool id", + distrTo: lockuptypes.QueryCondition{ + LockQueryType: lockuptypes.NoLock, + }, + poolId: zeroPoolId, + + expectErr: true, + }, + } + + for _, tc := range testCases { + tc := tc + s.Run(tc.name, func() { + s.SetupTest() + + s.PrepareBalancerPool() + s.PrepareConcentratedPool() + + s.FundAcc(s.TestAccs[0], defaultCoins) + + // System under test + // Note that the default params are used for some inputs since they are not relevant to the test case. + gaugeId, err := s.App.IncentivesKeeper.CreateGauge(s.Ctx, defaultIsPerpetualParam, s.TestAccs[0], defaultCoins, tc.distrTo, defaultTime, defaultNumEpochPaidOver, tc.poolId) + + if tc.expectErr { + s.Require().Error(err) + } else { + s.Require().NoError(err) + + s.Require().Equal(tc.expectedGaugeId, gaugeId) + + // Assert that pool id and gauge id links are created + gaugeId, err := s.App.PoolIncentivesKeeper.GetPoolGaugeId(s.Ctx, tc.poolId, tc.distrTo.Duration) + s.Require().NoError(err) + + s.Require().Equal(tc.expectedGaugeId, gaugeId) + } + }) + } +} diff --git a/x/incentives/keeper/genesis_test.go b/x/incentives/keeper/genesis_test.go index 9f49f2bd412..a342f985958 100644 --- a/x/incentives/keeper/genesis_test.go +++ b/x/incentives/keeper/genesis_test.go @@ -44,7 +44,7 @@ func TestIncentivesExportGenesis(t *testing.T) { // create a gauge that distributes coins to earlier created LP token and duration startTime := time.Now() - gaugeID, err := app.IncentivesKeeper.CreateGauge(ctx, true, addr, coins, distrTo, startTime, 1) + gaugeID, err := app.IncentivesKeeper.CreateGauge(ctx, true, addr, coins, distrTo, startTime, 1, 0) require.NoError(t, err) // export genesis using default configurations diff --git a/x/incentives/keeper/msg_server.go b/x/incentives/keeper/msg_server.go index ddac84ee5e9..76bdf9945c2 100644 --- a/x/incentives/keeper/msg_server.go +++ b/x/incentives/keeper/msg_server.go @@ -38,7 +38,7 @@ func (server msgServer) CreateGauge(goCtx context.Context, msg *types.MsgCreateG return nil, err } - gaugeID, err := server.keeper.CreateGauge(ctx, msg.IsPerpetual, owner, msg.Coins, msg.DistributeTo, msg.StartTime, msg.NumEpochsPaidOver) + gaugeID, err := server.keeper.CreateGauge(ctx, msg.IsPerpetual, owner, msg.Coins, msg.DistributeTo, msg.StartTime, msg.NumEpochsPaidOver, msg.PoolId) if err != nil { return nil, errorsmod.Wrap(sdkerrors.ErrInvalidRequest, err.Error()) } diff --git a/x/incentives/keeper/suite_test.go b/x/incentives/keeper/suite_test.go index 44d010ae83d..5e5b25d6e1b 100644 --- a/x/incentives/keeper/suite_test.go +++ b/x/incentives/keeper/suite_test.go @@ -134,7 +134,7 @@ func (s *KeeperTestSuite) SetupGauges(gaugeDescriptors []perpGaugeDesc, denom st // CreateGauge creates a gauge struct given the required params. func (s *KeeperTestSuite) CreateGauge(isPerpetual bool, addr sdk.AccAddress, coins sdk.Coins, distrTo lockuptypes.QueryCondition, startTime time.Time, numEpoch uint64) (uint64, *types.Gauge) { s.FundAcc(addr, coins) - gaugeID, err := s.App.IncentivesKeeper.CreateGauge(s.Ctx, isPerpetual, addr, coins, distrTo, startTime, numEpoch) + gaugeID, err := s.App.IncentivesKeeper.CreateGauge(s.Ctx, isPerpetual, addr, coins, distrTo, startTime, numEpoch, 0) s.Require().NoError(err) gauge, err := s.App.IncentivesKeeper.GetGaugeByID(s.Ctx, gaugeID) s.Require().NoError(err) diff --git a/x/incentives/types/msgs.go b/x/incentives/types/msgs.go index 5b94e041a9c..866f37d7763 100644 --- a/x/incentives/types/msgs.go +++ b/x/incentives/types/msgs.go @@ -55,8 +55,17 @@ func (m MsgCreateGauge) ValidateBasic() error { return errors.New("distribution period should be 1 epoch for perpetual gauge") } - if lockuptypes.LockQueryType_name[int32(m.DistributeTo.LockQueryType)] != "ByDuration" { - return errors.New("only duration query condition is allowed. Start time distr conditions is an obsolete codepath slated for deletion") + lockType := m.DistributeTo.LockQueryType + if lockType == lockuptypes.ByTime { + return errors.New("start time distr conditions is an obsolete codepath slated for deletion") + } + + if lockType == lockuptypes.ByDuration && m.PoolId != 0 { + return errors.New("pool id should not be set for duration distr condition") + } + + if lockType == lockuptypes.NoLock && m.PoolId == 0 { + return errors.New("pool id should be set for no lock distr condition") } return nil diff --git a/x/incentives/types/msgs_test.go b/x/incentives/types/msgs_test.go index a69fe97a212..8afee23b9e7 100644 --- a/x/incentives/types/msgs_test.go +++ b/x/incentives/types/msgs_test.go @@ -17,8 +17,8 @@ import ( lockuptypes "github.com/osmosis-labs/osmosis/v16/x/lockup/types" ) -// TestMsgCreatePool tests if valid/invalid create pool messages are properly validated/invalidated -func TestMsgCreatePool(t *testing.T) { +// TestMsgCreateGauge tests if valid/invalid create pool messages are properly validated/invalidated +func TestMsgCreateGauge(t *testing.T) { // generate a private/public key pair and get the respective address pk1 := ed25519.GenPrivKey().PubKey() addr1 := sdk.AccAddress(pk1.Address()) @@ -139,6 +139,41 @@ func TestMsgCreatePool(t *testing.T) { }), expectPass: true, }, + { + name: "invalid: by time lock type", + msg: createMsg(func(msg incentivestypes.MsgCreateGauge) incentivestypes.MsgCreateGauge { + msg.DistributeTo.LockQueryType = lockuptypes.ByTime + return msg + }), + expectPass: false, + }, + { + name: "invalid: by duration with pool id set", + msg: createMsg(func(msg incentivestypes.MsgCreateGauge) incentivestypes.MsgCreateGauge { + msg.DistributeTo.LockQueryType = lockuptypes.ByDuration + msg.PoolId = 1 + return msg + }), + expectPass: false, + }, + { + name: "invalid: no lock with pool id unset", + msg: createMsg(func(msg incentivestypes.MsgCreateGauge) incentivestypes.MsgCreateGauge { + msg.DistributeTo.LockQueryType = lockuptypes.NoLock + msg.PoolId = 0 + return msg + }), + expectPass: false, + }, + { + name: "valid no lick with pool id unset", + msg: createMsg(func(msg incentivestypes.MsgCreateGauge) incentivestypes.MsgCreateGauge { + msg.DistributeTo.LockQueryType = lockuptypes.NoLock + msg.PoolId = 1 + return msg + }), + expectPass: true, + }, } for _, test := range tests { diff --git a/x/incentives/types/tx.pb.go b/x/incentives/types/tx.pb.go index 8349647bfb3..d5cd5818639 100644 --- a/x/incentives/types/tx.pb.go +++ b/x/incentives/types/tx.pb.go @@ -56,6 +56,10 @@ type MsgCreateGauge struct { // num_epochs_paid_over is the number of epochs distribution will be completed // over NumEpochsPaidOver uint64 `protobuf:"varint,6,opt,name=num_epochs_paid_over,json=numEpochsPaidOver,proto3" json:"num_epochs_paid_over,omitempty"` + // pool_id is the ID of the pool that the gauge is meant to be associated + // with. if pool_id is set, then the "QueryCondition.LockQueryType" must be + // "NoLock" with all other fields unset. + PoolId uint64 `protobuf:"varint,7,opt,name=pool_id,json=poolId,proto3" json:"pool_id,omitempty"` } func (m *MsgCreateGauge) Reset() { *m = MsgCreateGauge{} } @@ -133,6 +137,13 @@ func (m *MsgCreateGauge) GetNumEpochsPaidOver() uint64 { return 0 } +func (m *MsgCreateGauge) GetPoolId() uint64 { + if m != nil { + return m.PoolId + } + return 0 +} + type MsgCreateGaugeResponse struct { } @@ -279,47 +290,48 @@ func init() { func init() { proto.RegisterFile("osmosis/incentives/tx.proto", fileDescriptor_8ea120e22291556e) } var fileDescriptor_8ea120e22291556e = []byte{ - // 628 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x94, 0x3f, 0x4f, 0xdc, 0x30, - 0x18, 0xc6, 0xcf, 0xbd, 0xe3, 0x9f, 0x0f, 0x2a, 0x88, 0x68, 0x1b, 0xae, 0x55, 0x72, 0x44, 0x55, - 0x95, 0x22, 0x9d, 0x5d, 0xa8, 0xc4, 0xc0, 0xd6, 0x43, 0x55, 0xc5, 0x80, 0x4a, 0x23, 0xa4, 0x4a, - 0x48, 0x55, 0xe4, 0xc4, 0x6e, 0xb0, 0xb8, 0xc4, 0x51, 0xec, 0x1c, 0xf0, 0x15, 0x3a, 0xf1, 0x39, - 0x3a, 0x75, 0xed, 0xd6, 0x91, 0x91, 0xb1, 0x13, 0x54, 0x30, 0x74, 0xe7, 0x13, 0x54, 0x71, 0x12, - 0xe0, 0x54, 0x28, 0x4b, 0x97, 0x38, 0xf6, 0xf3, 0xbe, 0xaf, 0xfd, 0x3e, 0x3f, 0x27, 0xf0, 0xa9, - 0x90, 0xb1, 0x90, 0x5c, 0x62, 0x9e, 0x84, 0x2c, 0x51, 0x7c, 0xc8, 0x24, 0x56, 0x07, 0x28, 0xcd, - 0x84, 0x12, 0x86, 0x51, 0x89, 0xe8, 0x5a, 0xec, 0xcc, 0x47, 0x22, 0x12, 0x5a, 0xc6, 0xc5, 0x5b, - 0x19, 0xd9, 0x99, 0x23, 0x31, 0x4f, 0x04, 0xd6, 0xcf, 0x6a, 0xc9, 0x8e, 0x84, 0x88, 0x06, 0x0c, - 0xeb, 0x59, 0x90, 0x7f, 0xc6, 0x8a, 0xc7, 0x4c, 0x2a, 0x12, 0xa7, 0x55, 0x80, 0x15, 0xea, 0xf2, - 0x38, 0x20, 0x92, 0xe1, 0xe1, 0x72, 0xc0, 0x14, 0x59, 0xc6, 0xa1, 0xe0, 0x49, 0xad, 0xdf, 0x72, - 0xb4, 0x88, 0xe4, 0x11, 0xab, 0xf4, 0x85, 0x5a, 0x1f, 0x88, 0x70, 0x2f, 0x4f, 0xf5, 0x50, 0x4a, - 0xce, 0xf7, 0x26, 0x7c, 0xb8, 0x29, 0xa3, 0xf5, 0x8c, 0x11, 0xc5, 0xde, 0x15, 0x39, 0xc6, 0x22, - 0x9c, 0xe6, 0xd2, 0x4f, 0x59, 0x96, 0x32, 0x95, 0x93, 0x81, 0x09, 0xba, 0xc0, 0x9d, 0xf4, 0xda, - 0x5c, 0x6e, 0xd5, 0x4b, 0xc6, 0x0b, 0x38, 0x26, 0xf6, 0x13, 0x96, 0x99, 0x0f, 0xba, 0xc0, 0x9d, - 0xea, 0xcf, 0x5e, 0x9e, 0xda, 0xd3, 0x87, 0x24, 0x1e, 0xac, 0x39, 0x7a, 0xd9, 0xf1, 0x4a, 0xd9, - 0xd8, 0x80, 0x33, 0x94, 0x4b, 0x95, 0xf1, 0x20, 0x57, 0xcc, 0x57, 0xc2, 0x6c, 0x76, 0x81, 0xdb, - 0x5e, 0xb1, 0x50, 0x6d, 0x57, 0x79, 0x20, 0xf4, 0x21, 0x67, 0xd9, 0xe1, 0xba, 0x48, 0x28, 0x57, - 0x5c, 0x24, 0xfd, 0xd6, 0xf1, 0xa9, 0xdd, 0xf0, 0xa6, 0xaf, 0x53, 0xb7, 0x85, 0x41, 0xe0, 0x58, - 0xd1, 0xb1, 0x34, 0x5b, 0xdd, 0xa6, 0xdb, 0x5e, 0x59, 0x40, 0xa5, 0x27, 0xa8, 0xf0, 0x04, 0x55, - 0x9e, 0xa0, 0x75, 0xc1, 0x93, 0xfe, 0xab, 0x22, 0xfb, 0xeb, 0x99, 0xed, 0x46, 0x5c, 0xed, 0xe6, - 0x01, 0x0a, 0x45, 0x8c, 0x2b, 0x03, 0xcb, 0xa1, 0x27, 0xe9, 0x1e, 0x56, 0x87, 0x29, 0x93, 0x3a, - 0x41, 0x7a, 0x65, 0x65, 0xe3, 0x23, 0x84, 0x52, 0x91, 0x4c, 0xf9, 0x85, 0xff, 0xe6, 0x98, 0x3e, - 0x6a, 0x07, 0x95, 0x70, 0x50, 0x0d, 0x07, 0x6d, 0xd7, 0x70, 0xfa, 0xcf, 0x8a, 0x8d, 0x2e, 0x4f, - 0xed, 0xd9, 0xb2, 0xf5, 0x2b, 0x6a, 0xce, 0xd1, 0x99, 0x0d, 0xbc, 0x29, 0x5d, 0xab, 0x88, 0x36, - 0x30, 0x9c, 0x4f, 0xf2, 0xd8, 0x67, 0xa9, 0x08, 0x77, 0xa5, 0x9f, 0x12, 0x4e, 0x7d, 0x31, 0x64, - 0x99, 0x39, 0xde, 0x05, 0x6e, 0xcb, 0x9b, 0x4b, 0xf2, 0xf8, 0xad, 0x96, 0xb6, 0x08, 0xa7, 0xef, - 0x87, 0x2c, 0x5b, 0x7b, 0xfe, 0xe5, 0xf7, 0xb7, 0x25, 0xfb, 0x16, 0xaa, 0xa1, 0xe6, 0xd4, 0xd3, - 0x70, 0x1d, 0x13, 0x3e, 0x1e, 0x45, 0xe7, 0x31, 0x99, 0x8a, 0x44, 0x32, 0xe7, 0x0c, 0xc0, 0x99, - 0x4d, 0x19, 0xbd, 0xa1, 0x74, 0x5b, 0x94, 0x50, 0xaf, 0x88, 0x81, 0x7f, 0x13, 0x5b, 0x80, 0x93, - 0xba, 0xb8, 0xcf, 0xa9, 0x86, 0xdb, 0xf2, 0x26, 0xf4, 0x7c, 0x83, 0x1a, 0x0c, 0x4e, 0x64, 0x6c, - 0x9f, 0x64, 0x54, 0x9a, 0xcd, 0xff, 0xcf, 0xa0, 0xae, 0x7d, 0x77, 0xef, 0x84, 0xd2, 0x9e, 0x12, - 0x55, 0xef, 0x4f, 0xe0, 0xa3, 0x91, 0x06, 0xeb, 0xd6, 0x57, 0x7e, 0x00, 0xd8, 0xdc, 0x94, 0x91, - 0xf1, 0x09, 0xb6, 0x6f, 0x5e, 0x6a, 0x07, 0xfd, 0xfd, 0x85, 0xa2, 0x51, 0xf7, 0x3a, 0x4b, 0xf7, - 0xc7, 0xd4, 0xdb, 0x18, 0x3b, 0x10, 0xde, 0x70, 0x77, 0xf1, 0x8e, 0xcc, 0xeb, 0x90, 0xce, 0xcb, - 0x7b, 0x43, 0xea, 0xda, 0xfd, 0xad, 0xe3, 0x73, 0x0b, 0x9c, 0x9c, 0x5b, 0xe0, 0xd7, 0xb9, 0x05, - 0x8e, 0x2e, 0xac, 0xc6, 0xc9, 0x85, 0xd5, 0xf8, 0x79, 0x61, 0x35, 0x76, 0x56, 0x6f, 0xd8, 0x59, - 0x95, 0xeb, 0x0d, 0x48, 0x20, 0xeb, 0x09, 0x1e, 0x2e, 0xaf, 0xe2, 0x83, 0x91, 0x3f, 0x54, 0x61, - 0x71, 0x30, 0xae, 0x6f, 0xef, 0xeb, 0x3f, 0x01, 0x00, 0x00, 0xff, 0xff, 0xc7, 0xb8, 0xbe, 0xaa, - 0xc4, 0x04, 0x00, 0x00, + // 642 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x54, 0x41, 0x4f, 0xd4, 0x40, + 0x14, 0xde, 0xb2, 0xc0, 0xc2, 0x2c, 0x18, 0x68, 0x50, 0xca, 0x6a, 0xda, 0xa5, 0x31, 0x66, 0x25, + 0xd9, 0x19, 0xc1, 0x84, 0x03, 0x37, 0x97, 0x18, 0xc3, 0x81, 0x88, 0x0d, 0x89, 0x09, 0x89, 0x69, + 0xa6, 0xed, 0x58, 0x26, 0x6c, 0xfb, 0x9a, 0xce, 0x74, 0x81, 0xbf, 0xe0, 0x89, 0xdf, 0xe1, 0xc9, + 0x9f, 0xe0, 0x91, 0x23, 0xf1, 0xe4, 0x09, 0x0c, 0x1c, 0xbc, 0xf3, 0x0b, 0x4c, 0xa7, 0x2d, 0xec, + 0x46, 0x90, 0x8b, 0x97, 0x4e, 0xdf, 0x7c, 0xef, 0x7d, 0xf3, 0xde, 0xf7, 0x4d, 0x8b, 0x9e, 0x82, + 0x88, 0x40, 0x70, 0x41, 0x78, 0xec, 0xb3, 0x58, 0xf2, 0x01, 0x13, 0x44, 0x1e, 0xe1, 0x24, 0x05, + 0x09, 0xba, 0x5e, 0x82, 0xf8, 0x16, 0x6c, 0x2d, 0x84, 0x10, 0x82, 0x82, 0x49, 0xfe, 0x56, 0x64, + 0xb6, 0xe6, 0x69, 0xc4, 0x63, 0x20, 0xea, 0x59, 0x6e, 0x59, 0x21, 0x40, 0xd8, 0x67, 0x44, 0x45, + 0x5e, 0xf6, 0x99, 0x48, 0x1e, 0x31, 0x21, 0x69, 0x94, 0x94, 0x09, 0xa6, 0xaf, 0xe8, 0x89, 0x47, + 0x05, 0x23, 0x83, 0x55, 0x8f, 0x49, 0xba, 0x4a, 0x7c, 0xe0, 0x71, 0x85, 0xdf, 0xd1, 0x5a, 0x48, + 0xb3, 0x90, 0x95, 0xf8, 0x52, 0x85, 0xf7, 0xc1, 0x3f, 0xc8, 0x12, 0xb5, 0x14, 0x90, 0xfd, 0xa3, + 0x8e, 0x1e, 0x6d, 0x8b, 0x70, 0x33, 0x65, 0x54, 0xb2, 0x77, 0x79, 0x8d, 0xbe, 0x8c, 0x66, 0xb8, + 0x70, 0x13, 0x96, 0x26, 0x4c, 0x66, 0xb4, 0x6f, 0x68, 0x6d, 0xad, 0x33, 0xe5, 0x34, 0xb9, 0xd8, + 0xa9, 0xb6, 0xf4, 0x17, 0x68, 0x02, 0x0e, 0x63, 0x96, 0x1a, 0x63, 0x6d, 0xad, 0x33, 0xdd, 0x9b, + 0xbb, 0x3e, 0xb7, 0x66, 0x8e, 0x69, 0xd4, 0xdf, 0xb0, 0xd5, 0xb6, 0xed, 0x14, 0xb0, 0xbe, 0x85, + 0x66, 0x03, 0x2e, 0x64, 0xca, 0xbd, 0x4c, 0x32, 0x57, 0x82, 0x51, 0x6f, 0x6b, 0x9d, 0xe6, 0x9a, + 0x89, 0x2b, 0xb9, 0x8a, 0x86, 0xf0, 0x87, 0x8c, 0xa5, 0xc7, 0x9b, 0x10, 0x07, 0x5c, 0x72, 0x88, + 0x7b, 0xe3, 0xa7, 0xe7, 0x56, 0xcd, 0x99, 0xb9, 0x2d, 0xdd, 0x05, 0x9d, 0xa2, 0x89, 0x7c, 0x62, + 0x61, 0x8c, 0xb7, 0xeb, 0x9d, 0xe6, 0xda, 0x12, 0x2e, 0x34, 0xc1, 0xb9, 0x26, 0xb8, 0xd4, 0x04, + 0x6f, 0x02, 0x8f, 0x7b, 0xaf, 0xf2, 0xea, 0xaf, 0x17, 0x56, 0x27, 0xe4, 0x72, 0x3f, 0xf3, 0xb0, + 0x0f, 0x11, 0x29, 0x05, 0x2c, 0x96, 0xae, 0x08, 0x0e, 0x88, 0x3c, 0x4e, 0x98, 0x50, 0x05, 0xc2, + 0x29, 0x98, 0xf5, 0x8f, 0x08, 0x09, 0x49, 0x53, 0xe9, 0xe6, 0xfa, 0x1b, 0x13, 0xaa, 0xd5, 0x16, + 0x2e, 0xcc, 0xc1, 0x95, 0x39, 0x78, 0xb7, 0x32, 0xa7, 0xf7, 0x2c, 0x3f, 0xe8, 0xfa, 0xdc, 0x9a, + 0x2b, 0x46, 0xbf, 0x71, 0xcd, 0x3e, 0xb9, 0xb0, 0x34, 0x67, 0x5a, 0x71, 0xe5, 0xd9, 0x3a, 0x41, + 0x0b, 0x71, 0x16, 0xb9, 0x2c, 0x01, 0x7f, 0x5f, 0xb8, 0x09, 0xe5, 0x81, 0x0b, 0x03, 0x96, 0x1a, + 0x93, 0x6d, 0xad, 0x33, 0xee, 0xcc, 0xc7, 0x59, 0xf4, 0x56, 0x41, 0x3b, 0x94, 0x07, 0xef, 0x07, + 0x2c, 0xd5, 0x17, 0x51, 0x23, 0x01, 0xe8, 0xbb, 0x3c, 0x30, 0x1a, 0x2a, 0x67, 0x32, 0x0f, 0xb7, + 0x82, 0x8d, 0xe7, 0x5f, 0x7e, 0x7f, 0x5b, 0xb1, 0xee, 0xb0, 0xdb, 0x57, 0x06, 0x76, 0x95, 0xeb, + 0xb6, 0x81, 0x9e, 0x8c, 0x7a, 0xea, 0x30, 0x91, 0x40, 0x2c, 0x98, 0x7d, 0xa1, 0xa1, 0xd9, 0x6d, + 0x11, 0xbe, 0x09, 0x82, 0x5d, 0x28, 0xdc, 0xbe, 0xb1, 0x52, 0xfb, 0xb7, 0x95, 0x4b, 0x68, 0x4a, + 0x91, 0xe7, 0x3d, 0x8d, 0xa9, 0x9e, 0x1a, 0x2a, 0xde, 0x0a, 0x74, 0x86, 0x1a, 0x29, 0x3b, 0xa4, + 0x69, 0x20, 0x8c, 0xfa, 0xff, 0x37, 0xa7, 0xe2, 0xbe, 0x7f, 0x76, 0x1a, 0x04, 0x5d, 0x09, 0xe5, + 0xec, 0x8b, 0xe8, 0xf1, 0xc8, 0x80, 0xd5, 0xe8, 0x6b, 0xdf, 0x35, 0x54, 0xdf, 0x16, 0xa1, 0xfe, + 0x09, 0x35, 0x87, 0x6f, 0xbb, 0x8d, 0xff, 0xfe, 0x74, 0xf1, 0xa8, 0x7a, 0xad, 0x95, 0x87, 0x73, + 0xaa, 0x63, 0xf4, 0x3d, 0x84, 0x86, 0xd4, 0x5d, 0xbe, 0xa7, 0xf2, 0x36, 0xa5, 0xf5, 0xf2, 0xc1, + 0x94, 0x8a, 0xbb, 0xb7, 0x73, 0x7a, 0x69, 0x6a, 0x67, 0x97, 0xa6, 0xf6, 0xeb, 0xd2, 0xd4, 0x4e, + 0xae, 0xcc, 0xda, 0xd9, 0x95, 0x59, 0xfb, 0x79, 0x65, 0xd6, 0xf6, 0xd6, 0x87, 0xe4, 0x2c, 0xe9, + 0xba, 0x7d, 0xea, 0x89, 0x2a, 0x20, 0x83, 0xd5, 0x75, 0x72, 0x34, 0xf2, 0xeb, 0xca, 0x25, 0xf6, + 0x26, 0xd5, 0xb5, 0x7e, 0xfd, 0x27, 0x00, 0x00, 0xff, 0xff, 0xa4, 0x41, 0x82, 0x0e, 0xdd, 0x04, + 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -458,6 +470,11 @@ func (m *MsgCreateGauge) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if m.PoolId != 0 { + i = encodeVarintTx(dAtA, i, uint64(m.PoolId)) + i-- + dAtA[i] = 0x38 + } if m.NumEpochsPaidOver != 0 { i = encodeVarintTx(dAtA, i, uint64(m.NumEpochsPaidOver)) i-- @@ -647,6 +664,9 @@ func (m *MsgCreateGauge) Size() (n int) { if m.NumEpochsPaidOver != 0 { n += 1 + sovTx(uint64(m.NumEpochsPaidOver)) } + if m.PoolId != 0 { + n += 1 + sovTx(uint64(m.PoolId)) + } return n } @@ -896,6 +916,25 @@ func (m *MsgCreateGauge) Unmarshal(dAtA []byte) error { break } } + case 7: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field PoolId", wireType) + } + m.PoolId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.PoolId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := skipTx(dAtA[iNdEx:]) diff --git a/x/lockup/types/lock.pb.go b/x/lockup/types/lock.pb.go index dd7965493ef..fb636a4e8ca 100644 --- a/x/lockup/types/lock.pb.go +++ b/x/lockup/types/lock.pb.go @@ -36,16 +36,19 @@ type LockQueryType int32 const ( ByDuration LockQueryType = 0 ByTime LockQueryType = 1 + NoLock LockQueryType = 2 ) var LockQueryType_name = map[int32]string{ 0: "ByDuration", 1: "ByTime", + 2: "NoLock", } var LockQueryType_value = map[string]int32{ "ByDuration": 0, "ByTime": 1, + "NoLock": 2, } func (x LockQueryType) String() string { @@ -328,47 +331,48 @@ func init() { func init() { proto.RegisterFile("osmosis/lockup/lock.proto", fileDescriptor_7e9d7527a237b489) } var fileDescriptor_7e9d7527a237b489 = []byte{ - // 640 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x54, 0x3f, 0x6f, 0xd4, 0x30, - 0x1c, 0xbd, 0xdc, 0x9f, 0xd2, 0xba, 0xf4, 0x7a, 0xb2, 0x8a, 0x48, 0x0f, 0x48, 0x4e, 0x19, 0xd0, - 0x09, 0xb5, 0x09, 0x57, 0x24, 0x06, 0x36, 0xd2, 0x63, 0xa8, 0xd4, 0x01, 0x42, 0xc5, 0xd0, 0x25, - 0x4a, 0x62, 0x93, 0x5a, 0x4d, 0xe2, 0x10, 0x27, 0x2d, 0xf9, 0x06, 0x8c, 0x1d, 0x41, 0x62, 0x63, - 0xe3, 0x5b, 0xb0, 0x75, 0xec, 0xc8, 0x74, 0x45, 0xed, 0xc6, 0xd8, 0x4f, 0x80, 0x6c, 0x27, 0xd7, - 0x6b, 0x51, 0xa5, 0x0e, 0x30, 0xe5, 0xec, 0xf7, 0xfb, 0x3d, 0xff, 0xfc, 0xde, 0xf3, 0x81, 0x55, - 0xca, 0x62, 0xca, 0x08, 0xb3, 0x22, 0x1a, 0xec, 0x17, 0xa9, 0xf8, 0x98, 0x69, 0x46, 0x73, 0x0a, - 0xbb, 0x15, 0x64, 0x4a, 0xa8, 0xbf, 0x12, 0xd2, 0x90, 0x0a, 0xc8, 0xe2, 0xbf, 0x64, 0x55, 0x5f, - 0x0b, 0x29, 0x0d, 0x23, 0x6c, 0x89, 0x95, 0x5f, 0xbc, 0xb7, 0x50, 0x91, 0x79, 0x39, 0xa1, 0x49, - 0x85, 0xeb, 0xd7, 0xf1, 0x9c, 0xc4, 0x98, 0xe5, 0x5e, 0x9c, 0xd6, 0x04, 0x81, 0x38, 0xc7, 0xf2, - 0x3d, 0x86, 0xad, 0x83, 0x91, 0x8f, 0x73, 0x6f, 0x64, 0x05, 0x94, 0x54, 0x04, 0xc6, 0x8f, 0x16, - 0x00, 0xaf, 0x71, 0x46, 0x28, 0xda, 0xa6, 0xc1, 0x3e, 0xec, 0x82, 0xe6, 0xd6, 0x58, 0x55, 0x06, - 0xca, 0xb0, 0xed, 0x34, 0xb7, 0xc6, 0xf0, 0x31, 0xe8, 0xd0, 0xc3, 0x04, 0x67, 0x6a, 0x73, 0xa0, - 0x0c, 0x17, 0xec, 0xde, 0xc5, 0x44, 0xbf, 0x5b, 0x7a, 0x71, 0xf4, 0xc2, 0x10, 0xdb, 0x86, 0x23, - 0x61, 0xb8, 0x07, 0xe6, 0xeb, 0xc9, 0xd4, 0xd6, 0x40, 0x19, 0x2e, 0x6e, 0xac, 0x9a, 0x72, 0x34, - 0xb3, 0x1e, 0xcd, 0x1c, 0x57, 0x05, 0xf6, 0xe8, 0x78, 0xa2, 0x37, 0x7e, 0x4f, 0x74, 0x58, 0xb7, - 0xac, 0xd1, 0x98, 0xe4, 0x38, 0x4e, 0xf3, 0xf2, 0x62, 0xa2, 0x2f, 0x4b, 0xfe, 0x1a, 0x33, 0x3e, - 0x9f, 0xea, 0x8a, 0x33, 0x65, 0x87, 0x0e, 0x98, 0xc7, 0x09, 0x72, 0xf9, 0x3d, 0xd5, 0xb6, 0x38, - 0xa9, 0xff, 0xd7, 0x49, 0x3b, 0xb5, 0x08, 0xf6, 0x03, 0x7e, 0xd4, 0x25, 0x69, 0xdd, 0x69, 0x1c, - 0x71, 0xd2, 0x3b, 0x38, 0x41, 0xbc, 0x14, 0x7a, 0xa0, 0xc3, 0x25, 0x61, 0x6a, 0x67, 0xd0, 0x12, - 0xa3, 0x4b, 0xd1, 0x4c, 0x2e, 0x9a, 0x59, 0x89, 0x66, 0x6e, 0x52, 0x92, 0xd8, 0x4f, 0x39, 0xdf, - 0xf7, 0x53, 0x7d, 0x18, 0x92, 0x7c, 0xaf, 0xf0, 0xcd, 0x80, 0xc6, 0x56, 0xa5, 0xb0, 0xfc, 0xac, - 0x33, 0xb4, 0x6f, 0xe5, 0x65, 0x8a, 0x99, 0x68, 0x60, 0x8e, 0x64, 0x86, 0xbb, 0xe0, 0x7e, 0x86, - 0x0f, 0xbd, 0x0c, 0xb9, 0x19, 0x0e, 0x30, 0x39, 0xc0, 0x99, 0xeb, 0x21, 0x94, 0x61, 0xc6, 0xd4, - 0x39, 0x21, 0xad, 0x71, 0x31, 0xd1, 0x35, 0x39, 0xe5, 0x0d, 0x85, 0x86, 0x73, 0x4f, 0x22, 0x4e, - 0x05, 0xbc, 0xac, 0xf6, 0xbf, 0x34, 0x41, 0xf7, 0x4d, 0x81, 0xb3, 0x72, 0x93, 0x26, 0x88, 0x08, - 0x95, 0x5e, 0x81, 0x65, 0x9e, 0x2b, 0xf7, 0x03, 0xdf, 0x76, 0xf9, 0x3c, 0xc2, 0xd4, 0xee, 0xc6, - 0x23, 0xf3, 0x6a, 0xee, 0x4c, 0x6e, 0xbb, 0x68, 0xde, 0x29, 0x53, 0xec, 0x2c, 0x45, 0xb3, 0x4b, - 0xb8, 0x02, 0x3a, 0x08, 0x27, 0x34, 0x96, 0xf6, 0x3b, 0x72, 0xc1, 0x2d, 0xb8, 0xbd, 0xd9, 0xd7, - 0x1c, 0xb8, 0xc9, 0xd6, 0x77, 0x60, 0x61, 0x1a, 0xdd, 0x5b, 0xf8, 0xfa, 0xb0, 0x62, 0xed, 0x49, - 0xd6, 0x69, 0xab, 0x34, 0xf6, 0x92, 0xca, 0xf8, 0xda, 0x04, 0x4b, 0x6f, 0xcb, 0x24, 0xdf, 0xc3, - 0x39, 0x09, 0x44, 0xc4, 0xd7, 0x00, 0x2c, 0x12, 0x84, 0xb3, 0xa8, 0x24, 0x49, 0xe8, 0x0a, 0x95, - 0x08, 0xaa, 0x22, 0xdf, 0xbb, 0x44, 0x78, 0xed, 0x16, 0x82, 0x3a, 0x58, 0x64, 0xbc, 0xdd, 0x9d, - 0xd5, 0x01, 0x88, 0xad, 0x71, 0x2d, 0xc6, 0x34, 0x8f, 0xad, 0x7f, 0x94, 0xc7, 0xd9, 0xd7, 0xd4, - 0xfe, 0x9f, 0xaf, 0xe9, 0xc9, 0x08, 0x2c, 0x5d, 0x09, 0x00, 0xec, 0x02, 0x60, 0x97, 0x35, 0x77, - 0xaf, 0x01, 0x01, 0x98, 0xb3, 0x4b, 0x3e, 0x54, 0x4f, 0xe9, 0xb7, 0x3f, 0x7d, 0xd3, 0x1a, 0xf6, - 0xf6, 0xf1, 0x99, 0xa6, 0x9c, 0x9c, 0x69, 0xca, 0xaf, 0x33, 0x4d, 0x39, 0x3a, 0xd7, 0x1a, 0x27, - 0xe7, 0x5a, 0xe3, 0xe7, 0xb9, 0xd6, 0xd8, 0xdd, 0x98, 0x79, 0x14, 0x55, 0xca, 0xd6, 0x23, 0xcf, - 0x67, 0xf5, 0xc2, 0x3a, 0x18, 0x3d, 0xb7, 0x3e, 0xd6, 0xff, 0x85, 0xe2, 0x91, 0xf8, 0x73, 0xe2, - 0x42, 0xcf, 0xfe, 0x04, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xc7, 0xca, 0xaa, 0x2a, 0x05, 0x00, 0x00, + // 649 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x54, 0x3f, 0x6f, 0xd3, 0x40, + 0x1c, 0x8d, 0xf3, 0xa7, 0xb4, 0x57, 0x9a, 0x46, 0xa7, 0x22, 0xd2, 0x00, 0x76, 0xe4, 0x01, 0x45, + 0xa8, 0xb5, 0x49, 0x91, 0x18, 0x90, 0x18, 0x70, 0xc3, 0x50, 0xa9, 0x42, 0x60, 0x2a, 0x86, 0x2e, + 0x96, 0xed, 0x3b, 0xdc, 0x53, 0x6d, 0x9f, 0xf1, 0xd9, 0x2d, 0xfe, 0x06, 0x8c, 0x1d, 0x41, 0x62, + 0x63, 0xe3, 0x5b, 0xb0, 0x75, 0xec, 0xc8, 0x94, 0xa2, 0x76, 0x63, 0xec, 0x27, 0x40, 0x77, 0x67, + 0x27, 0x69, 0x51, 0xa5, 0x0e, 0x30, 0xd9, 0x77, 0xef, 0xf7, 0x7b, 0xf7, 0xf3, 0x7b, 0xef, 0x0c, + 0x56, 0x29, 0x8b, 0x28, 0x23, 0xcc, 0x0c, 0xa9, 0xbf, 0x9f, 0x27, 0xe2, 0x61, 0x24, 0x29, 0xcd, + 0x28, 0x6c, 0x97, 0x90, 0x21, 0xa1, 0xde, 0x4a, 0x40, 0x03, 0x2a, 0x20, 0x93, 0xbf, 0xc9, 0xaa, + 0x9e, 0x1a, 0x50, 0x1a, 0x84, 0xd8, 0x14, 0x2b, 0x2f, 0x7f, 0x6f, 0xa2, 0x3c, 0x75, 0x33, 0x42, + 0xe3, 0x12, 0xd7, 0xae, 0xe2, 0x19, 0x89, 0x30, 0xcb, 0xdc, 0x28, 0xa9, 0x08, 0x7c, 0x71, 0x8e, + 0xe9, 0xb9, 0x0c, 0x9b, 0x07, 0x43, 0x0f, 0x67, 0xee, 0xd0, 0xf4, 0x29, 0x29, 0x09, 0xf4, 0x1f, + 0x0d, 0x00, 0x5e, 0xe3, 0x94, 0x50, 0xb4, 0x4d, 0xfd, 0x7d, 0xd8, 0x06, 0xf5, 0xad, 0x51, 0x57, + 0xe9, 0x2b, 0x83, 0xa6, 0x5d, 0xdf, 0x1a, 0xc1, 0x87, 0xa0, 0x45, 0x0f, 0x63, 0x9c, 0x76, 0xeb, + 0x7d, 0x65, 0xb0, 0x60, 0x75, 0x2e, 0xc6, 0xda, 0xed, 0xc2, 0x8d, 0xc2, 0x67, 0xba, 0xd8, 0xd6, + 0x6d, 0x09, 0xc3, 0x3d, 0x30, 0x5f, 0x4d, 0xd6, 0x6d, 0xf4, 0x95, 0xc1, 0xe2, 0xc6, 0xaa, 0x21, + 0x47, 0x33, 0xaa, 0xd1, 0x8c, 0x51, 0x59, 0x60, 0x0d, 0x8f, 0xc7, 0x5a, 0xed, 0xf7, 0x58, 0x83, + 0x55, 0xcb, 0x1a, 0x8d, 0x48, 0x86, 0xa3, 0x24, 0x2b, 0x2e, 0xc6, 0xda, 0xb2, 0xe4, 0xaf, 0x30, + 0xfd, 0xf3, 0xa9, 0xa6, 0xd8, 0x13, 0x76, 0x68, 0x83, 0x79, 0x1c, 0x23, 0x87, 0x7f, 0x67, 0xb7, + 0x29, 0x4e, 0xea, 0xfd, 0x75, 0xd2, 0x4e, 0x25, 0x82, 0x75, 0x8f, 0x1f, 0x35, 0x25, 0xad, 0x3a, + 0xf5, 0x23, 0x4e, 0x7a, 0x0b, 0xc7, 0x88, 0x97, 0x42, 0x17, 0xb4, 0xb8, 0x24, 0xac, 0xdb, 0xea, + 0x37, 0xc4, 0xe8, 0x52, 0x34, 0x83, 0x8b, 0x66, 0x94, 0xa2, 0x19, 0x9b, 0x94, 0xc4, 0xd6, 0x63, + 0xce, 0xf7, 0xfd, 0x54, 0x1b, 0x04, 0x24, 0xdb, 0xcb, 0x3d, 0xc3, 0xa7, 0x91, 0x59, 0x2a, 0x2c, + 0x1f, 0xeb, 0x0c, 0xed, 0x9b, 0x59, 0x91, 0x60, 0x26, 0x1a, 0x98, 0x2d, 0x99, 0xe1, 0x2e, 0xb8, + 0x9b, 0xe2, 0x43, 0x37, 0x45, 0x4e, 0x8a, 0x7d, 0x4c, 0x0e, 0x70, 0xea, 0xb8, 0x08, 0xa5, 0x98, + 0xb1, 0xee, 0x9c, 0x90, 0x56, 0xbf, 0x18, 0x6b, 0xaa, 0x9c, 0xf2, 0x9a, 0x42, 0xdd, 0xbe, 0x23, + 0x11, 0xbb, 0x04, 0x5e, 0x94, 0xfb, 0x5f, 0xea, 0xa0, 0xfd, 0x26, 0xc7, 0x69, 0xb1, 0x49, 0x63, + 0x44, 0x84, 0x4a, 0x2f, 0xc1, 0x32, 0xcf, 0x95, 0xf3, 0x81, 0x6f, 0x3b, 0x7c, 0x1e, 0x61, 0x6a, + 0x7b, 0xe3, 0x81, 0x71, 0x39, 0x77, 0x06, 0xb7, 0x5d, 0x34, 0xef, 0x14, 0x09, 0xb6, 0x97, 0xc2, + 0xd9, 0x25, 0x5c, 0x01, 0x2d, 0x84, 0x63, 0x1a, 0x49, 0xfb, 0x6d, 0xb9, 0xe0, 0x16, 0xdc, 0xdc, + 0xec, 0x2b, 0x0e, 0x5c, 0x67, 0xeb, 0x3b, 0xb0, 0x30, 0x89, 0xee, 0x0d, 0x7c, 0xbd, 0x5f, 0xb2, + 0x76, 0x24, 0xeb, 0xa4, 0x55, 0x1a, 0x3b, 0xa5, 0xd2, 0xbf, 0xd6, 0xc1, 0xd2, 0xdb, 0x22, 0xce, + 0xf6, 0x70, 0x46, 0x7c, 0x11, 0xf1, 0x35, 0x00, 0xf3, 0x18, 0xe1, 0x34, 0x2c, 0x48, 0x1c, 0x38, + 0x42, 0x25, 0x82, 0xca, 0xc8, 0x77, 0xa6, 0x08, 0xaf, 0xdd, 0x42, 0x50, 0x03, 0x8b, 0x8c, 0xb7, + 0x3b, 0xb3, 0x3a, 0x00, 0xb1, 0x35, 0xaa, 0xc4, 0x98, 0xe4, 0xb1, 0xf1, 0x8f, 0xf2, 0x38, 0x7b, + 0x9b, 0x9a, 0xff, 0xf3, 0x36, 0x3d, 0x7a, 0x0e, 0x96, 0x2e, 0x05, 0x00, 0xb6, 0x01, 0xb0, 0x8a, + 0x8a, 0xbb, 0x53, 0x83, 0x00, 0xcc, 0x59, 0x05, 0x1f, 0xaa, 0xa3, 0xf0, 0xf7, 0x57, 0x94, 0x97, + 0x77, 0xea, 0xbd, 0xe6, 0xa7, 0x6f, 0x6a, 0xcd, 0xda, 0x3e, 0x3e, 0x53, 0x95, 0x93, 0x33, 0x55, + 0xf9, 0x75, 0xa6, 0x2a, 0x47, 0xe7, 0x6a, 0xed, 0xe4, 0x5c, 0xad, 0xfd, 0x3c, 0x57, 0x6b, 0xbb, + 0x1b, 0x33, 0x17, 0xa4, 0x4c, 0xdc, 0x7a, 0xe8, 0x7a, 0xac, 0x5a, 0x98, 0x07, 0xc3, 0xa7, 0xe6, + 0xc7, 0xea, 0xbf, 0x28, 0x2e, 0x8c, 0x37, 0x27, 0x3e, 0xee, 0xc9, 0x9f, 0x00, 0x00, 0x00, 0xff, + 0xff, 0x27, 0xff, 0x3d, 0x4a, 0x36, 0x05, 0x00, 0x00, } func (m *PeriodLock) Marshal() (dAtA []byte, err error) { diff --git a/x/pool-incentives/keeper/grpc_query_test.go b/x/pool-incentives/keeper/grpc_query_test.go index e963c422d02..20e48898394 100644 --- a/x/pool-incentives/keeper/grpc_query_test.go +++ b/x/pool-incentives/keeper/grpc_query_test.go @@ -242,7 +242,7 @@ func (s *KeeperTestSuite) TestIncentivizedPools() { LockQueryType: lockuptypes.ByDuration, Denom: "stake", Duration: time.Hour, - }, time.Now(), 1) + }, time.Now(), 1, 0) s.Require().NoError(err) distRecords = append(distRecords, types.DistrRecord{GaugeId: gaugePerpetualId, Weight: sdk.NewInt(300)}) } @@ -252,7 +252,7 @@ func (s *KeeperTestSuite) TestIncentivizedPools() { LockQueryType: lockuptypes.ByDuration, Denom: "stake", Duration: time.Hour, - }, time.Now(), 1) + }, time.Now(), 1, 0) s.Require().NoError(err) distRecords = append(distRecords, types.DistrRecord{GaugeId: gaugeNonPerpetualId, Weight: sdk.NewInt(100)}) } @@ -394,7 +394,7 @@ func (s *KeeperTestSuite) TestExternalIncentiveGauges() { LockQueryType: lockuptypes.ByDuration, Denom: "stake", Duration: time.Hour, - }, time.Now(), 1) + }, time.Now(), 1, 0) s.Require().NoError(err) } } diff --git a/x/pool-incentives/keeper/keeper.go b/x/pool-incentives/keeper/keeper.go index 0ce1db2067c..987b139c554 100644 --- a/x/pool-incentives/keeper/keeper.go +++ b/x/pool-incentives/keeper/keeper.go @@ -79,6 +79,7 @@ func (k Keeper) CreateLockablePoolGauges(ctx sdk.Context, poolId uint64) error { }, ctx.BlockTime(), 1, + 0, ) if err != nil { return err @@ -100,29 +101,26 @@ func (k Keeper) CreateConcentratedLiquidityPoolGauge(ctx sdk.Context, poolId uin return fmt.Errorf("pool %d is not concentrated liquidity pool", poolId) } - gaugeIdCL, err := k.incentivesKeeper.CreateGauge( + incentivesEpoch := k.incentivesKeeper.GetEpochInfo(ctx) + + _, err = k.incentivesKeeper.CreateGauge( ctx, true, k.accountKeeper.GetModuleAddress(types.ModuleName), sdk.Coins{}, - // dummy variable so that the existing logic does not break - // CreateGauge checks if LockQueryType is `ByDuration` or not, we bypass this check by passing - // lockQueryType as byTime. Although we do not need this check, we still cannot pass empty struct. lockuptypes.QueryCondition{ - LockQueryType: lockuptypes.ByTime, + LockQueryType: lockuptypes.NoLock, Denom: appParams.BaseCoinUnit, + Duration: incentivesEpoch.Duration, }, ctx.BlockTime(), 1, + poolId, ) if err != nil { return err } - incParams := k.incentivesKeeper.GetEpochInfo(ctx) - // lockable duration is epoch duration because we create incentive_record on every epoch - k.SetPoolGaugeId(ctx, poolId, incParams.Duration, gaugeIdCL) - return nil } diff --git a/x/pool-incentives/types/expected_keepers.go b/x/pool-incentives/types/expected_keepers.go index 626bd427feb..b6db0fb4878 100644 --- a/x/pool-incentives/types/expected_keepers.go +++ b/x/pool-incentives/types/expected_keepers.go @@ -32,7 +32,7 @@ type PoolManagerKeeper interface { // IncentivesKeeper creates and gets gauges, and also allows additions to gauge rewards. type IncentivesKeeper interface { - CreateGauge(ctx sdk.Context, isPerpetual bool, owner sdk.AccAddress, coins sdk.Coins, distrTo lockuptypes.QueryCondition, startTime time.Time, numEpochsPaidOver uint64) (uint64, error) + CreateGauge(ctx sdk.Context, isPerpetual bool, owner sdk.AccAddress, coins sdk.Coins, distrTo lockuptypes.QueryCondition, startTime time.Time, numEpochsPaidOver uint64, poolId uint64) (uint64, error) GetGaugeByID(ctx sdk.Context, gaugeID uint64) (*incentivestypes.Gauge, error) GetGauges(ctx sdk.Context) []incentivestypes.Gauge GetParams(ctx sdk.Context) incentivestypes.Params diff --git a/x/superfluid/keeper/intermediary_account.go b/x/superfluid/keeper/intermediary_account.go index d38e414124f..0aaaa79eca8 100644 --- a/x/superfluid/keeper/intermediary_account.go +++ b/x/superfluid/keeper/intermediary_account.go @@ -78,7 +78,7 @@ func (k Keeper) GetOrCreateIntermediaryAccount(ctx sdk.Context, denom, valAddr s // move this synthetic denom creation to a dedicated function Denom: stakingSyntheticDenom(denom, valAddr), Duration: k.sk.GetParams(ctx).UnbondingTime, - }, ctx.BlockTime(), 1) + }, ctx.BlockTime(), 1, 0) if err != nil { k.Logger(ctx).Error(err.Error()) return types.SuperfluidIntermediaryAccount{}, err diff --git a/x/superfluid/types/expected_keepers.go b/x/superfluid/types/expected_keepers.go index ecf7bb76f4e..1a0275c7b5a 100644 --- a/x/superfluid/types/expected_keepers.go +++ b/x/superfluid/types/expected_keepers.go @@ -91,7 +91,7 @@ type CommunityPoolKeeper interface { // IncentivesKeeper expected incentives keeper. type IncentivesKeeper interface { - CreateGauge(ctx sdk.Context, isPerpetual bool, owner sdk.AccAddress, coins sdk.Coins, distrTo lockuptypes.QueryCondition, startTime time.Time, numEpochsPaidOver uint64) (uint64, error) + CreateGauge(ctx sdk.Context, isPerpetual bool, owner sdk.AccAddress, coins sdk.Coins, distrTo lockuptypes.QueryCondition, startTime time.Time, numEpochsPaidOver uint64, poolId uint64) (uint64, error) AddToGaugeRewards(ctx sdk.Context, owner sdk.AccAddress, coins sdk.Coins, gaugeID uint64) error GetActiveGauges(ctx sdk.Context) []incentivestypes.Gauge