mirror of
				https://github.com/0glabs/0g-chain.git
				synced 2025-11-04 05:57:33 +00:00 
			
		
		
		
	* Update cometbft, cosmos, ethermint, and ibc-go * Replace github.com/tendermint/tendermint by github.com/cometbft/cometbft * Replace github.com/tendermint/tm-db by github.com/cometbft/cometbft-db * Replace gogo/protobuf with cosmos/gogoproto & simapp replacement * Replace cosmos-sdk/simapp/helpers with cosmos-sdk/testutil/sims * Remove no longer used simulations * Replace ibchost with ibcexported See https://github.com/cosmos/ibc-go/blob/v7.2.2/docs/migrations/v6-to-v7.md#ibc-module-constants * Add new consensus params keeper * Add consensus keeper to blockers * Fix keeper and module issues in app.go * Add IsSendEnabledCoins and update SetParams interface changes * Fix protobuf build for cosmos 47 (#1800) * fix cp errors by using -f; fix lint by only linting our proto dir; and use proofs.proto directly from ics23 for ibc-go v7 * run proto-all; commit updated third party deps and swagger changes * regenerate proto files * use correct gocosmos build plugin for buf * re-gen all protobuf files to update paths for new gocosmos plugin * update protoc and buf to latest versions * fix staking keeper issues in app.go * update tally handler for gov changes * chain id fix and flag fixes * update deps for cometbft 47.7 upgrade * remove all module legacy queriers * update stakingKeeper to pointer * Replace ModuleCdc from govv1beta1 to govcodec * remove simulations * abci.LastCommitInfo → abci.CommitInfo * Remove unused code in keys.go * simapp.MakeTestEncodingConfig -> moduletestutil.MakeTestEncodingConfi * Fix chain id issues in tests * Fix remaining unit test issues * Update changelog for upgrade * Fix e2e tests using updated kvtool * Update protonet to v47 compatible genesis * Bump cometbft-db to v0.9.1-kava.1 * Update kvtool * Remove extra changelog * Fix merged rocksdb issues * go mod cleanup * Bump cometbft-db to v9 and go to 1.21 * Bump rocksdb version to v8.10.0 * Update kvtool to latest version * Update gin to v1.9.0 * Use ibctm.ModuleName in app_test * Fallback to genesis chain id instead of client toml * Remove all simulations * Fix cdp migrations issue with v47 * Update dependencies to correct tags --------- Co-authored-by: Nick DeLuca <nickdeluca08@gmail.com>
		
			
				
	
	
		
			422 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			422 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package testutil
 | 
						|
 | 
						|
import (
 | 
						|
	"fmt"
 | 
						|
	"math"
 | 
						|
	"math/rand"
 | 
						|
	"time"
 | 
						|
 | 
						|
	tmproto "github.com/cometbft/cometbft/proto/tendermint/types"
 | 
						|
	"github.com/stretchr/testify/suite"
 | 
						|
 | 
						|
	sdkmath "cosmossdk.io/math"
 | 
						|
	sdk "github.com/cosmos/cosmos-sdk/types"
 | 
						|
	authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
 | 
						|
	"github.com/kava-labs/kava/app"
 | 
						|
	"github.com/kava-labs/kava/x/community"
 | 
						|
	"github.com/kava-labs/kava/x/community/keeper"
 | 
						|
	"github.com/kava-labs/kava/x/community/types"
 | 
						|
)
 | 
						|
 | 
						|
// StakingRewardsTestSuite tests staking rewards per second logic
 | 
						|
type stakingRewardsTestSuite struct {
 | 
						|
	suite.Suite
 | 
						|
 | 
						|
	App    app.TestApp
 | 
						|
	Keeper keeper.Keeper
 | 
						|
 | 
						|
	testFunc testFunc
 | 
						|
}
 | 
						|
 | 
						|
func NewStakingRewardsTestSuite(tf testFunc) *stakingRewardsTestSuite {
 | 
						|
	suite := &stakingRewardsTestSuite{}
 | 
						|
	suite.testFunc = tf
 | 
						|
	return suite
 | 
						|
}
 | 
						|
 | 
						|
// The default state used by each test
 | 
						|
func (suite *stakingRewardsTestSuite) SetupTest() {
 | 
						|
	app.SetSDKConfig()
 | 
						|
 | 
						|
	tApp := app.NewTestApp()
 | 
						|
	tApp.InitializeFromGenesisStates()
 | 
						|
 | 
						|
	suite.App = tApp
 | 
						|
	suite.Keeper = suite.App.GetCommunityKeeper()
 | 
						|
}
 | 
						|
 | 
						|
func (suite *stakingRewardsTestSuite) TestStakingRewards() {
 | 
						|
	testCases := []struct {
 | 
						|
		// name of subtest
 | 
						|
		name string
 | 
						|
 | 
						|
		// block time of first block
 | 
						|
		periodStart time.Time
 | 
						|
		// block time of last block
 | 
						|
		periodEnd time.Time
 | 
						|
 | 
						|
		// block time n will be periodStart + rand(range_min...range_max)*(n-1) up to periodEnd
 | 
						|
		blockTimeRangeMin float64
 | 
						|
		blockTimeRangeMax float64
 | 
						|
 | 
						|
		// rewards per second to set in state
 | 
						|
		rewardsPerSecond sdkmath.LegacyDec
 | 
						|
 | 
						|
		// the amount of ukava to mint and transfer to the community pool
 | 
						|
		// to use to pay for rewards
 | 
						|
		communityPoolFunds sdkmath.Int
 | 
						|
 | 
						|
		// how many total rewards are expected to be accumulated in ukava
 | 
						|
		expectedRewardsTotal sdkmath.Int
 | 
						|
	}{
 | 
						|
		// ** These take a long time to run **
 | 
						|
		//{
 | 
						|
		//	name:                 "one year with 0.5 to 1 second block times",
 | 
						|
		//	periodStart:          time.Date(2023, 1, 1, 0, 0, 0, 0, time.UTC),
 | 
						|
		//	periodEnd:            time.Date(2024, 1, 1, 0, 0, 0, 0, time.UTC),
 | 
						|
		//	blockTimeRangeMin:    0.5,
 | 
						|
		//	blockTimeRangeMax:    1,
 | 
						|
		//	rewardsPerSecond:     sdkmath.LegacyMustNewDecFromStr("1585489.599188229325215626"),
 | 
						|
		//	expectedRewardsTotal: sdkmath.NewInt(49999999999999), // 50 million KAVA per year
 | 
						|
		//},
 | 
						|
		//{
 | 
						|
		//	name:                 "one year with 5.5 to 6.5 second blocktimes",
 | 
						|
		//	periodStart:          time.Date(2023, 1, 1, 0, 0, 0, 0, time.UTC),
 | 
						|
		//	periodEnd:            time.Date(2024, 1, 1, 0, 0, 0, 0, time.UTC),
 | 
						|
		//	blockTimeRangeMin:    5.5,
 | 
						|
		//	blockTimeRangeMax:    6.5,
 | 
						|
		//	rewardsPerSecond:     sdkmath.LegacyMustNewDecFromStr("1585489.599188229325215626"), // 50 million kava per year
 | 
						|
		//	communityPoolFunds:   sdkmath.NewInt(50000000000000),
 | 
						|
		//	expectedRewardsTotal: sdkmath.NewInt(49999999999999), // truncation results in 1 ukava error
 | 
						|
		//},
 | 
						|
		//
 | 
						|
		//
 | 
						|
		//  One Day of blocks with different block time variations
 | 
						|
		//
 | 
						|
		//
 | 
						|
		{
 | 
						|
			name:                 "one day with sub-second block times and 50 million KAVA per year",
 | 
						|
			periodStart:          time.Date(2023, 1, 1, 0, 0, 0, 0, time.UTC),
 | 
						|
			periodEnd:            time.Date(2023, 1, 2, 0, 0, 0, 0, time.UTC),
 | 
						|
			blockTimeRangeMin:    0.1,
 | 
						|
			blockTimeRangeMax:    1,
 | 
						|
			rewardsPerSecond:     sdkmath.LegacyMustNewDecFromStr("1585489.599188229325215626"), // 50 million kava per year
 | 
						|
			communityPoolFunds:   sdkmath.NewInt(200000000000),
 | 
						|
			expectedRewardsTotal: sdkmath.NewInt(136986301369), // 50 million / 365 days  - 1 ukava
 | 
						|
 | 
						|
		},
 | 
						|
		{
 | 
						|
			name:                 "one day with 5.5 to 6.5 second block times and 50 million KAVA per year",
 | 
						|
			periodStart:          time.Date(2023, 1, 1, 0, 0, 0, 0, time.UTC),
 | 
						|
			periodEnd:            time.Date(2023, 1, 2, 0, 0, 0, 0, time.UTC),
 | 
						|
			blockTimeRangeMin:    5.5,
 | 
						|
			blockTimeRangeMax:    6.5,
 | 
						|
			rewardsPerSecond:     sdkmath.LegacyMustNewDecFromStr("1585489.599188229325215626"), // 50 million kava per year
 | 
						|
			communityPoolFunds:   sdkmath.NewInt(200000000000),
 | 
						|
			expectedRewardsTotal: sdkmath.NewInt(136986301369), // 50 million / 365 days  - 1 ukava
 | 
						|
		},
 | 
						|
		//
 | 
						|
		//
 | 
						|
		// Total time span under 1 second
 | 
						|
		//
 | 
						|
		//
 | 
						|
		{
 | 
						|
			name:                 "single 6.9 second time span and 25 million KAVA per year",
 | 
						|
			periodStart:          time.Date(2023, 1, 1, 0, 0, 0, 0, time.UTC),
 | 
						|
			periodEnd:            time.Date(2023, 1, 1, 0, 0, 6, 900000000, time.UTC),
 | 
						|
			blockTimeRangeMin:    10, // forces only two blocks -- one time span
 | 
						|
			blockTimeRangeMax:    10,
 | 
						|
			rewardsPerSecond:     sdkmath.LegacyMustNewDecFromStr("792744.799594114662607813"), // 25 million kava per year
 | 
						|
			communityPoolFunds:   sdkmath.NewInt(10000000),
 | 
						|
			expectedRewardsTotal: sdkmath.NewInt(5469939), // per second rate * 6.9
 | 
						|
		},
 | 
						|
		{
 | 
						|
			name:                 "multiple blocks across sub-second time span nd 10 million KAVA per year",
 | 
						|
			periodStart:          time.Date(2023, 1, 1, 0, 0, 0, 0, time.UTC),
 | 
						|
			periodEnd:            time.Date(2023, 1, 1, 0, 0, 0, 800000000, time.UTC),
 | 
						|
			blockTimeRangeMin:    0.1, // multiple blocks in a sub-second time span
 | 
						|
			blockTimeRangeMax:    0.2,
 | 
						|
			rewardsPerSecond:     sdkmath.LegacyMustNewDecFromStr("317097.919837645865043125"), // 10 million kava per year
 | 
						|
			communityPoolFunds:   sdkmath.NewInt(300000),
 | 
						|
			expectedRewardsTotal: sdkmath.NewInt(253678), // per second rate * 0.8
 | 
						|
		},
 | 
						|
		//
 | 
						|
		//
 | 
						|
		// Variations of community pool balance
 | 
						|
		//
 | 
						|
		//
 | 
						|
		{
 | 
						|
			name:                 "community pool exact funds -- should spend community to zero and not panic",
 | 
						|
			periodStart:          time.Date(2023, 1, 1, 0, 0, 0, 0, time.UTC),
 | 
						|
			periodEnd:            time.Date(2023, 1, 2, 0, 0, 0, 0, time.UTC),
 | 
						|
			blockTimeRangeMin:    5.5,
 | 
						|
			blockTimeRangeMax:    6.2,
 | 
						|
			rewardsPerSecond:     sdkmath.LegacyMustNewDecFromStr("317097.919837645865043125"), // 10 million kava per year
 | 
						|
			communityPoolFunds:   sdkmath.NewInt(27397260273),
 | 
						|
			expectedRewardsTotal: sdkmath.NewInt(27397260273),
 | 
						|
		},
 | 
						|
		{
 | 
						|
			name:                 "community pool under funded -- should spend community pool to down to zero and not panic",
 | 
						|
			periodStart:          time.Date(2023, 1, 1, 0, 0, 0, 0, time.UTC),
 | 
						|
			periodEnd:            time.Date(2023, 1, 2, 0, 0, 0, 0, time.UTC),
 | 
						|
			blockTimeRangeMin:    5.5,
 | 
						|
			blockTimeRangeMax:    6.5,
 | 
						|
			rewardsPerSecond:     sdkmath.LegacyMustNewDecFromStr("1585489.599188229325215626"), // 25 million kava per year
 | 
						|
			communityPoolFunds:   sdkmath.NewInt(100000000000),                                  // under funded
 | 
						|
			expectedRewardsTotal: sdkmath.NewInt(100000000000),                                  // rewards max is the community pool balance
 | 
						|
		},
 | 
						|
		{
 | 
						|
			name:                 "community pool no funds -- should pay zero rewards and not panic",
 | 
						|
			periodStart:          time.Date(2023, 1, 1, 0, 0, 0, 0, time.UTC),
 | 
						|
			periodEnd:            time.Date(2023, 1, 2, 0, 0, 0, 0, time.UTC),
 | 
						|
			blockTimeRangeMin:    5.5,
 | 
						|
			blockTimeRangeMax:    6.5,
 | 
						|
			rewardsPerSecond:     sdkmath.LegacyMustNewDecFromStr("792744.799594114662607813"), // 25 million kava per year
 | 
						|
			communityPoolFunds:   sdkmath.NewInt(0),
 | 
						|
			expectedRewardsTotal: sdkmath.NewInt(0),
 | 
						|
		},
 | 
						|
		//
 | 
						|
		//
 | 
						|
		// Disabled
 | 
						|
		//
 | 
						|
		//
 | 
						|
		{
 | 
						|
			name:                 "zero rewards per second results in zero rewards paid",
 | 
						|
			periodStart:          time.Date(2023, 1, 1, 0, 0, 0, 0, time.UTC),
 | 
						|
			periodEnd:            time.Date(2023, 1, 2, 0, 0, 0, 0, time.UTC),
 | 
						|
			blockTimeRangeMin:    5.5,
 | 
						|
			blockTimeRangeMax:    6.5,
 | 
						|
			rewardsPerSecond:     sdkmath.LegacyMustNewDecFromStr("0.000000000000000000"), // 25 million kava per year
 | 
						|
			communityPoolFunds:   sdkmath.NewInt(100000000000000),
 | 
						|
			expectedRewardsTotal: sdkmath.NewInt(0),
 | 
						|
		},
 | 
						|
		//
 | 
						|
		//
 | 
						|
		// Test underlying calculations are safe and overflow/underflow bounds are reasonable
 | 
						|
		//
 | 
						|
		//
 | 
						|
		{
 | 
						|
			name:                 "does not overflow with extremely large per second value and extremely large single block durations",
 | 
						|
			periodStart:          time.Date(2023, 1, 1, 0, 0, 0, 0, time.UTC),
 | 
						|
			periodEnd:            time.Date(2033, 1, 1, 0, 0, 0, 0, time.UTC),
 | 
						|
			blockTimeRangeMin:    315619200,                                                                         // a single 10 year long block in seconds (w/ 3 leap years)
 | 
						|
			blockTimeRangeMax:    315619200,                                                                         // a single 10 year long block in seconds (w/ 3 leap years)
 | 
						|
			rewardsPerSecond:     sdkmath.LegacyMustNewDecFromStr("100000000000000000000000000.000000000000000000"), // 100 million kava per second in 18 decimal form
 | 
						|
			communityPoolFunds:   newIntFromString("40000000000000000000000000000000000"),
 | 
						|
			expectedRewardsTotal: newIntFromString("31561920000000000000000000000000000"), // 10 years worth of rewards (with three leap years)
 | 
						|
		},
 | 
						|
		{
 | 
						|
			name:                 "able to accumulate decimal ukava units across blocks",
 | 
						|
			periodStart:          time.Date(2023, 1, 1, 0, 0, 0, 0, time.UTC),
 | 
						|
			periodEnd:            time.Date(2023, 1, 2, 0, 0, 0, 0, time.UTC),
 | 
						|
			blockTimeRangeMin:    5.5,
 | 
						|
			blockTimeRangeMax:    6.5,
 | 
						|
			rewardsPerSecond:     sdkmath.LegacyMustNewDecFromStr("0.100000000000000000"), // blocks are not long enough to accumulate a single ukava with this rate
 | 
						|
			communityPoolFunds:   sdkmath.NewInt(10000),
 | 
						|
			expectedRewardsTotal: sdkmath.NewInt(8640),
 | 
						|
		},
 | 
						|
		{
 | 
						|
			name:                 "down to 1 ukava per year can be accumulated -- we are safe from underflow at reasonably small values",
 | 
						|
			periodStart:          time.Date(2023, 1, 1, 0, 0, 0, 0, time.UTC),
 | 
						|
			periodEnd:            time.Date(2024, 1, 1, 0, 0, 0, 0, time.UTC),
 | 
						|
			blockTimeRangeMin:    60, // large block times speed up this test case
 | 
						|
			blockTimeRangeMax:    120,
 | 
						|
			rewardsPerSecond:     sdkmath.LegacyMustNewDecFromStr("0.000000031709791984"),
 | 
						|
			communityPoolFunds:   sdkmath.NewInt(1),
 | 
						|
			expectedRewardsTotal: sdkmath.NewInt(1),
 | 
						|
		},
 | 
						|
	}
 | 
						|
 | 
						|
	for _, tc := range testCases {
 | 
						|
		suite.Run(tc.name, func() {
 | 
						|
			suite.SetupTest()
 | 
						|
 | 
						|
			// keepers
 | 
						|
			keeper := suite.Keeper
 | 
						|
			accountKeeper := suite.App.GetAccountKeeper()
 | 
						|
			bankKeeper := suite.App.GetBankKeeper()
 | 
						|
 | 
						|
			// initial context at height 1
 | 
						|
			height := int64(1)
 | 
						|
			blockTime := tc.periodStart
 | 
						|
			ctx := suite.App.NewContext(true, tmproto.Header{Height: height, Time: blockTime})
 | 
						|
 | 
						|
			// ensure community pool balance matches the test expectations
 | 
						|
			poolAcc := accountKeeper.GetModuleAccount(ctx, types.ModuleName)
 | 
						|
			// community pool balance should start at zero
 | 
						|
			suite.Require().True(bankKeeper.GetBalance(ctx, poolAcc.GetAddress(), "ukava").Amount.IsZero(), "expected community pool to start with zero coins in test genesis")
 | 
						|
			// fund withexact amount from test case
 | 
						|
			suite.App.FundAccount(ctx, poolAcc.GetAddress(), sdk.NewCoins(sdk.NewCoin("ukava", tc.communityPoolFunds)))
 | 
						|
 | 
						|
			// get starting balance of fee collector to substract later in case this is non-zero in genesis
 | 
						|
			feeCollectorAcc := accountKeeper.GetModuleAccount(ctx, authtypes.FeeCollectorName)
 | 
						|
			initialFeeCollectorBalance := bankKeeper.GetBalance(ctx, feeCollectorAcc.GetAddress(), "ukava").Amount
 | 
						|
 | 
						|
			// set rewards per second in state
 | 
						|
			params, found := keeper.GetParams(ctx)
 | 
						|
			suite.Require().True(found)
 | 
						|
			params.StakingRewardsPerSecond = tc.rewardsPerSecond
 | 
						|
			keeper.SetParams(ctx, params)
 | 
						|
 | 
						|
			stakingRewardEvents := sdk.Events{}
 | 
						|
 | 
						|
			for {
 | 
						|
				// run community begin blocker logic
 | 
						|
				suite.testFunc(ctx, keeper)
 | 
						|
 | 
						|
				// accumulate event rewards from events
 | 
						|
				stakingRewardEvents = append(stakingRewardEvents, filterStakingRewardEvents(ctx.EventManager().Events())...)
 | 
						|
 | 
						|
				// exit loop if we are at last block
 | 
						|
				if blockTime.Equal(tc.periodEnd) {
 | 
						|
					break
 | 
						|
				}
 | 
						|
 | 
						|
				// create random block duration in nanoseconds
 | 
						|
				randomBlockDurationInSeconds := tc.blockTimeRangeMin + rand.Float64()*(tc.blockTimeRangeMax-tc.blockTimeRangeMin)
 | 
						|
				nextBlockDuration := time.Duration(randomBlockDurationInSeconds * math.Pow10(9))
 | 
						|
 | 
						|
				// move to next block by incrementing height, adding random duration, and settings new context
 | 
						|
				height++
 | 
						|
				blockTime = blockTime.Add(nextBlockDuration)
 | 
						|
				// set last block to exact end of period if we go past
 | 
						|
				if blockTime.After(tc.periodEnd) {
 | 
						|
					blockTime = tc.periodEnd
 | 
						|
				}
 | 
						|
				ctx = suite.App.NewContext(true, tmproto.Header{Height: height, Time: blockTime})
 | 
						|
			}
 | 
						|
 | 
						|
			endingFeeCollectorBalance := bankKeeper.GetBalance(ctx, feeCollectorAcc.GetAddress(), "ukava").Amount
 | 
						|
			feeCollectorBalanceAdded := endingFeeCollectorBalance.Sub(initialFeeCollectorBalance)
 | 
						|
 | 
						|
			// assert fee pool was payed the correct rewards
 | 
						|
			suite.Equal(tc.expectedRewardsTotal.String(), feeCollectorBalanceAdded.String(), "expected fee collector balance to match")
 | 
						|
 | 
						|
			if tc.expectedRewardsTotal.IsZero() {
 | 
						|
				suite.Equal(0, len(stakingRewardEvents), "expected no events to be emitted")
 | 
						|
			} else {
 | 
						|
				// we add up all reward coin events
 | 
						|
				eventCoins := getRewardCoinsFromEvents(stakingRewardEvents)
 | 
						|
 | 
						|
				// assert events emitted match expected rewards
 | 
						|
				suite.Equal(
 | 
						|
					tc.expectedRewardsTotal.String(),
 | 
						|
					eventCoins.AmountOf("ukava").String(),
 | 
						|
					"expected event coins to match",
 | 
						|
				)
 | 
						|
			}
 | 
						|
 | 
						|
			// assert the community pool deducted the same amount
 | 
						|
			expectedCommunityPoolBalance := tc.communityPoolFunds.Sub(tc.expectedRewardsTotal)
 | 
						|
			actualCommunityPoolBalance := bankKeeper.GetBalance(ctx, poolAcc.GetAddress(), "ukava").Amount
 | 
						|
			suite.Equal(expectedCommunityPoolBalance.String(), actualCommunityPoolBalance.String(), "expected community pool balance to match")
 | 
						|
		})
 | 
						|
	}
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
func (suite *stakingRewardsTestSuite) TestStakingRewardsDoNotAccumulateWhenPoolIsDrained() {
 | 
						|
	app := suite.App
 | 
						|
	keeper := suite.Keeper
 | 
						|
	accountKeeper := suite.App.GetAccountKeeper()
 | 
						|
	bankKeeper := suite.App.GetBankKeeper()
 | 
						|
 | 
						|
	// first block
 | 
						|
	blockTime := time.Now()
 | 
						|
	ctx := app.NewContext(true, tmproto.Header{Height: 1, Time: blockTime})
 | 
						|
 | 
						|
	poolAcc := accountKeeper.GetModuleAccount(ctx, types.ModuleName)
 | 
						|
	feeCollectorAcc := accountKeeper.GetModuleAccount(ctx, authtypes.FeeCollectorName)
 | 
						|
 | 
						|
	// set state to pay staking rewards
 | 
						|
	params, _ := keeper.GetParams(ctx)
 | 
						|
	// we set a decimal amount that ensures after 10 seconds we overspend the community pool
 | 
						|
	// with enough truncation error that we would have an ending balance of 20.000001 if it was
 | 
						|
	// carried over after the pool run out of funds
 | 
						|
	params.StakingRewardsPerSecond = sdkmath.LegacyMustNewDecFromStr("1000000.099999999999999999") // > 1 KAVA per second
 | 
						|
	keeper.SetParams(ctx, params)
 | 
						|
 | 
						|
	// fund community pool account
 | 
						|
	app.FundAccount(ctx, poolAcc.GetAddress(), sdk.NewCoins(sdk.NewCoin("ukava", sdkmath.NewInt(10000000)))) // 10 KAVA
 | 
						|
	initialFeeCollectorBalance := bankKeeper.GetBalance(ctx, feeCollectorAcc.GetAddress(), "ukava").Amount
 | 
						|
 | 
						|
	// run first block (no rewards hapeen on first block)
 | 
						|
	community.BeginBlocker(ctx, keeper)
 | 
						|
 | 
						|
	// run second block 10 seconds in future and spend all community pool rewards
 | 
						|
	blockTime = blockTime.Add(10 * time.Second)
 | 
						|
	ctx = app.NewContext(true, tmproto.Header{Height: 2, Time: blockTime})
 | 
						|
	community.BeginBlocker(ctx, keeper)
 | 
						|
 | 
						|
	// run third block 10 seconds in future which no rewards will be paid
 | 
						|
	blockTime = blockTime.Add(10 * time.Second)
 | 
						|
	ctx = app.NewContext(true, tmproto.Header{Height: 3, Time: blockTime})
 | 
						|
	community.BeginBlocker(ctx, keeper)
 | 
						|
 | 
						|
	// run fourth block 10 seconds in future which no rewards will be paid
 | 
						|
	blockTime = blockTime.Add(10 * time.Second)
 | 
						|
	ctx = app.NewContext(true, tmproto.Header{Height: 4, Time: blockTime})
 | 
						|
	community.BeginBlocker(ctx, keeper)
 | 
						|
 | 
						|
	// refund the community pool with 100 KAVA -- plenty of funds
 | 
						|
	app.FundAccount(ctx, poolAcc.GetAddress(), sdk.NewCoins(sdk.NewCoin("ukava", sdkmath.NewInt(100000000)))) // 100 KAVA
 | 
						|
 | 
						|
	// run fifth block 10 seconds in future which no rewards will be paid
 | 
						|
	blockTime = blockTime.Add(10 * time.Second)
 | 
						|
	ctx = app.NewContext(true, tmproto.Header{Height: 5, Time: blockTime})
 | 
						|
	community.BeginBlocker(ctx, keeper)
 | 
						|
 | 
						|
	// assert that only 20 total KAVA has been distributed in rewards
 | 
						|
	// and blocks where community pool had d
 | 
						|
	rewards := bankKeeper.GetBalance(ctx, feeCollectorAcc.GetAddress(), "ukava").Amount.Sub(initialFeeCollectorBalance)
 | 
						|
	suite.Require().Equal(sdkmath.NewInt(20000000).String(), rewards.String())
 | 
						|
}
 | 
						|
 | 
						|
func (suite *stakingRewardsTestSuite) TestPanicsOnMissingParameters() {
 | 
						|
	suite.SetupTest()
 | 
						|
 | 
						|
	ctx := suite.App.NewContext(true, tmproto.Header{Height: 1, Time: time.Now()})
 | 
						|
	store := ctx.KVStore(suite.App.GetKVStoreKey(types.StoreKey))
 | 
						|
	store.Delete(types.ParamsKey)
 | 
						|
 | 
						|
	suite.PanicsWithValue("invalid state: module parameters not found", func() {
 | 
						|
		suite.testFunc(ctx, suite.Keeper)
 | 
						|
	})
 | 
						|
}
 | 
						|
 | 
						|
// newIntFromString returns a new sdkmath.Int from a string
 | 
						|
func newIntFromString(str string) sdkmath.Int {
 | 
						|
	num, ok := sdkmath.NewIntFromString(str)
 | 
						|
	if !ok {
 | 
						|
		panic(fmt.Sprintf("overflow creating Int from %s", str))
 | 
						|
	}
 | 
						|
	return num
 | 
						|
}
 | 
						|
 | 
						|
func filterStakingRewardEvents(events sdk.Events) (rewardEvents sdk.Events) {
 | 
						|
	for _, event := range events {
 | 
						|
		if event.Type == types.EventTypeStakingRewardsPaid {
 | 
						|
			rewardEvents = append(rewardEvents, event)
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return
 | 
						|
}
 | 
						|
 | 
						|
func getRewardCoinsFromEvents(events sdk.Events) sdk.Coins {
 | 
						|
	coins := sdk.NewCoins()
 | 
						|
 | 
						|
	for _, event := range events {
 | 
						|
		if event.Type == types.EventTypeStakingRewardsPaid {
 | 
						|
			rewards, err := sdk.ParseCoinNormalized(string(event.Attributes[0].Value))
 | 
						|
			if err != nil {
 | 
						|
				panic(err)
 | 
						|
			}
 | 
						|
 | 
						|
			coins = coins.Add(rewards)
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return coins
 | 
						|
}
 |