From 9addb51f4ad676d17b5a63d542a0c3d8d345aaf7 Mon Sep 17 00:00:00 2001 From: zakir <80246097+zakir-code@users.noreply.github.com> Date: Mon, 20 Jan 2025 22:46:30 +0800 Subject: [PATCH] refactor(distribution): migrate distribution module (#928) --- app/upgrade_test.go | 1 + app/upgrades/v8/distribution.go | 156 ++++++++++++++++++++++++++++++++ app/upgrades/v8/upgrade.go | 6 +- types/constant.go | 4 + 4 files changed, 166 insertions(+), 1 deletion(-) create mode 100644 app/upgrades/v8/distribution.go diff --git a/app/upgrade_test.go b/app/upgrade_test.go index caebaf43..7edbc1ad 100644 --- a/app/upgrade_test.go +++ b/app/upgrade_test.go @@ -655,6 +655,7 @@ func checkModulesData(t *testing.T, ctx sdk.Context, myApp *app.App) { checkEvmParams(t, ctx, myApp) checkIBCTransferModule(t, ctx, myApp) checkMintModule(t, ctx, myApp) + nextversion.CheckDistributionModule(t, ctx, myApp.DistrKeeper) } func checkEvmParams(t *testing.T, ctx sdk.Context, myApp *app.App) { diff --git a/app/upgrades/v8/distribution.go b/app/upgrades/v8/distribution.go new file mode 100644 index 00000000..25acd210 --- /dev/null +++ b/app/upgrades/v8/distribution.go @@ -0,0 +1,156 @@ +package v8 + +import ( + "fmt" + "testing" + + sdk "github.com/cosmos/cosmos-sdk/types" + distributionkeeper "github.com/cosmos/cosmos-sdk/x/distribution/keeper" + "github.com/cosmos/cosmos-sdk/x/distribution/types" + "github.com/stretchr/testify/require" + + fxtypes "github.com/pundiai/fx-core/v8/types" +) + +func migrateDistribution(ctx sdk.Context, distrKeeper distributionkeeper.Keeper) error { + if err := migrateValidatorAccumulatedCommission(ctx, distrKeeper); err != nil { + return err + } + if err := migrateValidatorOutstandingRewards(ctx, distrKeeper); err != nil { + return err + } + if err := migrateValidatorCurrentRewards(ctx, distrKeeper); err != nil { + return err + } + if err := migrateDelegatorStartingInfos(ctx, distrKeeper); err != nil { + return err + } + if err := migrateValidatorHistoricalRewards(ctx, distrKeeper); err != nil { + return err + } + return migrateFeePool(ctx, distrKeeper) +} + +func migrateValidatorHistoricalRewards(ctx sdk.Context, keeper distributionkeeper.Keeper) error { + var err error + keeper.IterateValidatorHistoricalRewards(ctx, func(valAddr sdk.ValAddress, period uint64, rewards types.ValidatorHistoricalRewards) bool { + newRewards := swapFXDecCoinsToDefaultCoin(rewards.CumulativeRewardRatio) + rewards.CumulativeRewardRatio = newRewards + err = keeper.SetValidatorHistoricalRewards(ctx, valAddr, period, rewards) + return err != nil + }) + return err +} + +func migrateDelegatorStartingInfos(ctx sdk.Context, distrKeeper distributionkeeper.Keeper) error { + var err error + distrKeeper.IterateDelegatorStartingInfos(ctx, func(valAddr sdk.ValAddress, addr sdk.AccAddress, info types.DelegatorStartingInfo) bool { + info.Stake = fxtypes.SwapDecAmount(info.Stake) + err = distrKeeper.SetDelegatorStartingInfo(ctx, valAddr, addr, info) + return err != nil + }) + return err +} + +func migrateFeePool(ctx sdk.Context, distrKeeper distributionkeeper.Keeper) error { + feePool, err := distrKeeper.FeePool.Get(ctx) + if err != nil { + return err + } + + feePool.CommunityPool = swapFXDecCoinsToDefaultCoin(feePool.CommunityPool) + return distrKeeper.FeePool.Set(ctx, feePool) +} + +func migrateValidatorAccumulatedCommission(ctx sdk.Context, distrKeeper distributionkeeper.Keeper) error { + var err error + distrKeeper.IterateValidatorAccumulatedCommissions(ctx, func(addr sdk.ValAddress, commission types.ValidatorAccumulatedCommission) bool { + newCommission := swapFXDecCoinsToDefaultCoin(commission.Commission) + commission.Commission = newCommission + err = distrKeeper.SetValidatorAccumulatedCommission(ctx, addr, commission) + return err != nil + }) + + return err +} + +func migrateValidatorCurrentRewards(ctx sdk.Context, distrKeeper distributionkeeper.Keeper) error { + var err error + distrKeeper.IterateValidatorCurrentRewards(ctx, func(addr sdk.ValAddress, rewards types.ValidatorCurrentRewards) bool { + newRewards := swapFXDecCoinsToDefaultCoin(rewards.Rewards) + rewards.Rewards = newRewards + err = distrKeeper.SetValidatorCurrentRewards(ctx, addr, rewards) + return err != nil + }) + return err +} + +func migrateValidatorOutstandingRewards(ctx sdk.Context, distrKeeper distributionkeeper.Keeper) error { + var err error + distrKeeper.IterateValidatorOutstandingRewards(ctx, func(addr sdk.ValAddress, rewards types.ValidatorOutstandingRewards) bool { + newRewards := swapFXDecCoinsToDefaultCoin(rewards.Rewards) + rewards.Rewards = newRewards + err = distrKeeper.SetValidatorOutstandingRewards(ctx, addr, rewards) + return err != nil + }) + + return err +} + +func swapFXDecCoinsToDefaultCoin(decCoins sdk.DecCoins) sdk.DecCoins { + oldDenom := fxtypes.LegacyFXDenom + newDenom := fxtypes.DefaultDenom + newDecCoins := sdk.NewDecCoins() + for _, decCoin := range decCoins { + if decCoin.Denom == oldDenom { + decCoin.Denom = newDenom + decCoin.Amount = fxtypes.SwapDecAmount(decCoin.Amount) + if !decCoin.IsPositive() { + continue + } + } + newDecCoins = newDecCoins.Add(decCoin) + } + return newDecCoins +} + +func CheckDistributionModule(t *testing.T, ctx sdk.Context, distrKeeper distributionkeeper.Keeper) { + t.Helper() + + denomCheckFn := func(decCoins sdk.DecCoins, msg ...string) { + if decCoins.IsZero() { + return + } + require.Truef(t, decCoins.AmountOf(fxtypes.LegacyFXDenom).IsZero(), decCoins.String(), msg) + require.Falsef(t, decCoins.AmountOf(fxtypes.DefaultDenom).IsZero(), decCoins.String(), msg) + } + + // check fee pool + feePool, err := distrKeeper.FeePool.Get(ctx) + require.NoError(t, err) + denomCheckFn(feePool.GetCommunityPool()) + + // check validator commission + distrKeeper.IterateValidatorAccumulatedCommissions(ctx, func(val sdk.ValAddress, commission types.ValidatorAccumulatedCommission) (stop bool) { + denomCheckFn(commission.GetCommission(), fmt.Sprintf("val:%s,commission:%s", val.String(), commission.String())) + return false + }) + + // check validator outstanding rewards + distrKeeper.IterateValidatorOutstandingRewards(ctx, func(val sdk.ValAddress, rewards types.ValidatorOutstandingRewards) (stop bool) { + denomCheckFn(rewards.GetRewards(), fmt.Sprintf("val:%s,outstanding rewards:%s", val.String(), rewards.String())) + return false + }) + + // check validator current rewards + distrKeeper.IterateValidatorCurrentRewards(ctx, func(val sdk.ValAddress, rewards types.ValidatorCurrentRewards) (stop bool) { + denomCheckFn(rewards.GetRewards(), fmt.Sprintf("val:%s,current rewards:%s", val.String(), rewards.String())) + return false + }) + + // check validator historical rewards + distrKeeper.IterateValidatorHistoricalRewards(ctx, func(val sdk.ValAddress, period uint64, rewards types.ValidatorHistoricalRewards) (stop bool) { + denomCheckFn(rewards.GetCumulativeRewardRatio(), fmt.Sprintf("val:%s,historical rewards:%s", val.String(), rewards.String())) + return false + }) +} diff --git a/app/upgrades/v8/upgrade.go b/app/upgrades/v8/upgrade.go index e985ce3d..06b90d05 100644 --- a/app/upgrades/v8/upgrade.go +++ b/app/upgrades/v8/upgrade.go @@ -47,7 +47,7 @@ import ( fxstakingv8 "github.com/pundiai/fx-core/v8/x/staking/migrations/v8" ) -func CreateUpgradeHandler(cdc codec.Codec, mm *module.Manager, configurator module.Configurator, app *keepers.AppKeepers) upgradetypes.UpgradeHandler { +func CreateUpgradeHandler(_ codec.Codec, mm *module.Manager, configurator module.Configurator, app *keepers.AppKeepers) upgradetypes.UpgradeHandler { return func(ctx context.Context, plan upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) { cacheCtx, commit := sdk.UnwrapSDKContext(ctx).CacheContext() @@ -219,6 +219,10 @@ func migrateModulesData(ctx sdk.Context, app *keepers.AppKeepers) error { migrateTransferTokenInEscrow(ctx, app.IBCTransferKeeper) + if err := migrateDistribution(ctx, app.DistrKeeper); err != nil { + return err + } + return migrateCrisisModule(ctx, app.CrisisKeeper) } diff --git a/types/constant.go b/types/constant.go index d9406bab..be5b3268 100644 --- a/types/constant.go +++ b/types/constant.go @@ -98,6 +98,10 @@ func SwapAmount(amount sdkmath.Int) sdkmath.Int { return amount.QuoRaw(100) } +func SwapDecAmount(amount sdkmath.LegacyDec) sdkmath.LegacyDec { + return amount.QuoInt64(100) +} + func SwapCoin(coin sdk.Coin) sdk.Coin { if coin.Denom != FXDenom { return coin