From 87e369c45f89e07b36ca6915acfcaf5bf4acd533 Mon Sep 17 00:00:00 2001 From: javiersuweijie Date: Wed, 28 Feb 2024 10:41:57 +0800 Subject: [PATCH] test: added tests for backward compatibility --- x/alliance/keeper/reward.go | 6 +- x/alliance/keeper/tests/reward_test.go | 230 ++++++++++++++++++++++++- 2 files changed, 228 insertions(+), 8 deletions(-) diff --git a/x/alliance/keeper/reward.go b/x/alliance/keeper/reward.go index b2f45b8..486228a 100644 --- a/x/alliance/keeper/reward.go +++ b/x/alliance/keeper/reward.go @@ -165,14 +165,16 @@ func (k Keeper) AddAssetsToRewardPool(ctx sdk.Context, from sdk.AccAddress, val normalizedWeight := asset.RewardWeight.Quo(totalRewardWeight) for _, c := range coins { rewardHistory, found := rewardHistories.GetIndexByDenom(c.Denom, asset.Denom) + totalTokens := val.TotalTokensWithAsset(*asset) + difference := sdk.NewDecFromInt(c.Amount).Mul(normalizedWeight).Quo(totalTokens) if !found { rewardHistories = append(rewardHistories, types.RewardHistory{ Denom: c.Denom, Alliance: asset.Denom, - Index: sdk.NewDecFromInt(c.Amount).Mul(normalizedWeight).QuoInt(asset.TotalTokens), + Index: difference, }) } else { - rewardHistory.Index = rewardHistory.Index.Add(sdk.NewDecFromInt(c.Amount).Mul(normalizedWeight).QuoInt(asset.TotalTokens)) + rewardHistory.Index = rewardHistory.Index.Add(difference) } } } diff --git a/x/alliance/keeper/tests/reward_test.go b/x/alliance/keeper/tests/reward_test.go index c4567f1..0c14aee 100644 --- a/x/alliance/keeper/tests/reward_test.go +++ b/x/alliance/keeper/tests/reward_test.go @@ -103,7 +103,7 @@ func TestRewardPoolAndGlobalIndex(t *testing.T) { types.RewardHistory{ Denom: "stake", Alliance: AllianceDenom, - Index: sdk.MustNewDecFromStr("2.4"), + Index: sdk.MustNewDecFromStr("2.400000000000000001"), }, types.RewardHistory{ Denom: "stake", @@ -122,7 +122,7 @@ func TestRewardPoolAndGlobalIndex(t *testing.T) { types.RewardHistory{ Denom: "stake", Alliance: AllianceDenom, - Index: sdk.MustNewDecFromStr("2.4"), + Index: sdk.MustNewDecFromStr("2.400000000000000001"), }, types.RewardHistory{ Denom: "stake", @@ -137,7 +137,7 @@ func TestRewardPoolAndGlobalIndex(t *testing.T) { types.RewardHistory{ Denom: "stake2", Alliance: AllianceDenomTwo, - Index: sdk.MustNewDecFromStr("0.999999999999999999"), + Index: sdk.MustNewDecFromStr("1.0"), }, }, globalIndices) } @@ -634,7 +634,8 @@ func TestClaimRewardsAfterRewardsRatesChange(t *testing.T) { PrevRewardWeight: sdk.NewDec(2), RewardHistories: val1.GlobalRewardHistory, }, snapshot) - iter.Close() + err = iter.Close() + require.NoError(t, err) // Accumulate rewards in pool err = app.BankKeeper.SendCoinsFromModuleToModule(ctx, minttypes.ModuleName, authtypes.FeeCollectorName, sdk.NewCoins(sdk.NewCoin(bondDenom, sdk.NewInt(10_000_000)))) @@ -1075,6 +1076,223 @@ func TestClaimRewardsWithDifferentTokenDecimals(t *testing.T) { require.Equal(t, sdk.NewCoins(sdk.NewCoin("stake", sdk.NewInt(0))), coins) } -func TestMigratedRewardsLogic(t *testing.T) { - // TODO: Need to test this for the migration +// Since 0.3.4, rewards distribution logic has changed to be asset scoped +// this test makes sure that we have backward compatibility +func TestMigratedRewardsWithRatesChange(t *testing.T) { + var err error + app, ctx := createTestContext(t) + ctx = ctx.WithBlockHeight(1) + app.AllianceKeeper.InitGenesis(ctx, &types.GenesisState{ + Params: types.DefaultParams(), + Assets: []types.AllianceAsset{ + types.NewAllianceAsset(AllianceDenom, sdk.NewDec(2), sdk.NewDec(0), sdk.NewDec(5), sdk.NewDec(0), ctx.BlockTime()), + types.NewAllianceAsset(AllianceDenomTwo, sdk.NewDec(8), sdk.NewDec(2), sdk.NewDec(12), sdk.NewDec(0), ctx.BlockTime()), + }, + }) + + // Set tax and rewards to be zero for easier calculation + distParams := app.DistrKeeper.GetParams(ctx) + distParams.CommunityTax = sdk.ZeroDec() + + err = app.DistrKeeper.SetParams(ctx, distParams) + require.NoError(t, err) + + // Accounts + mintPoolAddr := app.AccountKeeper.GetModuleAddress(minttypes.ModuleName) + bondDenom := app.StakingKeeper.BondDenom(ctx) + addrs := test_helpers.AddTestAddrsIncremental(app, ctx, 4, sdk.NewCoins( + sdk.NewCoin(AllianceDenom, sdk.NewInt(10_000_000)), + sdk.NewCoin(AllianceDenomTwo, sdk.NewInt(10_000_000)), + )) + + // Creating validator 0% commissions + pks := test_helpers.CreateTestPubKeys(2) + valAddr1 := sdk.ValAddress(addrs[0]) + _val1 := teststaking.NewValidator(t, valAddr1, pks[0]) + _val1.Commission = stakingtypes.Commission{ + CommissionRates: stakingtypes.CommissionRates{ + Rate: sdk.NewDec(0), + MaxRate: sdk.NewDec(0), + MaxChangeRate: sdk.NewDec(0), + }, + UpdateTime: time.Now(), + } + test_helpers.RegisterNewValidator(t, app, ctx, _val1) + val1, err := app.AllianceKeeper.GetAllianceValidator(ctx, valAddr1) + require.NoError(t, err) + + user1 := addrs[2] + user2 := addrs[3] + + // Mint bond denom + err = app.BankKeeper.MintCoins(ctx, minttypes.ModuleName, sdk.NewCoins(sdk.NewCoin(bondDenom, sdk.NewInt(40_000_000)))) + require.NoError(t, err) + + // New delegations + _, err = app.AllianceKeeper.Delegate(ctx, user1, val1, sdk.NewCoin(AllianceDenom, sdk.NewInt(1_000_000))) + require.NoError(t, err) + _, err = app.AllianceKeeper.Delegate(ctx, user2, val1, sdk.NewCoin(AllianceDenomTwo, sdk.NewInt(1_000_000))) + require.NoError(t, err) + + assets := app.AllianceKeeper.GetAllAssets(ctx) + err = app.AllianceKeeper.RebalanceBondTokenWeights(ctx, assets) + require.NoError(t, err) + + // Manually update global asset history + val1.GlobalRewardHistory = append(val1.GlobalRewardHistory, types.RewardHistory{ + Denom: bondDenom, + Index: sdk.MustNewDecFromStr("0.5"), + Alliance: "", + }) + app.AllianceKeeper.SetValidator(ctx, val1) + err = app.BankKeeper.SendCoinsFromModuleToModule(ctx, minttypes.ModuleName, types.RewardsPoolName, sdk.NewCoins(sdk.NewCoin(bondDenom, sdk.NewInt(5_000_000)))) + require.NoError(t, err) + + // Check rewards for user1 + queryServer := keeper.NewQueryServerImpl(app.AllianceKeeper) + qCtx, _ := ctx.CacheContext() + rewards, err := queryServer.AllianceDelegationRewards(qCtx, &types.QueryAllianceDelegationRewardsRequest{ + DelegatorAddr: user1.String(), + ValidatorAddr: val1.GetOperator().String(), + Denom: AllianceDenom, + Pagination: nil, + }) + require.NoError(t, err) + require.Equal(t, sdk.NewInt(1_000_000), sdk.NewCoins(rewards.Rewards...).AmountOf(bondDenom)) + + err = app.AllianceKeeper.AddAssetsToRewardPool(ctx, mintPoolAddr, val1, sdk.NewCoins(sdk.NewCoin(bondDenom, sdk.NewInt(10_000_000)))) + require.NoError(t, err) + + // Update alliance asset reward weight + err = app.AllianceKeeper.UpdateAllianceAsset(ctx, types.NewAllianceAsset(AllianceDenom, sdk.NewDec(8), sdk.NewDec(2), sdk.NewDec(12), sdk.NewDec(0), ctx.BlockTime())) + require.NoError(t, err) + assets = app.AllianceKeeper.GetAllAssets(ctx) + err = app.AllianceKeeper.RebalanceBondTokenWeights(ctx, assets) + require.NoError(t, err) + + err = app.AllianceKeeper.AddAssetsToRewardPool(ctx, mintPoolAddr, val1, sdk.NewCoins(sdk.NewCoin(bondDenom, sdk.NewInt(10_000_000)))) + require.NoError(t, err) + + rewards1, err := app.AllianceKeeper.ClaimDelegationRewards(ctx, user1, val1, AllianceDenom) + require.NoError(t, err) + require.Equal(t, sdk.NewInt(1_000_000+2_000_000+5_000_000), rewards1.AmountOf(bondDenom)) + + rewards2, err := app.AllianceKeeper.ClaimDelegationRewards(ctx, user2, val1, AllianceDenomTwo) + require.NoError(t, err) + require.Equal(t, sdk.NewInt(4_000_000+8_000_000+5_000_000), rewards2.AmountOf(bondDenom)) +} + +func TestMigratedRewards(t *testing.T) { + var err error + app, ctx := createTestContext(t) + ctx = ctx.WithBlockHeight(1) + app.AllianceKeeper.InitGenesis(ctx, &types.GenesisState{ + Params: types.DefaultParams(), + Assets: []types.AllianceAsset{ + types.NewAllianceAsset(AllianceDenom, sdk.NewDec(2), sdk.NewDec(0), sdk.NewDec(5), sdk.NewDec(0), ctx.BlockTime()), + types.NewAllianceAsset(AllianceDenomTwo, sdk.NewDec(8), sdk.NewDec(2), sdk.NewDec(12), sdk.NewDec(0), ctx.BlockTime()), + }, + }) + + // Set tax and rewards to be zero for easier calculation + distParams := app.DistrKeeper.GetParams(ctx) + distParams.CommunityTax = sdk.ZeroDec() + + err = app.DistrKeeper.SetParams(ctx, distParams) + require.NoError(t, err) + + // Accounts + mintPoolAddr := app.AccountKeeper.GetModuleAddress(minttypes.ModuleName) + bondDenom := app.StakingKeeper.BondDenom(ctx) + addrs := test_helpers.AddTestAddrsIncremental(app, ctx, 4, sdk.NewCoins( + sdk.NewCoin(AllianceDenom, sdk.NewInt(10_000_000)), + sdk.NewCoin(AllianceDenomTwo, sdk.NewInt(10_000_000)), + )) + + pks := test_helpers.CreateTestPubKeys(2) + + // Creating two validators with 0% commission + valAddr1 := sdk.ValAddress(addrs[0]) + _val1 := teststaking.NewValidator(t, valAddr1, pks[0]) + _val1.Commission = stakingtypes.Commission{ + CommissionRates: stakingtypes.CommissionRates{ + Rate: sdk.NewDec(0), + MaxRate: sdk.NewDec(0), + MaxChangeRate: sdk.NewDec(0), + }, + UpdateTime: time.Now(), + } + test_helpers.RegisterNewValidator(t, app, ctx, _val1) + + valAddr2 := sdk.ValAddress(addrs[1]) + _val2 := teststaking.NewValidator(t, valAddr2, pks[1]) + _val2.Commission = stakingtypes.Commission{ + CommissionRates: stakingtypes.CommissionRates{ + Rate: sdk.NewDec(0), + MaxRate: sdk.NewDec(0), + MaxChangeRate: sdk.NewDec(0), + }, + UpdateTime: time.Now(), + } + test_helpers.RegisterNewValidator(t, app, ctx, _val2) + + val1, _ := app.AllianceKeeper.GetAllianceValidator(ctx, valAddr1) + val2, _ := app.AllianceKeeper.GetAllianceValidator(ctx, valAddr2) + + user1 := addrs[2] + user2 := addrs[3] + + // Mint bond denom + err = app.BankKeeper.MintCoins(ctx, minttypes.ModuleName, sdk.NewCoins(sdk.NewCoin(bondDenom, sdk.NewInt(40_000_000)))) + require.NoError(t, err) + + // New delegations + _, err = app.AllianceKeeper.Delegate(ctx, user1, val1, sdk.NewCoin(AllianceDenom, sdk.NewInt(1000_000))) + require.NoError(t, err) + _, err = app.AllianceKeeper.Delegate(ctx, user2, val1, sdk.NewCoin(AllianceDenomTwo, sdk.NewInt(1000_000))) + require.NoError(t, err) + _, err = app.AllianceKeeper.Delegate(ctx, user2, val2, sdk.NewCoin(AllianceDenomTwo, sdk.NewInt(1000_000))) + require.NoError(t, err) + + assets := app.AllianceKeeper.GetAllAssets(ctx) + err = app.AllianceKeeper.RebalanceBondTokenWeights(ctx, assets) + require.NoError(t, err) + + // Manually update global asset history + val1.GlobalRewardHistory = append(val1.GlobalRewardHistory, + types.RewardHistory{ + Denom: bondDenom, + Index: sdk.MustNewDecFromStr("0.5"), + Alliance: "", + }, + ) + app.AllianceKeeper.SetValidator(ctx, val1) + + val2.GlobalRewardHistory = append(val2.GlobalRewardHistory, + types.RewardHistory{ + Denom: bondDenom, + Index: sdk.MustNewDecFromStr("0.5"), + Alliance: "", + }, + ) + app.AllianceKeeper.SetValidator(ctx, val2) + err = app.BankKeeper.SendCoinsFromModuleToModule(ctx, minttypes.ModuleName, types.RewardsPoolName, sdk.NewCoins(sdk.NewCoin(bondDenom, sdk.NewInt(9_000_000)))) + require.NoError(t, err) + + err = app.AllianceKeeper.AddAssetsToRewardPool(ctx, mintPoolAddr, val1, sdk.NewCoins(sdk.NewCoin(bondDenom, sdk.NewInt(10_000_000)))) + require.NoError(t, err) + err = app.AllianceKeeper.AddAssetsToRewardPool(ctx, mintPoolAddr, val2, sdk.NewCoins(sdk.NewCoin(bondDenom, sdk.NewInt(10_000_000)))) + require.NoError(t, err) + + rewards1, err := app.AllianceKeeper.ClaimDelegationRewards(ctx, user1, val1, AllianceDenom) + require.NoError(t, err) + require.Equal(t, sdk.NewInt(1_000_000+2_000_000), rewards1.AmountOf(bondDenom)) + + rewards2, err := app.AllianceKeeper.ClaimDelegationRewards(ctx, user2, val1, AllianceDenomTwo) + require.NoError(t, err) + require.Equal(t, sdk.NewInt(4_000_000+8_000_000), rewards2.AmountOf(bondDenom)) + + rewards3, err := app.AllianceKeeper.ClaimDelegationRewards(ctx, user2, val2, AllianceDenomTwo) + require.NoError(t, err) + require.Equal(t, sdk.NewInt(4_000_000+10_000_000), rewards3.AmountOf(bondDenom)) }