2023-10-02 20:10:22 +00:00
package testutil
import (
"time"
sdk "github.com/cosmos/cosmos-sdk/types"
2023-10-23 19:15:44 +00:00
distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types"
2023-10-02 20:10:22 +00:00
minttypes "github.com/cosmos/cosmos-sdk/x/mint/types"
"github.com/stretchr/testify/suite"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
tmtime "github.com/tendermint/tendermint/types/time"
2023-10-03 15:41:54 +00:00
sdkmath "cosmossdk.io/math"
2023-10-02 20:10:22 +00:00
"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"
kavadisttypes "github.com/kava-labs/kava/x/kavadist/types"
)
type testFunc func ( sdk . Context , keeper . Keeper )
// Test suite used for all abci inflation tests
type disableInflationTestSuite struct {
suite . Suite
App app . TestApp
Ctx sdk . Context
Keeper keeper . Keeper
genesisMintState * minttypes . GenesisState
genesisKavadistState * kavadisttypes . GenesisState
2023-10-23 19:15:44 +00:00
genesisDistrState * distrtypes . GenesisState
2023-10-02 20:10:22 +00:00
testFunc testFunc
}
func NewDisableInflationTestSuite ( tf testFunc ) * disableInflationTestSuite {
suite := & disableInflationTestSuite { }
suite . testFunc = tf
return suite
}
// The default state used by each test
func ( suite * disableInflationTestSuite ) SetupTest ( ) {
app . SetSDKConfig ( )
tApp := app . NewTestApp ( )
suite . App = tApp
suite . Ctx = suite . App . NewContext ( true , tmproto . Header { Height : 1 , Time : tmtime . Now ( ) } )
suite . Keeper = suite . App . GetCommunityKeeper ( )
// Set up x/mint and x/kavadist gen state
mintGen := minttypes . DefaultGenesisState ( )
mintGen . Params . InflationMax = sdk . NewDecWithPrec ( 595 , 3 )
mintGen . Params . InflationMin = sdk . NewDecWithPrec ( 595 , 3 )
suite . genesisMintState = mintGen
kavadistGen := kavadisttypes . DefaultGenesisState ( )
kavadistGen . Params . Active = true
suite . genesisKavadistState = kavadistGen
2023-10-23 19:15:44 +00:00
distrGen := distrtypes . DefaultGenesisState ( )
distrGen . Params . CommunityTax = sdk . MustNewDecFromStr ( "0.949500000000000000" )
suite . genesisDistrState = distrGen
2023-10-02 20:10:22 +00:00
appCodec := tApp . AppCodec ( )
suite . App . InitializeFromGenesisStates (
app . GenesisState { minttypes . ModuleName : appCodec . MustMarshalJSON ( mintGen ) } ,
app . GenesisState { kavadisttypes . ModuleName : appCodec . MustMarshalJSON ( kavadistGen ) } ,
2023-10-23 19:15:44 +00:00
app . GenesisState { distrtypes . ModuleName : appCodec . MustMarshalJSON ( distrGen ) } ,
2023-10-02 20:10:22 +00:00
)
}
func ( suite * disableInflationTestSuite ) TestDisableInflation ( ) {
2023-10-03 15:41:54 +00:00
validateState := func ( upgraded bool , expectedDisableTime time . Time , originalStakingRewards sdkmath . LegacyDec , setStakingRewards sdkmath . LegacyDec , msg string ) {
2023-10-02 20:10:22 +00:00
params , found := suite . Keeper . GetParams ( suite . Ctx )
suite . Require ( ) . True ( found )
mintParams := suite . App . GetMintKeeper ( ) . GetParams ( suite . Ctx )
kavadistParams := suite . App . GetKavadistKeeper ( ) . GetParams ( suite . Ctx )
2023-10-23 19:15:44 +00:00
distrParams := suite . App . GetDistrKeeper ( ) . GetParams ( suite . Ctx )
2023-10-02 20:10:22 +00:00
disableTimeMsg := "expected inflation disable time to match"
expectedMintState := suite . genesisMintState
expectedKavadistState := suite . genesisKavadistState
2023-10-23 19:15:44 +00:00
expectedDistrState := suite . genesisDistrState
2023-10-03 15:41:54 +00:00
expectedStakingRewards := originalStakingRewards
2023-10-02 20:10:22 +00:00
msgSuffix := "before upgrade"
// The state expected after upgrade time is reached
if upgraded {
// Disable upgrade time is reset when run.
//
// This allows the time to be set and run again if required.
// In addition, with zero time not upgrading, achieves idempotence
// without extra logic or state.
expectedDisableTime = time . Time { }
disableTimeMsg = "expected inflation disable time to be reset"
2023-10-03 15:41:54 +00:00
expectedStakingRewards = setStakingRewards
2023-10-02 20:10:22 +00:00
expectedMintState . Params . InflationMin = sdk . ZeroDec ( )
expectedMintState . Params . InflationMax = sdk . ZeroDec ( )
expectedKavadistState . Params . Active = false
2023-10-23 19:15:44 +00:00
expectedDistrState . Params . CommunityTax = sdk . ZeroDec ( )
2023-10-02 20:10:22 +00:00
msgSuffix = "after upgrade"
2023-10-03 22:10:22 +00:00
suite . Require ( ) . NoError ( app . EventsContains ( suite . Ctx . EventManager ( ) . Events ( ) , sdk . NewEvent ( types . EventTypeInflationStop ) ) )
2023-10-02 20:10:22 +00:00
}
suite . Require ( ) . Equal ( expectedMintState . Params . InflationMin , mintParams . InflationMin , msg + ": expected mint inflation min to match state " + msgSuffix )
suite . Require ( ) . Equal ( expectedMintState . Params . InflationMax , mintParams . InflationMax , msg + ": expected mint inflation max to match state " + msgSuffix )
suite . Require ( ) . Equal ( expectedKavadistState . Params . Active , kavadistParams . Active , msg + ":expected kavadist active flag match state " + msgSuffix )
2023-10-23 19:15:44 +00:00
suite . Require ( ) . Equal ( expectedDistrState . Params . CommunityTax , distrParams . CommunityTax , msg + ":expected x/distribution community tax to match state " + msgSuffix )
2023-10-02 20:10:22 +00:00
suite . Require ( ) . Equal ( expectedDisableTime , params . UpgradeTimeDisableInflation , msg + ": " + disableTimeMsg )
2023-10-03 15:41:54 +00:00
// we always check staking rewards per second matches the passed in expectation
suite . Require ( ) . Equal ( expectedStakingRewards , params . StakingRewardsPerSecond , msg + ": " + "staking rewards per second to match " + msgSuffix )
// we don't modify or zero out the initial rewards per second for upgrade time
suite . Require ( ) . Equal ( setStakingRewards , params . UpgradeTimeSetStakingRewardsPerSecond , msg + ": " + "set staking rewards per second to match " + msgSuffix )
2023-10-02 20:10:22 +00:00
}
blockTime := suite . Ctx . BlockTime ( )
testCases := [ ] struct {
2023-10-03 15:41:54 +00:00
name string
upgradeTime time . Time
setStakingRewards sdkmath . LegacyDec
shouldUpgrade bool
2023-10-02 20:10:22 +00:00
} {
2023-10-03 15:41:54 +00:00
{ "zero upgrade time -- should not upgrade" , time . Time { } , sdkmath . LegacyNewDec ( 1001 ) , false } ,
{ "upgrade time in future -- should not upgrade" , blockTime . Add ( 1 * time . Second ) , sdkmath . LegacyNewDec ( 1002 ) , false } ,
{ "upgrade time in past -- should upgrade" , blockTime . Add ( - 1 * time . Second ) , sdkmath . LegacyNewDec ( 1003 ) , true } ,
{ "upgrade time equal to block time -- should upgrade" , blockTime , sdkmath . LegacyNewDec ( 1004 ) , true } ,
2023-10-02 20:10:22 +00:00
}
for _ , tc := range testCases {
suite . Run ( tc . name , func ( ) {
suite . SetupTest ( )
2023-10-03 15:41:54 +00:00
params , found := suite . Keeper . GetParams ( suite . Ctx )
suite . Require ( ) . True ( found )
// these should not match in order to assure assertions test correct behavior
suite . Require ( ) . NotEqual ( params . StakingRewardsPerSecond , tc . setStakingRewards , "set staking rewards can not match initial staking rewards" )
2023-10-02 20:10:22 +00:00
// ensure state is as we expect before running upgrade or updating time
2023-10-03 15:41:54 +00:00
validateState ( false , time . Time { } , params . StakingRewardsPerSecond , params . UpgradeTimeSetStakingRewardsPerSecond , "initial state" )
2023-10-02 20:10:22 +00:00
// set inflation disable time
params . UpgradeTimeDisableInflation = tc . upgradeTime
2023-10-03 15:41:54 +00:00
// set upgrade time set staking rewards per second
params . UpgradeTimeSetStakingRewardsPerSecond = tc . setStakingRewards
2023-10-02 20:10:22 +00:00
suite . Keeper . SetParams ( suite . Ctx , params )
// run test function
suite . testFunc ( suite . Ctx , suite . Keeper )
// run assertions to ensure upgrade did or did not run
2023-10-03 15:41:54 +00:00
validateState ( tc . shouldUpgrade , tc . upgradeTime , params . StakingRewardsPerSecond , tc . setStakingRewards , "first begin blocker run" )
2023-10-02 20:10:22 +00:00
// test idempotence only if upgrade should have been ran
if tc . shouldUpgrade {
// reset mint and kavadist state to their initial values
suite . App . GetMintKeeper ( ) . SetParams ( suite . Ctx , suite . genesisMintState . Params )
suite . App . GetKavadistKeeper ( ) . SetParams ( suite . Ctx , suite . genesisKavadistState . Params )
2023-10-03 15:41:54 +00:00
// modify staking rewards per second to ensure they are not overridden again
params , found := suite . Keeper . GetParams ( suite . Ctx )
suite . Require ( ) . True ( found )
params . StakingRewardsPerSecond = params . StakingRewardsPerSecond . Add ( sdkmath . LegacyOneDec ( ) )
suite . Keeper . SetParams ( suite . Ctx , params )
2023-10-02 20:10:22 +00:00
// run begin blocker again
community . BeginBlocker ( suite . Ctx , suite . Keeper )
2023-10-03 15:41:54 +00:00
// ensure begin blocker is idempotent and never runs twice
validateState ( false , time . Time { } , params . StakingRewardsPerSecond , tc . setStakingRewards , "second begin blocker run" )
2023-10-02 20:10:22 +00:00
}
} )
}
}
func ( suite * disableInflationTestSuite ) TestPanicsOnMissingParameters ( ) {
suite . SetupTest ( )
store := suite . Ctx . KVStore ( suite . App . GetKVStoreKey ( types . StoreKey ) )
store . Delete ( types . ParamsKey )
suite . PanicsWithValue ( "invalid state: module parameters not found" , func ( ) {
suite . testFunc ( suite . Ctx , suite . Keeper )
} )
}