stake_test.go 28.33 KiB
package keeper_test
import (
	"time"
	abci "github.com/tendermint/tendermint/abci/types"
	lockuptypes "github.com/osmosis-labs/osmosis/v10/x/lockup/types"
	"github.com/osmosis-labs/osmosis/v10/x/superfluid/keeper"
	"github.com/osmosis-labs/osmosis/v10/x/superfluid/types"
	sdk "github.com/cosmos/cosmos-sdk/types"
	stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
type superfluidDelegation struct {
	delIndex int64
	valIndex int64
	lpIndex  int64
	lpAmount int64
func (suite *KeeperTestSuite) TestSuperfluidDelegate() {
	testCases := []struct {
		name               string
		validatorStats     []stakingtypes.BondStatus
		superDelegations   []superfluidDelegation
		expInterDelegation []sdk.Dec
			"with single validator and single superfluid delegation",
			[]stakingtypes.BondStatus{stakingtypes.Bonded},
			[]superfluidDelegation{{0, 0, 0, 1000000}},
			[]sdk.Dec{sdk.NewDec(10000000)}, // 50% x 20 x 1000000
			"with single validator and additional superfluid delegations",
			[]stakingtypes.BondStatus{stakingtypes.Bonded},
			[]superfluidDelegation{{0, 0, 0, 1000000}, {0, 0, 0, 1000000}},
			[]sdk.Dec{sdk.NewDec(20000000)}, // 50% x 20 x 1000000 x 2
			"with multiple validators and multiple superfluid delegations",
			[]stakingtypes.BondStatus{stakingtypes.Bonded, stakingtypes.Bonded},
			[]superfluidDelegation{{0, 0, 0, 1000000}, {1, 1, 0, 1000000}},
			[]sdk.Dec{sdk.NewDec(10000000), sdk.NewDec(10000000)}, // 50% x 20 x 1000000
	for _, tc := range testCases {
		tc := tc
		suite.Run(tc.name, func() {
			suite.SetupTest()
			bondDenom := suite.App.StakingKeeper.BondDenom(suite.Ctx)
			// setup validators
			valAddrs := suite.SetupValidators(tc.validatorStats)
			denoms, _ := suite.SetupGammPoolsAndSuperfluidAssets([]sdk.Dec{sdk.NewDec(20), sdk.NewDec(20)})
			// get pre-superfluid delgations osmo supply and supplyWithOffset
			presupply := suite.App.BankKeeper.GetSupply(suite.Ctx, bondDenom)
			presupplyWithOffset := suite.App.BankKeeper.GetSupplyWithOffset(suite.Ctx, bondDenom)
			// setup superfluid delegations
			_, intermediaryAccs, locks := suite.setupSuperfluidDelegations(valAddrs, tc.superDelegations, denoms)
			// ensure post-superfluid delegations osmo supplywithoffset is the same while supply is not
			postsupply := suite.App.BankKeeper.GetSupply(suite.Ctx, bondDenom)
			postsupplyWithOffset := suite.App.BankKeeper.GetSupplyWithOffset(suite.Ctx, bondDenom)
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
suite.Require().False(postsupply.IsEqual(presupply), "presupply: %s postsupply: %s", presupply, postsupply) suite.Require().Equal(postsupplyWithOffset.String(), presupplyWithOffset.String()) unbondingDuration := suite.App.StakingKeeper.GetParams(suite.Ctx).UnbondingTime for index, del := range tc.superDelegations { lock := locks[index] valAddr := valAddrs[del.valIndex] // check synthetic lockup creation synthLock, err := suite.App.LockupKeeper.GetSyntheticLockup(suite.Ctx, lock.ID, keeper.StakingSyntheticDenom(lock.Coins[0].Denom, valAddr.String())) suite.Require().NoError(err) suite.Require().Equal(synthLock.UnderlyingLockId, lock.ID) suite.Require().Equal(synthLock.SynthDenom, keeper.StakingSyntheticDenom(lock.Coins[0].Denom, valAddr.String())) suite.Require().Equal(synthLock.EndTime, time.Time{}) expAcc := types.NewSuperfluidIntermediaryAccount(lock.Coins[0].Denom, valAddr.String(), 0) // Check lockID connection with intermediary account intAcc := suite.App.SuperfluidKeeper.GetLockIdIntermediaryAccountConnection(suite.Ctx, lock.ID) suite.Require().Equal(intAcc.String(), expAcc.GetAccAddress().String()) } for index, expAcc := range intermediaryAccs { // check intermediary account creation gotAcc := suite.App.SuperfluidKeeper.GetIntermediaryAccount(suite.Ctx, expAcc.GetAccAddress()) suite.Require().Equal(gotAcc.Denom, expAcc.Denom) suite.Require().Equal(gotAcc.ValAddr, expAcc.ValAddr) suite.Require().GreaterOrEqual(gotAcc.GaugeId, uint64(1)) valAddr, err := sdk.ValAddressFromBech32(expAcc.ValAddr) suite.Require().NoError(err) // check gauge creation gauge, err := suite.App.IncentivesKeeper.GetGaugeByID(suite.Ctx, gotAcc.GaugeId) suite.Require().NoError(err) suite.Require().Equal(gauge.Id, gotAcc.GaugeId) suite.Require().Equal(gauge.IsPerpetual, true) suite.Require().Equal(gauge.DistributeTo, lockuptypes.QueryCondition{ LockQueryType: lockuptypes.ByDuration, Denom: keeper.StakingSyntheticDenom(expAcc.Denom, valAddr.String()), Duration: unbondingDuration, }) suite.Require().Equal(gauge.Coins, sdk.Coins(nil)) suite.Require().Equal(gauge.StartTime, suite.Ctx.BlockTime()) suite.Require().Equal(gauge.NumEpochsPaidOver, uint64(1)) suite.Require().Equal(gauge.FilledEpochs, uint64(0)) suite.Require().Equal(gauge.DistributedCoins, sdk.Coins(nil)) // check delegation from intermediary account to validator delegation, found := suite.App.StakingKeeper.GetDelegation(suite.Ctx, expAcc.GetAccAddress(), valAddr) suite.Require().True(found) suite.Require().Equal(tc.expInterDelegation[index], delegation.Shares) } // check invariant is fine reason, broken := keeper.AllInvariants(*suite.App.SuperfluidKeeper)(suite.Ctx) suite.Require().False(broken, reason) // try delegating twice with same lockup for _, lock := range locks { err := suite.App.SuperfluidKeeper.SuperfluidDelegate(suite.Ctx, lock.Owner, lock.ID, valAddrs[0].String()) suite.Require().Error(err) } }) } } func (suite *KeeperTestSuite) TestSuperfluidUndelegate() { testCases := []struct {