diff --git a/app/apptesting/test_suite.go b/app/apptesting/test_suite.go new file mode 100644 index 00000000000..44d96fc2a41 --- /dev/null +++ b/app/apptesting/test_suite.go @@ -0,0 +1,101 @@ +package apptesting + +import ( + "fmt" + "time" + + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + "github.com/cosmos/cosmos-sdk/simapp" + + abci "github.com/tendermint/tendermint/abci/types" + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + + sdk "github.com/cosmos/cosmos-sdk/types" + slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types" + "github.com/cosmos/cosmos-sdk/x/staking/teststaking" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + + "github.com/osmosis-labs/osmosis/v7/app" + "github.com/stretchr/testify/suite" +) + +// TODO: Consider an embedded struct here rather than an interface +type SuiteI interface { + GetSuite() *suite.Suite + GetCtx() sdk.Context + SetCtx(sdk.Context) + GetApp() *app.OsmosisApp +} + +func SetupValidator(suite SuiteI, bondStatus stakingtypes.BondStatus) sdk.ValAddress { + valPub := secp256k1.GenPrivKey().PubKey() + valAddr := sdk.ValAddress(valPub.Address()) + bondDenom := suite.GetApp().StakingKeeper.GetParams(suite.GetCtx()).BondDenom + selfBond := sdk.NewCoins(sdk.Coin{Amount: sdk.NewInt(100), Denom: bondDenom}) + + err := simapp.FundAccount(suite.GetApp().BankKeeper, suite.GetCtx(), sdk.AccAddress(valAddr), selfBond) + suite.GetSuite().Require().NoError(err) + sh := teststaking.NewHelper(suite.GetSuite().T(), suite.GetCtx(), *suite.GetApp().StakingKeeper) + msg := sh.CreateValidatorMsg(valAddr, valPub, selfBond[0].Amount) + sh.Handle(msg, true) + val, found := suite.GetApp().StakingKeeper.GetValidator(suite.GetCtx(), valAddr) + suite.GetSuite().Require().True(found) + val = val.UpdateStatus(bondStatus) + suite.GetApp().StakingKeeper.SetValidator(suite.GetCtx(), val) + + consAddr, err := val.GetConsAddr() + suite.GetSuite().Require().NoError(err) + signingInfo := slashingtypes.NewValidatorSigningInfo( + consAddr, + suite.GetCtx().BlockHeight(), + 0, + time.Unix(0, 0), + false, + 0, + ) + suite.GetApp().SlashingKeeper.SetValidatorSigningInfo(suite.GetCtx(), consAddr, signingInfo) + + return valAddr +} + +func BeginNewBlock(suite SuiteI, executeNextEpoch bool) { + valAddr := []byte(":^) at this distribution workaround") + validators := suite.GetApp().StakingKeeper.GetAllValidators(suite.GetCtx()) + if len(validators) >= 1 { + valAddrFancy, err := validators[0].GetConsAddr() + suite.GetSuite().Require().NoError(err) + valAddr = valAddrFancy.Bytes() + } else { + valAddrFancy := SetupValidator(suite, stakingtypes.Bonded) + validator, _ := suite.GetApp().StakingKeeper.GetValidator(suite.GetCtx(), valAddrFancy) + valAddr2, _ := validator.GetConsAddr() + valAddr = valAddr2.Bytes() + } + + epochIdentifier := suite.GetApp().SuperfluidKeeper.GetEpochIdentifier(suite.GetCtx()) + epoch := suite.GetApp().EpochsKeeper.GetEpochInfo(suite.GetCtx(), epochIdentifier) + newBlockTime := suite.GetCtx().BlockTime().Add(5 * time.Second) + if executeNextEpoch { + endEpochTime := epoch.CurrentEpochStartTime.Add(epoch.Duration) + newBlockTime = endEpochTime.Add(time.Second) + } + // fmt.Println(executeNextEpoch, suite.ctx.BlockTime(), newBlockTime) + header := tmproto.Header{Height: suite.GetCtx().BlockHeight() + 1, Time: newBlockTime} + newCtx := suite.GetCtx().WithBlockTime(newBlockTime).WithBlockHeight(suite.GetCtx().BlockHeight() + 1) + suite.SetCtx(newCtx) + lastCommitInfo := abci.LastCommitInfo{ + Votes: []abci.VoteInfo{{ + Validator: abci.Validator{Address: valAddr, Power: 1000}, + SignedLastBlock: true}, + }, + } + reqBeginBlock := abci.RequestBeginBlock{Header: header, LastCommitInfo: lastCommitInfo} + + fmt.Println("beginning block ", suite.GetCtx().BlockHeight()) + suite.GetApp().BeginBlocker(suite.GetCtx(), reqBeginBlock) +} + +func EndBlock(suite SuiteI) { + reqEndBlock := abci.RequestEndBlock{Height: suite.GetCtx().BlockHeight()} + suite.GetApp().EndBlocker(suite.GetCtx(), reqEndBlock) +} diff --git a/x/superfluid/keeper/hooks_test.go b/x/superfluid/keeper/hooks_test.go index 7bfae037ab0..bcfa9048d59 100644 --- a/x/superfluid/keeper/hooks_test.go +++ b/x/superfluid/keeper/hooks_test.go @@ -4,6 +4,7 @@ import ( "github.com/cosmos/cosmos-sdk/simapp" sdk "github.com/cosmos/cosmos-sdk/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + "github.com/osmosis-labs/osmosis/v7/app/apptesting" "github.com/tendermint/tendermint/crypto/ed25519" ) @@ -44,7 +45,7 @@ func (suite *KeeperTestSuite) TestSuperfluidAfterEpochEnd() { suite.Require().NoError(err) // run epoch actions - suite.BeginNewBlock(true) + apptesting.BeginNewBlock(suite, true) // check lptoken twap value set newEpochTwap := suite.app.SuperfluidKeeper.GetOsmoEquivalentMultiplier(suite.ctx, "gamm/pool/1") @@ -58,6 +59,7 @@ func (suite *KeeperTestSuite) TestSuperfluidAfterEpochEnd() { suite.Require().True(found) suite.Require().Equal(sdk.NewDec(5000), delegation.Shares) // TODO: Check reward distribution + // suite.Require().NotEqual(sdk.Coins{}, ) } }) } diff --git a/x/superfluid/keeper/keeper_test.go b/x/superfluid/keeper/keeper_test.go index decd800616a..c30d6623dd0 100644 --- a/x/superfluid/keeper/keeper_test.go +++ b/x/superfluid/keeper/keeper_test.go @@ -7,22 +7,22 @@ import ( "github.com/cosmos/cosmos-sdk/baseapp" "github.com/cosmos/cosmos-sdk/simapp" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/staking/teststaking" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" "github.com/osmosis-labs/osmosis/v7/app" + "github.com/osmosis-labs/osmosis/v7/app/apptesting" "github.com/osmosis-labs/osmosis/v7/x/superfluid/types" "github.com/stretchr/testify/suite" - abci "github.com/tendermint/tendermint/abci/types" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" "github.com/osmosis-labs/osmosis/v7/x/gamm/pool-models/balancer" - gammtypes "github.com/osmosis-labs/osmosis/v7/x/gamm/types" "github.com/tendermint/tendermint/crypto/ed25519" lockupkeeper "github.com/osmosis-labs/osmosis/v7/x/lockup/keeper" - lockuptypes "github.com/osmosis-labs/osmosis/v7/x/lockup/types" - "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + epochtypes "github.com/osmosis-labs/osmosis/v7/x/epochs/types" + gammtypes "github.com/osmosis-labs/osmosis/v7/x/gamm/types" + lockuptypes "github.com/osmosis-labs/osmosis/v7/x/lockup/types" + minttypes "github.com/osmosis-labs/osmosis/v7/x/mint/types" ) type KeeperTestSuite struct { @@ -33,6 +33,19 @@ type KeeperTestSuite struct { app *app.OsmosisApp } +func (suite *KeeperTestSuite) GetSuite() *suite.Suite { + return &suite.Suite +} +func (suite *KeeperTestSuite) GetCtx() sdk.Context { + return suite.ctx +} +func (suite *KeeperTestSuite) GetApp() *app.OsmosisApp { + return suite.app +} +func (suite *KeeperTestSuite) SetCtx(ctx sdk.Context) { + suite.ctx = ctx +} + func (suite *KeeperTestSuite) SetupTest() { suite.app = app.Setup(false) @@ -53,6 +66,35 @@ func (suite *KeeperTestSuite) SetupTest() { time.Hour * 7, unbondingDuration, }) + + // TODO: Revisit if this is needed, it was added due to another bug in testing that is now fixed. + epochIdentifier := suite.app.SuperfluidKeeper.GetEpochIdentifier(suite.ctx) + suite.app.EpochsKeeper.SetEpochInfo(suite.ctx, epochtypes.EpochInfo{ + Identifier: epochIdentifier, + StartTime: startTime, + Duration: time.Hour, + CurrentEpochStartTime: startTime, + CurrentEpochStartHeight: 1, + CurrentEpoch: 1, + EpochCountingStarted: true, + }) + + mintParams := suite.app.MintKeeper.GetParams(suite.ctx) + mintParams.EpochIdentifier = epochIdentifier + mintParams.DistributionProportions = minttypes.DistributionProportions{ + Staking: sdk.OneDec(), + PoolIncentives: sdk.ZeroDec(), + DeveloperRewards: sdk.ZeroDec(), + CommunityPool: sdk.ZeroDec(), + } + suite.app.MintKeeper.SetParams(suite.ctx, mintParams) + suite.app.MintKeeper.SetMinter(suite.ctx, minttypes.NewMinter(sdk.NewDec(1_000_000))) + + distributionParams := suite.app.DistrKeeper.GetParams(suite.ctx) + distributionParams.BaseProposerReward = sdk.ZeroDec() + distributionParams.BonusProposerReward = sdk.ZeroDec() + distributionParams.CommunityTax = sdk.ZeroDec() + suite.app.DistrKeeper.SetParams(suite.ctx, distributionParams) } func (suite *KeeperTestSuite) SetupDefaultPool() { @@ -61,25 +103,6 @@ func (suite *KeeperTestSuite) SetupDefaultPool() { suite.Require().Equal(poolId, uint64(1)) } -func (suite *KeeperTestSuite) BeginNewBlock(executeNextEpoch bool) { - epochIdentifier := suite.app.SuperfluidKeeper.GetEpochIdentifier(suite.ctx) - epoch := suite.app.EpochsKeeper.GetEpochInfo(suite.ctx, epochIdentifier) - newBlockTime := suite.ctx.BlockTime().Add(5 * time.Second) - if executeNextEpoch { - endEpochTime := epoch.CurrentEpochStartTime.Add(epoch.Duration) - newBlockTime = endEpochTime.Add(time.Second) - } - header := tmproto.Header{Height: suite.ctx.BlockHeight() + 1, Time: newBlockTime} - reqBeginBlock := abci.RequestBeginBlock{Header: header} - suite.app.BeginBlocker(suite.ctx, reqBeginBlock) - -} - -func (suite *KeeperTestSuite) EndBlock() { - reqEndBlock := abci.RequestEndBlock{Height: suite.ctx.BlockHeight()} - suite.app.EndBlocker(suite.ctx, reqEndBlock) -} - // CreateRandomAccounts is a function return a list of randomly generated AccAddresses func CreateRandomAccounts(numAccts int) []sdk.AccAddress { testAddrs := make([]sdk.AccAddress, numAccts) @@ -125,28 +148,10 @@ func (suite *KeeperTestSuite) LockTokens(addr sdk.AccAddress, coins sdk.Coins, d return msgResponse.ID } -func (suite *KeeperTestSuite) SetupValidator(bondStatus stakingtypes.BondStatus) sdk.ValAddress { - valPub := secp256k1.GenPrivKey().PubKey() - valAddr := sdk.ValAddress(valPub.Address()) - bondDenom := suite.app.StakingKeeper.GetParams(suite.ctx).BondDenom - selfBond := sdk.NewCoins(sdk.Coin{Amount: sdk.NewInt(100), Denom: bondDenom}) - - simapp.FundAccount(suite.app.BankKeeper, suite.ctx, sdk.AccAddress(valAddr), selfBond) - sh := teststaking.NewHelper(suite.T(), suite.ctx, *suite.app.StakingKeeper) - msg := sh.CreateValidatorMsg(valAddr, valPub, selfBond[0].Amount) - sh.Handle(msg, true) - val, found := suite.app.StakingKeeper.GetValidator(suite.ctx, valAddr) - suite.Require().True(found) - val = val.UpdateStatus(bondStatus) - suite.app.StakingKeeper.SetValidator(suite.ctx, val) - - return valAddr -} - func (suite *KeeperTestSuite) SetupValidators(bondStatuses []stakingtypes.BondStatus) []sdk.ValAddress { valAddrs := []sdk.ValAddress{} for _, status := range bondStatuses { - valAddr := suite.SetupValidator(status) + valAddr := apptesting.SetupValidator(suite, status) valAddrs = append(valAddrs, valAddr) } return valAddrs