diff --git a/x/superfluid/keeper/distribution_test.go b/x/superfluid/keeper/distribution_test.go index 2662b921635..8d8a6c0bd3d 100644 --- a/x/superfluid/keeper/distribution_test.go +++ b/x/superfluid/keeper/distribution_test.go @@ -27,10 +27,10 @@ func (suite *KeeperTestSuite) allocateRewardsToValidator(valAddr sdk.ValAddress) func (suite *KeeperTestSuite) TestMoveSuperfluidDelegationRewardToGauges() { type gaugeChecker struct { - gaugeId uint64 - valIndex int64 - lpDenom string - rewarded bool + intermediaryAccIndex uint64 + valIndex int64 + lpIndex int64 + rewarded bool } testCases := []struct { name string @@ -44,33 +44,33 @@ func (suite *KeeperTestSuite) TestMoveSuperfluidDelegationRewardToGauges() { "happy path with single validator and delegator", []stakingtypes.BondStatus{stakingtypes.Bonded}, 1, - []superfluidDelegation{{0, 0, "gamm/pool/1", 1000000}}, + []superfluidDelegation{{0, 0, 0, 1000000}}, []int64{0}, - []gaugeChecker{{4, 0, "gamm/pool/1", true}}, + []gaugeChecker{{0, 0, 0, true}}, }, { "two LP tokens delegation to a single validator", []stakingtypes.BondStatus{stakingtypes.Bonded}, 2, - []superfluidDelegation{{0, 0, "gamm/pool/1", 1000000}, {0, 0, "gamm/pool/2", 1000000}}, + []superfluidDelegation{{0, 0, 0, 1000000}, {0, 0, 1, 1000000}}, []int64{0}, - []gaugeChecker{{4, 0, "gamm/pool/1", true}, {5, 0, "gamm/pool/2", true}}, + []gaugeChecker{{0, 0, 0, true}, {1, 0, 1, true}}, }, { "one LP token with two locks to a single validator", []stakingtypes.BondStatus{stakingtypes.Bonded}, 2, - []superfluidDelegation{{0, 0, "gamm/pool/1", 1000000}, {1, 0, "gamm/pool/1", 1000000}}, + []superfluidDelegation{{0, 0, 0, 1000000}, {1, 0, 0, 1000000}}, []int64{0}, - []gaugeChecker{{4, 0, "gamm/pool/1", true}}, + []gaugeChecker{{0, 0, 0, true}}, }, { "add unbonded validator case", []stakingtypes.BondStatus{stakingtypes.Bonded, stakingtypes.Unbonded}, 2, - []superfluidDelegation{{0, 0, "gamm/pool/1", 1000000}, {1, 1, "gamm/pool/1", 1000000}}, + []superfluidDelegation{{0, 0, 0, 1000000}, {1, 1, 0, 1000000}}, []int64{0}, - []gaugeChecker{{4, 0, "gamm/pool/1", true}, {5, 1, "gamm/pool/1", false}}, + []gaugeChecker{{0, 0, 0, true}, {1, 1, 0, false}}, }, } @@ -86,8 +86,10 @@ func (suite *KeeperTestSuite) TestMoveSuperfluidDelegationRewardToGauges() { // setup validators valAddrs := suite.SetupValidators(tc.validatorStats) + denoms, _ := suite.SetupGammPoolsAndSuperfluidAssets([]sdk.Dec{sdk.NewDec(20), sdk.NewDec(20)}) + // setup superfluid delegations - suite.SetupSuperfluidDelegations(delAddrs, valAddrs, tc.superDelegations) + intermediaryAccs, _ := suite.SetupSuperfluidDelegations(delAddrs, valAddrs, tc.superDelegations, denoms) unbondingDuration := suite.App.StakingKeeper.GetParams(suite.Ctx).UnbondingTime // allocate rewards to first validator @@ -100,13 +102,14 @@ func (suite *KeeperTestSuite) TestMoveSuperfluidDelegationRewardToGauges() { // check gauge balance for _, gaugeCheck := range tc.gaugeChecks { - gauge, err := suite.App.IncentivesKeeper.GetGaugeByID(suite.Ctx, gaugeCheck.gaugeId) + gaugeId := intermediaryAccs[gaugeCheck.intermediaryAccIndex].GaugeId + gauge, err := suite.App.IncentivesKeeper.GetGaugeByID(suite.Ctx, gaugeId) suite.Require().NoError(err) - suite.Require().Equal(gauge.Id, gaugeCheck.gaugeId) + suite.Require().Equal(gauge.Id, gaugeId) suite.Require().Equal(gauge.IsPerpetual, true) suite.Require().Equal(lockuptypes.QueryCondition{ LockQueryType: lockuptypes.ByDuration, - Denom: keeper.StakingSyntheticDenom(gaugeCheck.lpDenom, valAddrs[gaugeCheck.valIndex].String()), + Denom: keeper.StakingSyntheticDenom(denoms[gaugeCheck.lpIndex], valAddrs[gaugeCheck.valIndex].String()), Duration: unbondingDuration, }, gauge.DistributeTo) if gaugeCheck.rewarded { diff --git a/x/superfluid/keeper/grpc_query_test.go b/x/superfluid/keeper/grpc_query_test.go index 56dd151b787..cfdad362424 100644 --- a/x/superfluid/keeper/grpc_query_test.go +++ b/x/superfluid/keeper/grpc_query_test.go @@ -47,31 +47,29 @@ func (suite *KeeperTestSuite) TestGRPCQuerySuperfluidDelegations() { // setup 2 validators valAddrs := suite.SetupValidators([]stakingtypes.BondStatus{stakingtypes.Bonded, stakingtypes.Bonded}) - denoms := []string{"gamm/pool/1", "gamm/pool/2"} + denoms, _ := suite.SetupGammPoolsAndSuperfluidAssets([]sdk.Dec{sdk.NewDec(20), sdk.NewDec(20)}) // create a delegation of 1000000 for every combination of 2 delegations, 2 validators, and 2 superfluid denoms superfluidDelegations := []superfluidDelegation{ - {0, 0, denoms[0], 1000000}, - - {0, 1, denoms[1], 1000000}, - - {1, 0, denoms[1], 1000000}, - - {1, 1, denoms[0], 1000000}, + {0, 0, 0, 1000000}, + {0, 1, 1, 1000000}, + {1, 0, 1, 1000000}, + {1, 1, 0, 1000000}, } // setup superfluid delegations - suite.SetupSuperfluidDelegations(delAddrs, valAddrs, superfluidDelegations) + suite.SetupSuperfluidDelegations(delAddrs, valAddrs, superfluidDelegations, denoms) // for each superfluid delegation, query the amount and make sure it is 1000000 for _, delegation := range superfluidDelegations { + lpDenom := denoms[delegation.lpIndex] res, err := suite.queryClient.SuperfluidDelegationAmount(sdk.WrapSDKContext(suite.Ctx), &types.SuperfluidDelegationAmountRequest{ DelegatorAddress: delAddrs[delegation.delIndex].String(), ValidatorAddress: valAddrs[delegation.valIndex].String(), - Denom: delegation.lpDenom, + Denom: lpDenom, }) suite.Require().NoError(err) - suite.Require().Equal(res.Amount.AmountOf(delegation.lpDenom).Int64(), delegation.lpAmount) + suite.Require().Equal(res.Amount.AmountOf(lpDenom).Int64(), delegation.lpAmount) } // for each delegator, query all their superfluid delegations and make sure they have 2 delegations @@ -82,8 +80,8 @@ func (suite *KeeperTestSuite) TestGRPCQuerySuperfluidDelegations() { suite.Require().NoError(err) suite.Require().Len(res.SuperfluidDelegationRecords, 2) suite.Require().True(res.TotalDelegatedCoins.IsEqual(sdk.NewCoins( - sdk.NewInt64Coin("gamm/pool/1", 1000000), - sdk.NewInt64Coin("gamm/pool/2", 1000000), + sdk.NewInt64Coin(denoms[0], 1000000), + sdk.NewInt64Coin(denoms[1], 1000000), ))) } @@ -110,7 +108,6 @@ func (suite *KeeperTestSuite) TestGRPCQuerySuperfluidDelegations() { totalSuperfluidDelegationsRes, err := suite.queryClient.TotalSuperfluidDelegations(sdk.WrapSDKContext(suite.Ctx), &types.TotalSuperfluidDelegationsRequest{}) suite.Require().NoError(err) suite.Require().Equal(sdk.NewInt(40000000), totalSuperfluidDelegationsRes.TotalDelegations) - } func (suite *KeeperTestSuite) TestGRPCQuerySuperfluidDelegationsDontIncludeUnbonding() { @@ -122,21 +119,18 @@ func (suite *KeeperTestSuite) TestGRPCQuerySuperfluidDelegationsDontIncludeUnbon // setup 2 validators valAddrs := suite.SetupValidators([]stakingtypes.BondStatus{stakingtypes.Bonded, stakingtypes.Bonded}) - denoms := []string{"gamm/pool/1", "gamm/pool/2"} + denoms, _ := suite.SetupGammPoolsAndSuperfluidAssets([]sdk.Dec{sdk.NewDec(20), sdk.NewDec(20)}) // create a delegation of 1000000 for every combination of 2 delegations, 2 validators, and 2 superfluid denoms superfluidDelegations := []superfluidDelegation{ - {0, 0, denoms[0], 1000000}, - - {0, 1, denoms[1], 1000000}, - - {1, 0, denoms[1], 1000000}, - - {1, 1, denoms[0], 1000000}, + {0, 0, 0, 1000000}, + {0, 1, 1, 1000000}, + {1, 0, 1, 1000000}, + {1, 1, 0, 1000000}, } // setup superfluid delegations - _, locks := suite.SetupSuperfluidDelegations(delAddrs, valAddrs, superfluidDelegations) + _, locks := suite.SetupSuperfluidDelegations(delAddrs, valAddrs, superfluidDelegations, denoms) // start unbonding the superfluid delegations of denom0 from delegator0 to validator0 err := suite.App.SuperfluidKeeper.SuperfluidUndelegate(suite.Ctx, locks[0].Owner, locks[0].ID) @@ -158,7 +152,7 @@ func (suite *KeeperTestSuite) TestGRPCQuerySuperfluidDelegationsDontIncludeUnbon suite.Require().NoError(err) suite.Require().Len(res2.SuperfluidDelegationRecords, 1) suite.Require().Equal(sdk.NewCoins( - sdk.NewInt64Coin("gamm/pool/2", 1000000)), res2.TotalDelegatedCoins) + sdk.NewInt64Coin(denoms[1], 1000000)), res2.TotalDelegatedCoins) // query to make sure that the unbonding delegation is not included in the validator denom pair query amountRes, err := suite.queryClient.EstimateSuperfluidDelegatedAmountByValidatorDenom(sdk.WrapSDKContext(suite.Ctx), &types.EstimateSuperfluidDelegatedAmountByValidatorDenomRequest{ diff --git a/x/superfluid/keeper/hooks_test.go b/x/superfluid/keeper/hooks_test.go index db79912b39c..8016836d8e2 100644 --- a/x/superfluid/keeper/hooks_test.go +++ b/x/superfluid/keeper/hooks_test.go @@ -17,7 +17,7 @@ func (suite *KeeperTestSuite) TestSuperfluidAfterEpochEnd() { { "happy path with single validator and delegator", []stakingtypes.BondStatus{stakingtypes.Bonded}, - []superfluidDelegation{{0, 0, "gamm/pool/1", 1000000}}, + []superfluidDelegation{{0, 0, 0, 1000000}}, sdk.Coins{}, }, } @@ -26,29 +26,35 @@ func (suite *KeeperTestSuite) TestSuperfluidAfterEpochEnd() { suite.Run(tc.name, func() { suite.SetupTest() valAddrs := suite.SetupValidators(tc.validatorStats) - bondDenom := suite.App.StakingKeeper.BondDenom(suite.Ctx) + + denoms, poolIds := suite.SetupGammPoolsAndSuperfluidAssets([]sdk.Dec{sdk.NewDec(20), sdk.NewDec(20)}) // Generate delegator addresses delAddrs := CreateRandomAccounts(1) - intermediaryAccs, _ := suite.SetupSuperfluidDelegations(delAddrs, valAddrs, tc.superDelegations) + intermediaryAccs, _ := suite.SetupSuperfluidDelegations(delAddrs, valAddrs, tc.superDelegations, denoms) suite.checkIntermediaryAccountDelegations(intermediaryAccs) // gamm swap operation before refresh - suite.App.SuperfluidKeeper.SetOsmoEquivalentMultiplier(suite.Ctx, 2, "gamm/pool/1", sdk.NewDec(10)) acc1 := sdk.AccAddress(ed25519.GenPrivKey().PubKey().Address().Bytes()) + pool, err := suite.App.GAMMKeeper.GetPool(suite.Ctx, poolIds[0]) + suite.Require().NoError(err) + poolAssets := pool.GetAllPoolAssets() - coins := sdk.Coins{sdk.NewInt64Coin("foo", 100000000000000)} - err := simapp.FundAccount(suite.App.BankKeeper, suite.Ctx, acc1, coins) + coins := sdk.Coins{sdk.NewInt64Coin(poolAssets[1].Token.Denom, 100000000000000)} + err = simapp.FundAccount(suite.App.BankKeeper, suite.Ctx, acc1, coins) suite.Require().NoError(err) - _, _, err = suite.App.GAMMKeeper.SwapExactAmountOut(suite.Ctx, acc1, 1, "foo", sdk.NewInt(100000000000000), sdk.NewInt64Coin(bondDenom, 250000000000)) + _, _, err = suite.App.GAMMKeeper.SwapExactAmountOut( + suite.Ctx, acc1, + poolIds[0], poolAssets[1].Token.Denom, poolAssets[1].Token.Amount, + sdk.NewCoin(poolAssets[0].Token.Denom, poolAssets[0].Token.Amount.Quo(sdk.NewInt(4)))) suite.Require().NoError(err) // run epoch actions suite.BeginNewBlock(true) // check lptoken twap value set - newEpochTwap := suite.App.SuperfluidKeeper.GetOsmoEquivalentMultiplier(suite.Ctx, "gamm/pool/1") - suite.Require().Equal(newEpochTwap.String(), "0.009999997500000000") + newEpochTwap := suite.App.SuperfluidKeeper.GetOsmoEquivalentMultiplier(suite.Ctx, denoms[0]) + suite.Require().Equal(newEpochTwap.String(), "15.000000000000000000") // check delegation changes for _, acc := range intermediaryAccs { @@ -56,7 +62,7 @@ func (suite *KeeperTestSuite) TestSuperfluidAfterEpochEnd() { suite.Require().NoError(err) delegation, found := suite.App.StakingKeeper.GetDelegation(suite.Ctx, acc.GetAccAddress(), valAddr) suite.Require().True(found) - suite.Require().Equal(sdk.NewDec(5000), delegation.Shares) + suite.Require().Equal(sdk.NewDec(7500000), delegation.Shares) // TODO: Check reward distribution // suite.Require().NotEqual(sdk.Coins{}, ) } @@ -136,14 +142,14 @@ func (suite *KeeperTestSuite) TestSuperfluidAfterEpochEnd() { // for index, lockId := range tc.unbondingLockIds { // // get intermediary account -// accAddr := suite.app.SuperfluidKeeper.GetLockIdIntermediaryAccountConnection(suite.Ctx, lockId) -// intermediaryAcc := suite.app.SuperfluidKeeper.GetIntermediaryAccount(suite.Ctx, accAddr) +// accAddr := suite.App.SuperfluidKeeper.GetLockIdIntermediaryAccountConnection(suite.Ctx, lockId) +// intermediaryAcc := suite.App.SuperfluidKeeper.GetIntermediaryAccount(suite.Ctx, accAddr) // valAddr := intermediaryAcc.ValAddr // // unlock native lockup -// lock, err := suite.app.LockupKeeper.GetLockByID(suite.Ctx, lockId) +// lock, err := suite.App.LockupKeeper.GetLockByID(suite.Ctx, lockId) // if err == nil { -// err = suite.app.LockupKeeper.BeginUnlock(suite.Ctx, *lock, nil) +// err = suite.App.LockupKeeper.BeginUnlock(suite.Ctx, *lock, nil) // } // if tc.expUnbondingErr[index] { @@ -153,16 +159,16 @@ func (suite *KeeperTestSuite) TestSuperfluidAfterEpochEnd() { // suite.Require().NoError(err) // // check lockId and intermediary account connection deletion -// addr := suite.app.SuperfluidKeeper.GetLockIdIntermediaryAccountConnection(suite.Ctx, lockId) +// addr := suite.App.SuperfluidKeeper.GetLockIdIntermediaryAccountConnection(suite.Ctx, lockId) // suite.Require().Equal(addr.String(), "") // // check bonding synthetic lockup deletion -// _, err = suite.app.LockupKeeper.GetSyntheticLockup(suite.Ctx, lockId, keeper.StakingSyntheticDenom(lock.Coins[0].Denom, valAddr)) +// _, err = suite.App.LockupKeeper.GetSyntheticLockup(suite.Ctx, lockId, keeper.StakingSyntheticDenom(lock.Coins[0].Denom, valAddr)) // suite.Require().Error(err) // // check unbonding synthetic lockup creation -// unbondingDuration := suite.app.StakingKeeper.GetParams(suite.Ctx).UnbondingTime -// synthLock, err := suite.app.LockupKeeper.GetSyntheticLockup(suite.Ctx, lockId, keeper.UnstakingSyntheticDenom(lock.Coins[0].Denom, valAddr)) +// unbondingDuration := suite.App.StakingKeeper.GetParams(suite.Ctx).UnbondingTime +// synthLock, err := suite.App.LockupKeeper.GetSyntheticLockup(suite.Ctx, lockId, keeper.UnstakingSyntheticDenom(lock.Coins[0].Denom, valAddr)) // suite.Require().NoError(err) // suite.Require().Equal(synthLock.UnderlyingLockId, lockId) // suite.Require().Equal(synthLock.SynthDenom, keeper.UnstakingSyntheticDenom(lock.Coins[0].Denom, valAddr)) @@ -187,7 +193,7 @@ func (suite *KeeperTestSuite) TestBeforeSlashingUnbondingDelegationHook() { "happy path with single validator and multiple superfluid delegations", []stakingtypes.BondStatus{stakingtypes.Bonded}, 1, - []superfluidDelegation{{0, 0, "gamm/pool/1", 1000000}}, + []superfluidDelegation{{0, 0, 0, 1000000}}, []uint64{1}, []int64{0}, []uint64{1}, @@ -197,7 +203,7 @@ func (suite *KeeperTestSuite) TestBeforeSlashingUnbondingDelegationHook() { "with single validator and multiple superfluid delegations", []stakingtypes.BondStatus{stakingtypes.Bonded}, 2, - []superfluidDelegation{{0, 0, "gamm/pool/1", 1000000}, {1, 0, "gamm/pool/1", 1000000}}, + []superfluidDelegation{{0, 0, 0, 1000000}, {1, 0, 0, 1000000}}, []uint64{1, 2}, []int64{0}, []uint64{1, 2}, @@ -207,7 +213,7 @@ func (suite *KeeperTestSuite) TestBeforeSlashingUnbondingDelegationHook() { "with multiple validators and multiple superfluid delegations", []stakingtypes.BondStatus{stakingtypes.Bonded, stakingtypes.Bonded}, 2, - []superfluidDelegation{{0, 0, "gamm/pool/1", 1000000}, {1, 1, "gamm/pool/1", 1000000}}, + []superfluidDelegation{{0, 0, 0, 1000000}, {1, 1, 0, 1000000}}, []uint64{1, 2}, []int64{0}, []uint64{1}, @@ -228,8 +234,11 @@ func (suite *KeeperTestSuite) TestBeforeSlashingUnbondingDelegationHook() { // setup validators valAddrs := suite.SetupValidators(tc.validatorStats) + + denoms, _ := suite.SetupGammPoolsAndSuperfluidAssets([]sdk.Dec{sdk.NewDec(20), sdk.NewDec(20)}) + // setup superfluid delegations - intermediaryAccs, _ := suite.SetupSuperfluidDelegations(delAddrs, valAddrs, tc.superDelegations) + intermediaryAccs, _ := suite.SetupSuperfluidDelegations(delAddrs, valAddrs, tc.superDelegations, denoms) suite.checkIntermediaryAccountDelegations(intermediaryAccs) for _, lockId := range tc.superUnbondingLockIds { @@ -258,14 +267,14 @@ func (suite *KeeperTestSuite) TestBeforeSlashingUnbondingDelegationHook() { for _, lockId := range tc.expSlashedLockIds { gotLock, err := suite.App.LockupKeeper.GetLockByID(suite.Ctx, lockId) suite.Require().NoError(err) - suite.Require().Equal(sdk.NewInt(950000).String(), gotLock.Coins.AmountOf("gamm/pool/1").String()) + suite.Require().Equal(sdk.NewInt(950000).String(), gotLock.Coins.AmountOf(denoms[0]).String()) } // check unslashed lockups for _, lockId := range tc.expUnslashedLockIds { gotLock, err := suite.App.LockupKeeper.GetLockByID(suite.Ctx, lockId) suite.Require().NoError(err) - suite.Require().Equal(sdk.NewInt(1000000).String(), gotLock.Coins.AmountOf("gamm/pool/1").String()) + suite.Require().Equal(sdk.NewInt(1000000).String(), gotLock.Coins.AmountOf(denoms[0]).String()) } }) } diff --git a/x/superfluid/keeper/keeper_test.go b/x/superfluid/keeper/keeper_test.go index 8b17d7b8f7a..0e6b055ec85 100644 --- a/x/superfluid/keeper/keeper_test.go +++ b/x/superfluid/keeper/keeper_test.go @@ -157,6 +157,70 @@ func (suite *KeeperTestSuite) SetupValidators(bondStatuses []stakingtypes.BondSt return valAddrs } +func (suite *KeeperTestSuite) SetupGammPoolsAndSuperfluidAssets(multipliers []sdk.Dec) ([]string, []uint64) { + suite.App.GAMMKeeper.SetParams(suite.Ctx, gammtypes.Params{ + PoolCreationFee: sdk.Coins{}, + }) + + bondDenom := suite.App.StakingKeeper.BondDenom(suite.Ctx) + + acc1 := sdk.AccAddress(ed25519.GenPrivKey().PubKey().Address().Bytes()) + denoms := []string{} + poolIds := []uint64{} + + for index, multiplier := range multipliers { + token := fmt.Sprintf("token%d", index) + + uosmoAmount := gammtypes.InitPoolSharesSupply.ToDec().Mul(multiplier).RoundInt() + + err := simapp.FundAccount(suite.App.BankKeeper, suite.Ctx, acc1, sdk.NewCoins( + sdk.NewCoin(bondDenom, uosmoAmount.Mul(sdk.NewInt(10))), + sdk.NewInt64Coin(token, 100000), + )) + suite.NoError(err) + + var ( + defaultFutureGovernor = "" + + // pool assets + defaultFooAsset gammtypes.PoolAsset = gammtypes.PoolAsset{ + Weight: sdk.NewInt(100), + Token: sdk.NewCoin(bondDenom, uosmoAmount), + } + defaultBarAsset gammtypes.PoolAsset = gammtypes.PoolAsset{ + Weight: sdk.NewInt(100), + Token: sdk.NewCoin(token, sdk.NewInt(10000)), + } + poolAssets []gammtypes.PoolAsset = []gammtypes.PoolAsset{defaultFooAsset, defaultBarAsset} + ) + + poolId, err := suite.App.GAMMKeeper.CreateBalancerPool(suite.Ctx, acc1, balancer.PoolParams{ + SwapFee: sdk.NewDecWithPrec(1, 2), + ExitFee: sdk.NewDecWithPrec(1, 2), + }, poolAssets, defaultFutureGovernor) + suite.Require().NoError(err) + + pool, err := suite.App.GAMMKeeper.GetPool(suite.Ctx, poolId) + suite.Require().NoError(err) + + denom := pool.GetTotalShares().Denom + suite.App.SuperfluidKeeper.AddNewSuperfluidAsset(suite.Ctx, types.SuperfluidAsset{ + Denom: denom, + AssetType: types.SuperfluidAssetTypeLPShare, + }) + + // register a LP token as a superfluid asset + suite.App.SuperfluidKeeper.AddNewSuperfluidAsset(suite.Ctx, types.SuperfluidAsset{ + Denom: denom, + AssetType: types.SuperfluidAssetTypeLPShare, + }) + + poolIds = append(poolIds, poolId) + denoms = append(denoms, denom) + } + return denoms, poolIds +} + func TestKeeperTestSuite(t *testing.T) { suite.Run(t, new(KeeperTestSuite)) } diff --git a/x/superfluid/keeper/slash_test.go b/x/superfluid/keeper/slash_test.go index 55f0654bdcc..f9ff527de45 100644 --- a/x/superfluid/keeper/slash_test.go +++ b/x/superfluid/keeper/slash_test.go @@ -19,7 +19,7 @@ func (suite *KeeperTestSuite) TestBeforeValidatorSlashed() { "with single validator and single superfluid delegation", []stakingtypes.BondStatus{stakingtypes.Bonded}, 1, - []superfluidDelegation{{0, 0, "gamm/pool/1", 1000000}}, + []superfluidDelegation{{0, 0, 0, 1000000}}, []int64{0}, []int64{0}, }, @@ -27,7 +27,7 @@ func (suite *KeeperTestSuite) TestBeforeValidatorSlashed() { "with single validator and multiple superfluid delegations", []stakingtypes.BondStatus{stakingtypes.Bonded}, 2, - []superfluidDelegation{{0, 0, "gamm/pool/1", 1000000}, {1, 0, "gamm/pool/1", 1000000}}, + []superfluidDelegation{{0, 0, 0, 1000000}, {1, 0, 0, 1000000}}, []int64{0}, []int64{0, 1}, }, @@ -35,7 +35,7 @@ func (suite *KeeperTestSuite) TestBeforeValidatorSlashed() { "with multiple validators and multiple superfluid delegations with single validator slash", []stakingtypes.BondStatus{stakingtypes.Bonded, stakingtypes.Bonded}, 2, - []superfluidDelegation{{0, 0, "gamm/pool/1", 1000000}, {1, 1, "gamm/pool/1", 1000000}}, + []superfluidDelegation{{0, 0, 0, 1000000}, {1, 1, 0, 1000000}}, []int64{0}, []int64{0}, }, @@ -43,7 +43,7 @@ func (suite *KeeperTestSuite) TestBeforeValidatorSlashed() { "with multiple validators and multiple superfluid delegations with two validators slash", []stakingtypes.BondStatus{stakingtypes.Bonded, stakingtypes.Bonded}, 2, - []superfluidDelegation{{0, 0, "gamm/pool/1", 1000000}, {1, 1, "gamm/pool/1", 1000000}}, + []superfluidDelegation{{0, 0, 0, 1000000}, {1, 1, 0, 1000000}}, []int64{0, 1}, []int64{0, 1}, }, @@ -61,6 +61,8 @@ func (suite *KeeperTestSuite) TestBeforeValidatorSlashed() { // setup validators valAddrs := suite.SetupValidators(tc.validatorStats) + denoms, _ := suite.SetupGammPoolsAndSuperfluidAssets([]sdk.Dec{sdk.NewDec(20), sdk.NewDec(20)}) + locks := []lockuptypes.PeriodLock{} slashFactor := sdk.NewDecWithPrec(5, 2) @@ -68,7 +70,7 @@ func (suite *KeeperTestSuite) TestBeforeValidatorSlashed() { for _, del := range tc.superDelegations { valAddr := valAddrs[del.valIndex] delAddr := delAddrs[del.delIndex] - lock := suite.SetupSuperfluidDelegate(delAddr, valAddr, del.lpDenom, del.lpAmount) + lock := suite.SetupSuperfluidDelegate(delAddr, valAddr, denoms[del.lpIndex], del.lpAmount) // save accounts and locks for future use locks = append(locks, lock) @@ -92,7 +94,7 @@ func (suite *KeeperTestSuite) TestBeforeValidatorSlashed() { gotLock, err := suite.App.LockupKeeper.GetLockByID(suite.Ctx, locks[lockIndex].ID) suite.Require().NoError(err) suite.Require().Equal( - gotLock.Coins.AmountOf("gamm/pool/1").String(), + gotLock.Coins.AmountOf(denoms[0]).String(), sdk.NewDec(1000000).Mul(sdk.OneDec().Sub(slashFactor)).TruncateInt().String(), ) } @@ -112,21 +114,21 @@ func (suite *KeeperTestSuite) TestSlashLockupsForUnbondingDelegationSlash() { "happy path with single validator and multiple superfluid delegations", []stakingtypes.BondStatus{stakingtypes.Bonded}, 1, - []superfluidDelegation{{0, 0, "gamm/pool/1", 1000000}}, + []superfluidDelegation{{0, 0, 0, 1000000}}, []uint64{1}, }, { "with single validator and multiple superfluid delegations", []stakingtypes.BondStatus{stakingtypes.Bonded}, 2, - []superfluidDelegation{{0, 0, "gamm/pool/1", 1000000}, {1, 0, "gamm/pool/1", 1000000}}, + []superfluidDelegation{{0, 0, 0, 1000000}, {1, 0, 0, 1000000}}, []uint64{1, 2}, }, { "with multiple validators and multiple superfluid delegations", []stakingtypes.BondStatus{stakingtypes.Bonded, stakingtypes.Bonded}, 2, - []superfluidDelegation{{0, 0, "gamm/pool/1", 1000000}, {1, 1, "gamm/pool/1", 1000000}}, + []superfluidDelegation{{0, 0, 0, 1000000}, {1, 1, 0, 1000000}}, []uint64{1, 2}, }, } @@ -142,8 +144,11 @@ func (suite *KeeperTestSuite) TestSlashLockupsForUnbondingDelegationSlash() { // setup validators valAddrs := suite.SetupValidators(tc.validatorStats) + + denoms, _ := suite.SetupGammPoolsAndSuperfluidAssets([]sdk.Dec{sdk.NewDec(20), sdk.NewDec(20)}) + // setup superfluid delegations - intermediaryAccs, _ := suite.SetupSuperfluidDelegations(delAddrs, valAddrs, tc.superDelegations) + intermediaryAccs, _ := suite.SetupSuperfluidDelegations(delAddrs, valAddrs, tc.superDelegations, denoms) suite.checkIntermediaryAccountDelegations(intermediaryAccs) for _, lockId := range tc.superUnbondingLockIds { @@ -168,7 +173,7 @@ func (suite *KeeperTestSuite) TestSlashLockupsForUnbondingDelegationSlash() { for _, lockId := range tc.superUnbondingLockIds { gotLock, err := suite.App.LockupKeeper.GetLockByID(suite.Ctx, lockId) suite.Require().NoError(err) - suite.Require().Equal(gotLock.Coins.AmountOf("gamm/pool/1").String(), sdk.NewInt(950000).String()) + suite.Require().Equal(gotLock.Coins[0].Amount.String(), sdk.NewInt(950000).String()) } }) } diff --git a/x/superfluid/keeper/stake.go b/x/superfluid/keeper/stake.go index b49fa8f8087..8303d13a68f 100644 --- a/x/superfluid/keeper/stake.go +++ b/x/superfluid/keeper/stake.go @@ -327,6 +327,9 @@ func (k Keeper) forceUndelegateAndBurnOsmoTokens(ctx sdk.Context, return err } err = k.bk.BurnCoins(cacheCtx, types.ModuleName, undelegatedCoins) + if err != nil { + return err + } bondDenom := k.sk.BondDenom(cacheCtx) k.bk.AddSupplyOffset(cacheCtx, bondDenom, undelegatedCoins.AmountOf(bondDenom)) diff --git a/x/superfluid/keeper/stake_test.go b/x/superfluid/keeper/stake_test.go index 41af5640fbb..bbe3808378b 100644 --- a/x/superfluid/keeper/stake_test.go +++ b/x/superfluid/keeper/stake_test.go @@ -5,7 +5,6 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" - epochstypes "github.com/osmosis-labs/osmosis/v7/x/epochs/types" lockuptypes "github.com/osmosis-labs/osmosis/v7/x/lockup/types" minttypes "github.com/osmosis-labs/osmosis/v7/x/mint/types" "github.com/osmosis-labs/osmosis/v7/x/superfluid/keeper" @@ -15,7 +14,7 @@ import ( type superfluidDelegation struct { delIndex int64 valIndex int64 - lpDenom string + lpIndex int64 lpAmount int64 } type superfluidRedelegation struct { @@ -34,7 +33,7 @@ type osmoEquivalentMultiplier struct { price sdk.Dec } -func (suite *KeeperTestSuite) SetupSuperfluidDelegations(delAddrs []sdk.AccAddress, valAddrs []sdk.ValAddress, superDelegations []superfluidDelegation) ([]types.SuperfluidIntermediaryAccount, []lockuptypes.PeriodLock) { +func (suite *KeeperTestSuite) SetupSuperfluidDelegations(delAddrs []sdk.AccAddress, valAddrs []sdk.ValAddress, superDelegations []superfluidDelegation, denoms []string) ([]types.SuperfluidIntermediaryAccount, []lockuptypes.PeriodLock) { flagIntermediaryAcc := make(map[string]bool) intermediaryAccs := []types.SuperfluidIntermediaryAccount{} locks := []lockuptypes.PeriodLock{} @@ -47,13 +46,14 @@ func (suite *KeeperTestSuite) SetupSuperfluidDelegations(delAddrs []sdk.AccAddre for _, del := range superDelegations { delAddr := delAddrs[del.delIndex] valAddr := valAddrs[del.valIndex] - lock := suite.SetupSuperfluidDelegate(delAddr, valAddr, del.lpDenom, del.lpAmount) - expAcc := types.NewSuperfluidIntermediaryAccount(lock.Coins[0].Denom, valAddr.String(), 0) + lock := suite.SetupSuperfluidDelegate(delAddr, valAddr, denoms[del.lpIndex], del.lpAmount) + address := suite.App.SuperfluidKeeper.GetLockIdIntermediaryAccountConnection(suite.Ctx, lock.ID) + gotAcc := suite.App.SuperfluidKeeper.GetIntermediaryAccount(suite.Ctx, address) // save accounts for future use - if flagIntermediaryAcc[expAcc.String()] == false { - flagIntermediaryAcc[expAcc.String()] = true - intermediaryAccs = append(intermediaryAccs, expAcc) + if flagIntermediaryAcc[gotAcc.String()] == false { + flagIntermediaryAcc[gotAcc.String()] = true + intermediaryAccs = append(intermediaryAccs, gotAcc) } // save locks for future use locks = append(locks, lock) @@ -82,20 +82,6 @@ func (suite *KeeperTestSuite) checkIntermediaryAccountDelegations(intermediaryAc func (suite *KeeperTestSuite) SetupSuperfluidDelegate(delAddr sdk.AccAddress, valAddr sdk.ValAddress, denom string, amount int64) lockuptypes.PeriodLock { unbondingDuration := suite.App.StakingKeeper.GetParams(suite.Ctx).UnbondingTime - // register a LP token as a superfluid asset - suite.App.SuperfluidKeeper.SetSuperfluidAsset(suite.Ctx, types.SuperfluidAsset{ - Denom: denom, - AssetType: types.SuperfluidAssetTypeLPShare, - }) - - // set OSMO TWAP price for LP token - suite.App.SuperfluidKeeper.SetOsmoEquivalentMultiplier(suite.Ctx, 1, denom, sdk.NewDec(20)) - epochIdentifier := suite.App.SuperfluidKeeper.GetEpochIdentifier(suite.Ctx) - suite.App.EpochsKeeper.SetEpochInfo(suite.Ctx, epochstypes.EpochInfo{ - Identifier: epochIdentifier, - CurrentEpoch: 2, - }) - // create lockup of LP token coins := sdk.Coins{sdk.NewInt64Coin(denom, amount)} lastLockID := suite.App.LockupKeeper.GetLastLockID(suite.Ctx) @@ -141,21 +127,21 @@ func (suite *KeeperTestSuite) TestSuperfluidDelegate() { "with single validator and single superfluid delegation", []stakingtypes.BondStatus{stakingtypes.Bonded}, 1, - []superfluidDelegation{{0, 0, "gamm/pool/1", 1000000}}, + []superfluidDelegation{{0, 0, 0, 1000000}}, []sdk.Dec{sdk.NewDec(10000000)}, // 50% x 20 x 1000000 }, { "with single validator and additional superfluid delegations", []stakingtypes.BondStatus{stakingtypes.Bonded}, 1, - []superfluidDelegation{{0, 0, "gamm/pool/1", 1000000}, {0, 0, "gamm/pool/1", 1000000}}, + []superfluidDelegation{{0, 0, 0, 1000000}, {0, 0, 0, 1000000}}, []sdk.Dec{sdk.NewDec(20000000)}, // 50% x 20 x 1000000 x 2 }, { - "with multiples validator and multiple superfluid delegations", + "with multiple validators and multiple superfluid delegations", []stakingtypes.BondStatus{stakingtypes.Bonded, stakingtypes.Bonded}, 2, - []superfluidDelegation{{0, 0, "gamm/pool/1", 1000000}, {1, 1, "gamm/pool/1", 1000000}}, + []superfluidDelegation{{0, 0, 0, 1000000}, {1, 1, 0, 1000000}}, []sdk.Dec{sdk.NewDec(10000000), sdk.NewDec(10000000)}, // 50% x 20 x 1000000 }, } @@ -172,18 +158,21 @@ func (suite *KeeperTestSuite) TestSuperfluidDelegate() { // setup validators valAddrs := suite.SetupValidators(tc.validatorStats) + denoms, _ := suite.SetupGammPoolsAndSuperfluidAssets([]sdk.Dec{sdk.NewDec(20), sdk.NewDec(20)}) + // get pre-superfluid delgations osmo supply and supplyWithOffset presupply := suite.App.BankKeeper.GetSupply(suite.Ctx, bondDenom) presupplyWithOffset := suite.App.BankKeeper.GetSupplyWithOffset(suite.Ctx, bondDenom) // setup superfluid delegations - intermediaryAccs, locks := suite.SetupSuperfluidDelegations(delAddrs, valAddrs, tc.superDelegations) + _, _, _ = delAddrs, valAddrs, denoms + intermediaryAccs, locks := suite.SetupSuperfluidDelegations(delAddrs, valAddrs, tc.superDelegations, denoms) // ensure post-superfluid delegations osmo supplywithoffset is the same while supply is not postsupply := suite.App.BankKeeper.GetSupply(suite.Ctx, bondDenom) postsupplyWithOffset := suite.App.BankKeeper.GetSupplyWithOffset(suite.Ctx, bondDenom) suite.Require().False(postsupply.IsEqual(presupply), "presupply: %s postsupply: %s", presupply, postsupply) - suite.Require().True(postsupplyWithOffset.IsEqual(presupplyWithOffset)) + suite.Require().Equal(postsupplyWithOffset.String(), presupplyWithOffset.String()) unbondingDuration := suite.App.StakingKeeper.GetParams(suite.Ctx).UnbondingTime @@ -262,7 +251,7 @@ func (suite *KeeperTestSuite) TestSuperfluidUndelegate() { "with single validator and single superfluid delegation and single undelegation", []stakingtypes.BondStatus{stakingtypes.Bonded}, 1, - []superfluidDelegation{{0, 0, "gamm/pool/1", 1000000}}, + []superfluidDelegation{{0, 0, 0, 1000000}}, []uint64{}, []uint64{1}, []bool{false}, @@ -271,7 +260,7 @@ func (suite *KeeperTestSuite) TestSuperfluidUndelegate() { // { // "with single validator, single superfluid delegation, add more tokens to the lock, and single undelegation", // []stakingtypes.BondStatus{stakingtypes.Bonded}, - // []superfluidDelegation{{0, "gamm/pool/1", 1000000}}, + // []superfluidDelegation{{0, 0, 1000000}}, // []uint64{1}, // []uint64{1}, // []bool{false}, @@ -281,7 +270,7 @@ func (suite *KeeperTestSuite) TestSuperfluidUndelegate() { "with single validator and additional superfluid delegations and single undelegation", []stakingtypes.BondStatus{stakingtypes.Bonded}, 1, - []superfluidDelegation{{0, 0, "gamm/pool/1", 1000000}, {0, 0, "gamm/pool/1", 1000000}}, + []superfluidDelegation{{0, 0, 0, 1000000}, {0, 0, 0, 1000000}}, []uint64{}, []uint64{1}, []bool{false}, @@ -291,7 +280,7 @@ func (suite *KeeperTestSuite) TestSuperfluidUndelegate() { "with multiple validators and multiple superfluid delegations and multiple undelegations", []stakingtypes.BondStatus{stakingtypes.Bonded, stakingtypes.Bonded}, 2, - []superfluidDelegation{{0, 0, "gamm/pool/1", 1000000}, {1, 1, "gamm/pool/1", 1000000}}, + []superfluidDelegation{{0, 0, 0, 1000000}, {1, 1, 0, 1000000}}, []uint64{}, []uint64{1, 2}, []bool{false, false}, @@ -301,17 +290,17 @@ func (suite *KeeperTestSuite) TestSuperfluidUndelegate() { "undelegating not available lock id", []stakingtypes.BondStatus{stakingtypes.Bonded}, 1, - []superfluidDelegation{{0, 0, "gamm/pool/1", 1000000}}, + []superfluidDelegation{{0, 0, 0, 1000000}}, []uint64{}, []uint64{2}, []bool{true}, - []sdk.Dec{sdk.NewDec(10000000)}, + []sdk.Dec{}, }, { "try undelegating twice for same lock id", []stakingtypes.BondStatus{stakingtypes.Bonded}, 1, - []superfluidDelegation{{0, 0, "gamm/pool/1", 1000000}}, + []superfluidDelegation{{0, 0, 0, 1000000}}, []uint64{}, []uint64{1, 1}, []bool{false, true}, @@ -332,8 +321,10 @@ func (suite *KeeperTestSuite) TestSuperfluidUndelegate() { // setup validators valAddrs := suite.SetupValidators(tc.validatorStats) + denoms, _ := suite.SetupGammPoolsAndSuperfluidAssets([]sdk.Dec{sdk.NewDec(20), sdk.NewDec(20)}) + // setup superfluid delegations - intermediaryAccs, _ := suite.SetupSuperfluidDelegations(delAddrs, valAddrs, tc.superDelegations) + intermediaryAccs, _ := suite.SetupSuperfluidDelegations(delAddrs, valAddrs, tc.superDelegations, denoms) suite.checkIntermediaryAccountDelegations(intermediaryAccs) for _, lockId := range tc.addMoreTokensLockIds { @@ -438,8 +429,10 @@ func (suite *KeeperTestSuite) TestSuperfluidUnbondLock() { // setup validators valAddrs := suite.SetupValidators([]stakingtypes.BondStatus{stakingtypes.Bonded}) + denoms, _ := suite.SetupGammPoolsAndSuperfluidAssets([]sdk.Dec{sdk.NewDec(20), sdk.NewDec(20)}) + // setup superfluid delegations - intermediaryAccs, locks := suite.SetupSuperfluidDelegations(delAddrs, valAddrs, []superfluidDelegation{{0, 0, "gamm/pool/1", 1000000}}) + intermediaryAccs, locks := suite.SetupSuperfluidDelegations(delAddrs, valAddrs, []superfluidDelegation{{0, 0, 0, 1000000}}, denoms) suite.checkIntermediaryAccountDelegations(intermediaryAccs) for _, lock := range locks { @@ -503,7 +496,7 @@ func (suite *KeeperTestSuite) TestSuperfluidUnbondLock() { // check if finished unlocking succesfully increased balance balances = suite.App.BankKeeper.GetAllBalances(suite.Ctx, lock.OwnerAddress()) suite.Require().Equal(1, balances.Len()) - suite.Require().Equal("gamm/pool/1", balances[0].Denom) + suite.Require().Equal(denoms[0], balances[0].Denom) suite.Require().Equal(sdk.NewInt(1000000), balances[0].Amount) }