mirror of
				https://github.com/0glabs/0g-chain.git
				synced 2025-11-04 09:57:27 +00:00 
			
		
		
		
	feat(community): consolidate community funds (#1729)
* Add consolidate methods * Update distr feepool balance with dust, add tests * Set params for proposal handler to not influence module balances * Add StakingRewardsPerSecond param for proposal test * Update changelog * Update test to check emitted events * Log dust amounts for x/distribution * Modify feepool communitypool field instead of entire replacement * Update tests to include cases with empty balances * Move EventsContains to app * Remove extra copied ModuleName * Add Require() to incentive claims in tests to reduce errors * Move consolidate tests to testutil * Only transfer non-ukava coins * Add DefaultStakingRewardsState to proposal handler test * Move event emit before consolidate * add golangci specific timeout --------- Co-authored-by: Nick DeLuca <nickdeluca08@gmail.com>
This commit is contained in:
		
							parent
							
								
									395b69ac2f
								
							
						
					
					
						commit
						8186367c8b
					
				
							
								
								
									
										1
									
								
								.github/workflows/ci-lint.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.github/workflows/ci-lint.yml
									
									
									
									
										vendored
									
									
								
							@ -14,3 +14,4 @@ jobs:
 | 
				
			|||||||
        with:
 | 
					        with:
 | 
				
			||||||
          github_token: ${{ secrets.github_token }}
 | 
					          github_token: ${{ secrets.github_token }}
 | 
				
			||||||
          reporter: github-pr-review
 | 
					          reporter: github-pr-review
 | 
				
			||||||
 | 
					          golangci_lint_flags: --timeout 10m
 | 
				
			||||||
 | 
				
			|||||||
@ -53,6 +53,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
 | 
				
			|||||||
- (community) [#1704] Add param to control when inflation will be disabled
 | 
					- (community) [#1704] Add param to control when inflation will be disabled
 | 
				
			||||||
- (community) [#1707] Default staking rewards per second set to `744191`
 | 
					- (community) [#1707] Default staking rewards per second set to `744191`
 | 
				
			||||||
- (community) [#1706] Add disable inflation upgrade to begin blocker that updates x/mint and x/kavadist params.
 | 
					- (community) [#1706] Add disable inflation upgrade to begin blocker that updates x/mint and x/kavadist params.
 | 
				
			||||||
 | 
					- (community) [#1729] Consolidate community funds from `x/distribution` and `x/kavadist` to `x/community`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## [v0.24.0]
 | 
					## [v0.24.0]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -293,6 +294,7 @@ the [changelog](https://github.com/cosmos/cosmos-sdk/blob/v0.38.4/CHANGELOG.md).
 | 
				
			|||||||
- [#257](https://github.com/Kava-Labs/kava/pulls/257) Include scripts to run
 | 
					- [#257](https://github.com/Kava-Labs/kava/pulls/257) Include scripts to run
 | 
				
			||||||
  large-scale simulations remotely using aws-batch
 | 
					  large-scale simulations remotely using aws-batch
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[#1729]: https://github.com/Kava-Labs/kava/pull/1729
 | 
				
			||||||
[#1745]: https://github.com/Kava-Labs/kava/pull/1745
 | 
					[#1745]: https://github.com/Kava-Labs/kava/pull/1745
 | 
				
			||||||
[#1707]: https://github.com/Kava-Labs/kava/pull/1707
 | 
					[#1707]: https://github.com/Kava-Labs/kava/pull/1707
 | 
				
			||||||
[#1706]: https://github.com/Kava-Labs/kava/pull/1706
 | 
					[#1706]: https://github.com/Kava-Labs/kava/pull/1706
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										104
									
								
								x/community/keeper/consolidate.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										104
									
								
								x/community/keeper/consolidate.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,104 @@
 | 
				
			|||||||
 | 
					package keeper
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sdk "github.com/cosmos/cosmos-sdk/types"
 | 
				
			||||||
 | 
						"github.com/kava-labs/kava/x/community/types"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						kavadisttypes "github.com/kava-labs/kava/x/kavadist/types"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// StartCommunityFundConsolidation consolidates the community funds from
 | 
				
			||||||
 | 
					// x/distribution and x/kavadist into the x/community module account
 | 
				
			||||||
 | 
					func (k Keeper) StartCommunityFundConsolidation(ctx sdk.Context) error {
 | 
				
			||||||
 | 
						logger := k.Logger(ctx)
 | 
				
			||||||
 | 
						logger.Info("community fund consolidation upgrade started")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Consolidate x/distribution community pool
 | 
				
			||||||
 | 
						if err := k.consolidateCommunityDistribution(ctx); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Consolidate x/kavadist account
 | 
				
			||||||
 | 
						if err := k.consolidateCommunityKavadist(ctx); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Log new x/community balance
 | 
				
			||||||
 | 
						communityCoins := k.GetModuleAccountBalance(ctx)
 | 
				
			||||||
 | 
						logger.Info(fmt.Sprintf("community funds consolidated, x/community balance is now %s", communityCoins))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// consolidateCommunityDistribution transfers all coins from the x/distribution
 | 
				
			||||||
 | 
					// community pool to the x/community module account
 | 
				
			||||||
 | 
					func (k Keeper) consolidateCommunityDistribution(ctx sdk.Context) error {
 | 
				
			||||||
 | 
						logger := k.Logger(ctx)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Get community coins with leftover leftoverDust
 | 
				
			||||||
 | 
						truncatedCoins, leftoverDust := k.distrKeeper.
 | 
				
			||||||
 | 
							GetFeePoolCommunityCoins(ctx).
 | 
				
			||||||
 | 
							TruncateDecimal()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Transfer to x/community
 | 
				
			||||||
 | 
						err := k.bankKeeper.SendCoinsFromModuleToModule(
 | 
				
			||||||
 | 
							ctx,
 | 
				
			||||||
 | 
							distrtypes.ModuleName, // sender
 | 
				
			||||||
 | 
							types.ModuleName,      // recipient
 | 
				
			||||||
 | 
							truncatedCoins,
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return fmt.Errorf("failed to transfer x/distribution coins to x/community: %w", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						logger.Info(fmt.Sprintf("transferred %s from x/distribution to x/community", truncatedCoins))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Set x/distribution community pool to remaining dust amounts
 | 
				
			||||||
 | 
						feePool := k.distrKeeper.GetFeePool(ctx)
 | 
				
			||||||
 | 
						feePool.CommunityPool = leftoverDust
 | 
				
			||||||
 | 
						k.distrKeeper.SetFeePool(ctx, feePool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						logger.Info(fmt.Sprintf("remaining x/distribution community pool dust: %s", leftoverDust))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// consolidateCommunityKavadist transfers all coins from the x/kavadist module
 | 
				
			||||||
 | 
					// account to the x/community module account
 | 
				
			||||||
 | 
					func (k Keeper) consolidateCommunityKavadist(ctx sdk.Context) error {
 | 
				
			||||||
 | 
						logger := k.Logger(ctx)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						kavadistAcc := k.accountKeeper.GetModuleAccount(ctx, kavadisttypes.KavaDistMacc)
 | 
				
			||||||
 | 
						transferCoins := k.bankKeeper.GetAllBalances(ctx, kavadistAcc.GetAddress())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Remove ukava from transfer coins - ony transfer non-ukava coins
 | 
				
			||||||
 | 
						found, kavaCoins := transferCoins.Find("ukava")
 | 
				
			||||||
 | 
						if found {
 | 
				
			||||||
 | 
							transferCoins = transferCoins.Sub(kavaCoins)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Transfer remaining coins to x/community
 | 
				
			||||||
 | 
						err := k.bankKeeper.SendCoinsFromModuleToModule(
 | 
				
			||||||
 | 
							ctx,
 | 
				
			||||||
 | 
							kavadisttypes.ModuleName, // sender
 | 
				
			||||||
 | 
							types.ModuleName,         // recipient
 | 
				
			||||||
 | 
							transferCoins,
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return fmt.Errorf("failed to transfer x/kavadist coins to x/community: %w", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						kavadistRemainingCoins := k.bankKeeper.GetAllBalances(ctx, kavadistAcc.GetAddress())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						logger.Info(fmt.Sprintf(
 | 
				
			||||||
 | 
							"transferred %s from x/kavadist to x/community, remaining x/kavadist balance: %s",
 | 
				
			||||||
 | 
							transferCoins,
 | 
				
			||||||
 | 
							kavadistRemainingCoins,
 | 
				
			||||||
 | 
						))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -22,17 +22,21 @@ func (k Keeper) CheckAndDisableMintAndKavaDistInflation(ctx sdk.Context) {
 | 
				
			|||||||
	// run disable inflation logic
 | 
						// run disable inflation logic
 | 
				
			||||||
	k.disableInflation(ctx)
 | 
						k.disableInflation(ctx)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx.EventManager().EmitEvent(
 | 
				
			||||||
 | 
							sdk.NewEvent(
 | 
				
			||||||
 | 
								types.EventTypeInflationStop,
 | 
				
			||||||
 | 
							),
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// reset disable inflation time to ensure next call is a no-op
 | 
						// reset disable inflation time to ensure next call is a no-op
 | 
				
			||||||
	params.UpgradeTimeDisableInflation = time.Time{}
 | 
						params.UpgradeTimeDisableInflation = time.Time{}
 | 
				
			||||||
	// set staking rewards to provided intial value
 | 
						// set staking rewards to provided intial value
 | 
				
			||||||
	params.StakingRewardsPerSecond = params.UpgradeTimeSetStakingRewardsPerSecond
 | 
						params.StakingRewardsPerSecond = params.UpgradeTimeSetStakingRewardsPerSecond
 | 
				
			||||||
	k.SetParams(ctx, params)
 | 
						k.SetParams(ctx, params)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ctx.EventManager().EmitEvent(
 | 
						if err := k.StartCommunityFundConsolidation(ctx); err != nil {
 | 
				
			||||||
		sdk.NewEvent(
 | 
							panic(err)
 | 
				
			||||||
			types.EventTypeInflationStop,
 | 
						}
 | 
				
			||||||
		),
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// TODO: double check this is correct method for disabling inflation in kavadist without
 | 
					// TODO: double check this is correct method for disabling inflation in kavadist without
 | 
				
			||||||
 | 
				
			|||||||
@ -16,6 +16,7 @@ type Keeper struct {
 | 
				
			|||||||
	key storetypes.StoreKey
 | 
						key storetypes.StoreKey
 | 
				
			||||||
	cdc codec.Codec
 | 
						cdc codec.Codec
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						accountKeeper  types.AccountKeeper
 | 
				
			||||||
	bankKeeper     types.BankKeeper
 | 
						bankKeeper     types.BankKeeper
 | 
				
			||||||
	cdpKeeper      types.CdpKeeper
 | 
						cdpKeeper      types.CdpKeeper
 | 
				
			||||||
	distrKeeper    types.DistributionKeeper
 | 
						distrKeeper    types.DistributionKeeper
 | 
				
			||||||
@ -63,6 +64,7 @@ func NewKeeper(
 | 
				
			|||||||
		key: key,
 | 
							key: key,
 | 
				
			||||||
		cdc: cdc,
 | 
							cdc: cdc,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							accountKeeper:  ak,
 | 
				
			||||||
		bankKeeper:     bk,
 | 
							bankKeeper:     bk,
 | 
				
			||||||
		cdpKeeper:      ck,
 | 
							cdpKeeper:      ck,
 | 
				
			||||||
		distrKeeper:    dk,
 | 
							distrKeeper:    dk,
 | 
				
			||||||
 | 
				
			|||||||
@ -5,6 +5,7 @@ import (
 | 
				
			|||||||
	"testing"
 | 
						"testing"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sdkmath "cosmossdk.io/math"
 | 
				
			||||||
	sdk "github.com/cosmos/cosmos-sdk/types"
 | 
						sdk "github.com/cosmos/cosmos-sdk/types"
 | 
				
			||||||
	"github.com/stretchr/testify/suite"
 | 
						"github.com/stretchr/testify/suite"
 | 
				
			||||||
	abcitypes "github.com/tendermint/tendermint/abci/types"
 | 
						abcitypes "github.com/tendermint/tendermint/abci/types"
 | 
				
			||||||
@ -27,9 +28,11 @@ func c(denom string, amount int64) sdk.Coin { return sdk.NewInt64Coin(denom, amo
 | 
				
			|||||||
func ukava(amt int64) sdk.Coins {
 | 
					func ukava(amt int64) sdk.Coins {
 | 
				
			||||||
	return sdk.NewCoins(c("ukava", amt))
 | 
						return sdk.NewCoins(c("ukava", amt))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func usdx(amt int64) sdk.Coins {
 | 
					func usdx(amt int64) sdk.Coins {
 | 
				
			||||||
	return sdk.NewCoins(c("usdx", amt))
 | 
						return sdk.NewCoins(c("usdx", amt))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func otherdenom(amt int64) sdk.Coins {
 | 
					func otherdenom(amt int64) sdk.Coins {
 | 
				
			||||||
	return sdk.NewCoins(c("other-denom", amt))
 | 
						return sdk.NewCoins(c("other-denom", amt))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -67,10 +70,19 @@ func (suite *proposalTestSuite) SetupTest() {
 | 
				
			|||||||
		ChainID: chainID,
 | 
							ChainID: chainID,
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Set UpgradeTimeDisableInflation to far future to not influence module
 | 
				
			||||||
 | 
						// account balances
 | 
				
			||||||
 | 
						params := types.Params{
 | 
				
			||||||
 | 
							UpgradeTimeDisableInflation: time.Now().Add(100000 * time.Hour),
 | 
				
			||||||
 | 
							StakingRewardsPerSecond:     sdkmath.LegacyNewDec(0),
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						communityGs := types.NewGenesisState(params, types.DefaultStakingRewardsState())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	tApp.InitializeFromGenesisStatesWithTimeAndChainID(
 | 
						tApp.InitializeFromGenesisStatesWithTimeAndChainID(
 | 
				
			||||||
		genTime, chainID,
 | 
							genTime, chainID,
 | 
				
			||||||
		app.GenesisState{hardtypes.ModuleName: tApp.AppCodec().MustMarshalJSON(&hardGS)},
 | 
							app.GenesisState{hardtypes.ModuleName: tApp.AppCodec().MustMarshalJSON(&hardGS)},
 | 
				
			||||||
		app.GenesisState{pricefeedtypes.ModuleName: tApp.AppCodec().MustMarshalJSON(&pricefeedGS)},
 | 
							app.GenesisState{pricefeedtypes.ModuleName: tApp.AppCodec().MustMarshalJSON(&pricefeedGS)},
 | 
				
			||||||
 | 
							app.GenesisState{types.ModuleName: tApp.AppCodec().MustMarshalJSON(&communityGs)},
 | 
				
			||||||
		testutil.NewCDPGenState(tApp.AppCodec(), "ukava", "kava", sdk.NewDec(2)),
 | 
							testutil.NewCDPGenState(tApp.AppCodec(), "ukava", "kava", sdk.NewDec(2)),
 | 
				
			||||||
	)
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -11,10 +11,6 @@ import (
 | 
				
			|||||||
	"github.com/kava-labs/kava/x/community/types"
 | 
						"github.com/kava-labs/kava/x/community/types"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const (
 | 
					 | 
				
			||||||
	ModuleName = "mint"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Migrate migrates the x/community module state from the consensus version 1 to
 | 
					// Migrate migrates the x/community module state from the consensus version 1 to
 | 
				
			||||||
// version 2. Specifically, sets new parameters in the module state.
 | 
					// version 2. Specifically, sets new parameters in the module state.
 | 
				
			||||||
func Migrate(
 | 
					func Migrate(
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										180
									
								
								x/community/testutil/consolidate.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										180
									
								
								x/community/testutil/consolidate.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,180 @@
 | 
				
			|||||||
 | 
					package testutil
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sdk "github.com/cosmos/cosmos-sdk/types"
 | 
				
			||||||
 | 
						banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types"
 | 
				
			||||||
 | 
						"github.com/kava-labs/kava/app"
 | 
				
			||||||
 | 
						types "github.com/kava-labs/kava/x/community/types"
 | 
				
			||||||
 | 
						kavadisttypes "github.com/kava-labs/kava/x/kavadist/types"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (suite *disableInflationTestSuite) TestStartCommunityFundConsolidation() {
 | 
				
			||||||
 | 
						tests := []struct {
 | 
				
			||||||
 | 
							name                   string
 | 
				
			||||||
 | 
							initialFeePoolCoins    sdk.DecCoins
 | 
				
			||||||
 | 
							initialKavadistBalance sdk.Coins
 | 
				
			||||||
 | 
						}{
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								"basic test with both balances and dust",
 | 
				
			||||||
 | 
								sdk.NewDecCoins(
 | 
				
			||||||
 | 
									sdk.NewDecCoinFromDec("ukava", sdk.NewDecWithPrec(123456, 2)),
 | 
				
			||||||
 | 
									sdk.NewDecCoinFromDec("usdx", sdk.NewDecWithPrec(654321, 3)),
 | 
				
			||||||
 | 
								),
 | 
				
			||||||
 | 
								sdk.NewCoins(
 | 
				
			||||||
 | 
									sdk.NewInt64Coin("ukava", 10_000),
 | 
				
			||||||
 | 
									sdk.NewInt64Coin("usdx", 10_000),
 | 
				
			||||||
 | 
								),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								"empty x/distribution feepool",
 | 
				
			||||||
 | 
								sdk.DecCoins(nil),
 | 
				
			||||||
 | 
								sdk.NewCoins(
 | 
				
			||||||
 | 
									sdk.NewInt64Coin("ukava", 10_000),
 | 
				
			||||||
 | 
									sdk.NewInt64Coin("usdx", 10_000),
 | 
				
			||||||
 | 
								),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								"empty x/kavadist balance",
 | 
				
			||||||
 | 
								sdk.NewDecCoins(
 | 
				
			||||||
 | 
									sdk.NewDecCoinFromDec("ukava", sdk.NewDecWithPrec(123456, 2)),
 | 
				
			||||||
 | 
									sdk.NewDecCoinFromDec("usdx", sdk.NewDecWithPrec(654321, 3)),
 | 
				
			||||||
 | 
								),
 | 
				
			||||||
 | 
								sdk.Coins{},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								"both x/distribution feepool and x/kavadist balance empty",
 | 
				
			||||||
 | 
								sdk.DecCoins(nil),
 | 
				
			||||||
 | 
								sdk.Coins{},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, tc := range tests {
 | 
				
			||||||
 | 
							suite.Run(tc.name, func() {
 | 
				
			||||||
 | 
								suite.SetupTest()
 | 
				
			||||||
 | 
								ak := suite.App.GetAccountKeeper()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								initialFeePool := distrtypes.FeePool{
 | 
				
			||||||
 | 
									CommunityPool: tc.initialFeePoolCoins,
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								initialFeePoolCoins, initialFeePoolDust := initialFeePool.CommunityPool.TruncateDecimal()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// More coins than initial feepool/communitypool
 | 
				
			||||||
 | 
								fundCoins := sdk.NewCoins(
 | 
				
			||||||
 | 
									sdk.NewInt64Coin("ukava", 10_000),
 | 
				
			||||||
 | 
									sdk.NewInt64Coin("usdx", 10_000),
 | 
				
			||||||
 | 
								)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// Always fund x/distribution with enough coins to cover feepool
 | 
				
			||||||
 | 
								err := suite.App.FundModuleAccount(
 | 
				
			||||||
 | 
									suite.Ctx,
 | 
				
			||||||
 | 
									distrtypes.ModuleName,
 | 
				
			||||||
 | 
									fundCoins,
 | 
				
			||||||
 | 
								)
 | 
				
			||||||
 | 
								suite.NoError(err, "x/distribution account should be funded without error")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								err = suite.App.FundModuleAccount(
 | 
				
			||||||
 | 
									suite.Ctx,
 | 
				
			||||||
 | 
									kavadisttypes.ModuleName,
 | 
				
			||||||
 | 
									tc.initialKavadistBalance,
 | 
				
			||||||
 | 
								)
 | 
				
			||||||
 | 
								suite.NoError(err, "x/kavadist account should be funded without error")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								suite.App.GetDistrKeeper().SetFeePool(suite.Ctx, initialFeePool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// Ensure the feepool was set before migration
 | 
				
			||||||
 | 
								feePoolBefore := suite.App.GetDistrKeeper().GetFeePool(suite.Ctx)
 | 
				
			||||||
 | 
								suite.Equal(initialFeePool, feePoolBefore, "initial feepool should be set")
 | 
				
			||||||
 | 
								communityBalanceBefore := suite.App.GetCommunityKeeper().GetModuleAccountBalance(suite.Ctx)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								kavadistAcc := ak.GetModuleAccount(suite.Ctx, kavadisttypes.KavaDistMacc)
 | 
				
			||||||
 | 
								kavaDistCoinsBefore := suite.App.GetBankKeeper().GetAllBalances(suite.Ctx, kavadistAcc.GetAddress())
 | 
				
			||||||
 | 
								suite.Equal(
 | 
				
			||||||
 | 
									tc.initialKavadistBalance,
 | 
				
			||||||
 | 
									kavaDistCoinsBefore,
 | 
				
			||||||
 | 
									"x/kavadist balance should be funded",
 | 
				
			||||||
 | 
								)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								expectedKavaDistCoins := sdk.NewCoins(sdk.NewCoin("ukava", kavaDistCoinsBefore.AmountOf("ukava")))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// -------------
 | 
				
			||||||
 | 
								// Run upgrade
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								params, found := suite.Keeper.GetParams(suite.Ctx)
 | 
				
			||||||
 | 
								suite.Require().True(found)
 | 
				
			||||||
 | 
								params.UpgradeTimeDisableInflation = suite.Ctx.BlockTime().Add(-time.Minute)
 | 
				
			||||||
 | 
								suite.Keeper.SetParams(suite.Ctx, params)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								err = suite.Keeper.StartCommunityFundConsolidation(suite.Ctx)
 | 
				
			||||||
 | 
								suite.NoError(err, "consolidation should not error")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// -------------
 | 
				
			||||||
 | 
								// Check results
 | 
				
			||||||
 | 
								suite.Run("module balances after consolidation should moved", func() {
 | 
				
			||||||
 | 
									feePoolAfter := suite.App.GetDistrKeeper().GetFeePool(suite.Ctx)
 | 
				
			||||||
 | 
									suite.Equal(
 | 
				
			||||||
 | 
										initialFeePoolDust,
 | 
				
			||||||
 | 
										feePoolAfter.CommunityPool,
 | 
				
			||||||
 | 
										"x/distribution community pool should be sent to x/community",
 | 
				
			||||||
 | 
									)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									kavaDistCoinsAfter := suite.App.GetBankKeeper().GetAllBalances(suite.Ctx, kavadistAcc.GetAddress())
 | 
				
			||||||
 | 
									suite.Equal(
 | 
				
			||||||
 | 
										expectedKavaDistCoins,
 | 
				
			||||||
 | 
										kavaDistCoinsAfter,
 | 
				
			||||||
 | 
										"x/kavadist balance should ony contain ukava",
 | 
				
			||||||
 | 
									)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									totalExpectedCommunityPoolCoins := communityBalanceBefore.
 | 
				
			||||||
 | 
										Add(initialFeePoolCoins...).      // x/distribution fee pool
 | 
				
			||||||
 | 
										Add(tc.initialKavadistBalance...) // x/kavadist module balance
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									communityBalanceAfter := suite.App.GetCommunityKeeper().GetModuleAccountBalance(suite.Ctx)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									// Use .IsAllGTE to avoid types.Coins(nil) vs types.Coins{} mismatch
 | 
				
			||||||
 | 
									suite.Truef(
 | 
				
			||||||
 | 
										totalExpectedCommunityPoolCoins.IsAllGTE(communityBalanceAfter),
 | 
				
			||||||
 | 
										"x/community balance should be increased by the truncated x/distribution community pool, got %s, expected %s",
 | 
				
			||||||
 | 
										communityBalanceAfter,
 | 
				
			||||||
 | 
										totalExpectedCommunityPoolCoins,
 | 
				
			||||||
 | 
									)
 | 
				
			||||||
 | 
								})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								suite.Run("bank transfer events should be emitted", func() {
 | 
				
			||||||
 | 
									communityAcc := ak.GetModuleAccount(suite.Ctx, types.ModuleAccountName)
 | 
				
			||||||
 | 
									distributionAcc := ak.GetModuleAccount(suite.Ctx, distrtypes.ModuleName)
 | 
				
			||||||
 | 
									kavadistAcc := ak.GetModuleAccount(suite.Ctx, kavadisttypes.KavaDistMacc)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									events := suite.Ctx.EventManager().Events()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									suite.NoError(
 | 
				
			||||||
 | 
										app.EventsContains(
 | 
				
			||||||
 | 
											events,
 | 
				
			||||||
 | 
											sdk.NewEvent(
 | 
				
			||||||
 | 
												banktypes.EventTypeTransfer,
 | 
				
			||||||
 | 
												sdk.NewAttribute(banktypes.AttributeKeyRecipient, communityAcc.GetAddress().String()),
 | 
				
			||||||
 | 
												sdk.NewAttribute(banktypes.AttributeKeySender, distributionAcc.GetAddress().String()),
 | 
				
			||||||
 | 
												sdk.NewAttribute(sdk.AttributeKeyAmount, initialFeePoolCoins.String()),
 | 
				
			||||||
 | 
											),
 | 
				
			||||||
 | 
										),
 | 
				
			||||||
 | 
									)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									suite.NoError(
 | 
				
			||||||
 | 
										app.EventsContains(
 | 
				
			||||||
 | 
											events,
 | 
				
			||||||
 | 
											sdk.NewEvent(
 | 
				
			||||||
 | 
												banktypes.EventTypeTransfer,
 | 
				
			||||||
 | 
												sdk.NewAttribute(banktypes.AttributeKeyRecipient, communityAcc.GetAddress().String()),
 | 
				
			||||||
 | 
												sdk.NewAttribute(banktypes.AttributeKeySender, kavadistAcc.GetAddress().String()),
 | 
				
			||||||
 | 
												sdk.NewAttribute(sdk.AttributeKeyAmount, kavaDistCoinsBefore.Sub(expectedKavaDistCoins...).String()),
 | 
				
			||||||
 | 
											),
 | 
				
			||||||
 | 
										),
 | 
				
			||||||
 | 
									)
 | 
				
			||||||
 | 
								})
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -3,6 +3,7 @@ package types
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	sdk "github.com/cosmos/cosmos-sdk/types"
 | 
						sdk "github.com/cosmos/cosmos-sdk/types"
 | 
				
			||||||
	authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
 | 
						authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
 | 
				
			||||||
 | 
						distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types"
 | 
				
			||||||
	minttypes "github.com/cosmos/cosmos-sdk/x/mint/types"
 | 
						minttypes "github.com/cosmos/cosmos-sdk/x/mint/types"
 | 
				
			||||||
	kavadisttypes "github.com/kava-labs/kava/x/kavadist/types"
 | 
						kavadisttypes "github.com/kava-labs/kava/x/kavadist/types"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
@ -40,6 +41,8 @@ type DistributionKeeper interface {
 | 
				
			|||||||
	DistributeFromFeePool(ctx sdk.Context, amount sdk.Coins, receiveAddr sdk.AccAddress) error
 | 
						DistributeFromFeePool(ctx sdk.Context, amount sdk.Coins, receiveAddr sdk.AccAddress) error
 | 
				
			||||||
	FundCommunityPool(ctx sdk.Context, amount sdk.Coins, sender sdk.AccAddress) error
 | 
						FundCommunityPool(ctx sdk.Context, amount sdk.Coins, sender sdk.AccAddress) error
 | 
				
			||||||
	GetFeePoolCommunityCoins(ctx sdk.Context) sdk.DecCoins
 | 
						GetFeePoolCommunityCoins(ctx sdk.Context) sdk.DecCoins
 | 
				
			||||||
 | 
						GetFeePool(ctx sdk.Context) distrtypes.FeePool
 | 
				
			||||||
 | 
						SetFeePool(ctx sdk.Context, feePool distrtypes.FeePool)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type MintKeeper interface {
 | 
					type MintKeeper interface {
 | 
				
			||||||
 | 
				
			|||||||
@ -47,7 +47,7 @@ func (suite *HandlerTestSuite) TestPayoutDelegatorClaimMultiDenom() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	// Claim denoms
 | 
						// Claim denoms
 | 
				
			||||||
	err := suite.DeliverIncentiveMsg(&msg)
 | 
						err := suite.DeliverIncentiveMsg(&msg)
 | 
				
			||||||
	suite.NoError(err)
 | 
						suite.Require().NoError(err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Check rewards were paid out
 | 
						// Check rewards were paid out
 | 
				
			||||||
	expectedRewardsHard := c("hard", int64(0.2*float64(2*7*1e6)))
 | 
						expectedRewardsHard := c("hard", int64(0.2*float64(2*7*1e6)))
 | 
				
			||||||
@ -97,7 +97,7 @@ func (suite *HandlerTestSuite) TestPayoutDelegatorClaimSingleDenom() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	// Claim rewards
 | 
						// Claim rewards
 | 
				
			||||||
	err := suite.DeliverIncentiveMsg(&msg)
 | 
						err := suite.DeliverIncentiveMsg(&msg)
 | 
				
			||||||
	suite.NoError(err)
 | 
						suite.Require().NoError(err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Check rewards were paid out
 | 
						// Check rewards were paid out
 | 
				
			||||||
	expectedRewards := c("swap", 2*7*1e6)
 | 
						expectedRewards := c("swap", 2*7*1e6)
 | 
				
			||||||
 | 
				
			|||||||
@ -40,7 +40,7 @@ func (suite *HandlerTestSuite) TestPayoutHardClaimMultiDenom() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	// Claim denoms
 | 
						// Claim denoms
 | 
				
			||||||
	err := suite.DeliverIncentiveMsg(&msg)
 | 
						err := suite.DeliverIncentiveMsg(&msg)
 | 
				
			||||||
	suite.NoError(err)
 | 
						suite.Require().NoError(err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Check rewards were paid out
 | 
						// Check rewards were paid out
 | 
				
			||||||
	expectedRewardsHard := c("hard", int64(0.2*float64(2*7*1e6)))
 | 
						expectedRewardsHard := c("hard", int64(0.2*float64(2*7*1e6)))
 | 
				
			||||||
@ -85,7 +85,7 @@ func (suite *HandlerTestSuite) TestPayoutHardClaimSingleDenom() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	// Claim rewards
 | 
						// Claim rewards
 | 
				
			||||||
	err := suite.DeliverIncentiveMsg(&msg)
 | 
						err := suite.DeliverIncentiveMsg(&msg)
 | 
				
			||||||
	suite.NoError(err)
 | 
						suite.Require().NoError(err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Check rewards were paid out
 | 
						// Check rewards were paid out
 | 
				
			||||||
	expectedRewards := c("swap", 2*7*1e6)
 | 
						expectedRewards := c("swap", 2*7*1e6)
 | 
				
			||||||
 | 
				
			|||||||
@ -130,7 +130,7 @@ func (suite *HandlerTestSuite) TestPayoutSwapClaimMultiDenom() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	// Claim rewards
 | 
						// Claim rewards
 | 
				
			||||||
	err := suite.DeliverIncentiveMsg(&msg)
 | 
						err := suite.DeliverIncentiveMsg(&msg)
 | 
				
			||||||
	suite.NoError(err)
 | 
						suite.Require().NoError(err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Check rewards were paid out
 | 
						// Check rewards were paid out
 | 
				
			||||||
	expectedRewardsHard := c("hard", int64(0.2*float64(7*1e6)))
 | 
						expectedRewardsHard := c("hard", int64(0.2*float64(7*1e6)))
 | 
				
			||||||
@ -176,7 +176,7 @@ func (suite *HandlerTestSuite) TestPayoutSwapClaimSingleDenom() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	// Claim rewards
 | 
						// Claim rewards
 | 
				
			||||||
	err := suite.DeliverIncentiveMsg(&msg)
 | 
						err := suite.DeliverIncentiveMsg(&msg)
 | 
				
			||||||
	suite.NoError(err)
 | 
						suite.Require().NoError(err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Check rewards were paid out
 | 
						// Check rewards were paid out
 | 
				
			||||||
	expectedRewards := c("swap", 7*1e6)
 | 
						expectedRewards := c("swap", 7*1e6)
 | 
				
			||||||
 | 
				
			|||||||
@ -32,7 +32,7 @@ func (suite *HandlerTestSuite) TestPayoutUSDXClaim() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	// Claim a single denom
 | 
						// Claim a single denom
 | 
				
			||||||
	err = suite.DeliverIncentiveMsg(&msg)
 | 
						err = suite.DeliverIncentiveMsg(&msg)
 | 
				
			||||||
	suite.NoError(err)
 | 
						suite.Require().NoError(err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Check rewards were paid out
 | 
						// Check rewards were paid out
 | 
				
			||||||
	expectedRewards := cs(c(types.USDXMintingRewardDenom, 7*1e6))
 | 
						expectedRewards := cs(c(types.USDXMintingRewardDenom, 7*1e6))
 | 
				
			||||||
 | 
				
			|||||||
@ -86,7 +86,7 @@ func (suite *BorrowIntegrationTests) TestSingleUserAccumulatesRewardsAfterSyncin
 | 
				
			|||||||
	})
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// User claims all their rewards
 | 
						// User claims all their rewards
 | 
				
			||||||
	suite.NoError(suite.DeliverIncentiveMsg(&msg))
 | 
						suite.Require().NoError(suite.DeliverIncentiveMsg(&msg))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// The users has always had 100% of borrows, so they should receive all rewards for the previous two blocks.
 | 
						// The users has always had 100% of borrows, so they should receive all rewards for the previous two blocks.
 | 
				
			||||||
	// Total rewards for each block is block duration * rewards per second
 | 
						// Total rewards for each block is block duration * rewards per second
 | 
				
			||||||
 | 
				
			|||||||
@ -89,7 +89,7 @@ func (suite *SupplyIntegrationTests) TestSingleUserAccumulatesRewardsAfterSyncin
 | 
				
			|||||||
		})
 | 
							})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// User claims all their rewards
 | 
						// User claims all their rewards
 | 
				
			||||||
	suite.NoError(suite.DeliverIncentiveMsg(&msg))
 | 
						suite.Require().NoError(suite.DeliverIncentiveMsg(&msg))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// The users has always had 100% of deposits, so they should receive all rewards for the previous two blocks.
 | 
						// The users has always had 100% of deposits, so they should receive all rewards for the previous two blocks.
 | 
				
			||||||
	// Total rewards for each block is block duration * rewards per second
 | 
						// Total rewards for each block is block duration * rewards per second
 | 
				
			||||||
 | 
				
			|||||||
@ -94,7 +94,7 @@ func (suite *USDXIntegrationTests) TestSingleUserAccumulatesRewardsAfterSyncing(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	// User claims all their rewards
 | 
						// User claims all their rewards
 | 
				
			||||||
	msg := types.NewMsgClaimUSDXMintingReward(userA.String(), "large")
 | 
						msg := types.NewMsgClaimUSDXMintingReward(userA.String(), "large")
 | 
				
			||||||
	suite.NoError(suite.DeliverIncentiveMsg(&msg))
 | 
						suite.Require().NoError(suite.DeliverIncentiveMsg(&msg))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// The users has always had 100% of cdp debt, so they should receive all rewards for the previous two blocks.
 | 
						// The users has always had 100% of cdp debt, so they should receive all rewards for the previous two blocks.
 | 
				
			||||||
	// Total rewards for each block is block duration * rewards per second
 | 
						// Total rewards for each block is block duration * rewards per second
 | 
				
			||||||
@ -141,7 +141,7 @@ func (suite *USDXIntegrationTests) TestSingleUserAccumulatesRewardsWithoutSyncin
 | 
				
			|||||||
	suite.NextBlockAfter(1e6 * time.Second)
 | 
						suite.NextBlockAfter(1e6 * time.Second)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	msg := types.NewMsgClaimUSDXMintingReward(user.String(), "large")
 | 
						msg := types.NewMsgClaimUSDXMintingReward(user.String(), "large")
 | 
				
			||||||
	suite.NoError(suite.DeliverIncentiveMsg(&msg))
 | 
						suite.Require().NoError(suite.DeliverIncentiveMsg(&msg))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// The users has always had 100% of cdp debt, so they should receive all rewards for the previous two blocks.
 | 
						// The users has always had 100% of cdp debt, so they should receive all rewards for the previous two blocks.
 | 
				
			||||||
	// Total rewards for each block is block duration * rewards per second
 | 
						// Total rewards for each block is block duration * rewards per second
 | 
				
			||||||
@ -217,7 +217,7 @@ func (suite *USDXIntegrationTests) TestReinstatingRewardParamsDoesNotTriggerOver
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	// Claim rewards
 | 
						// Claim rewards
 | 
				
			||||||
	msg := types.NewMsgClaimUSDXMintingReward(userB.String(), "large")
 | 
						msg := types.NewMsgClaimUSDXMintingReward(userB.String(), "large")
 | 
				
			||||||
	suite.NoError(suite.DeliverIncentiveMsg(&msg))
 | 
						suite.Require().NoError(suite.DeliverIncentiveMsg(&msg))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// The cdp had half the total borrows for a 1s block. So should earn half the rewards for that block
 | 
						// The cdp had half the total borrows for a 1s block. So should earn half the rewards for that block
 | 
				
			||||||
	suite.BalanceInEpsilon(
 | 
						suite.BalanceInEpsilon(
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user