Skip to content

Commit

Permalink
Eugen/cherry pick superfluid test scaffolding updates (osmosis-labs#1052
Browse files Browse the repository at this point in the history
)

* add utility for SetupGammPoolsAndSuperfluidAssets

* remove hardcoded gamm pool denoms

* fix for main branch ctx => Ctx, app => App in tests

* Update x/superfluid/keeper/stake_test.go

Co-authored-by: Matt, Park <[email protected]>

Co-authored-by: Matt, Park <[email protected]>
  • Loading branch information
antstalepresh and mattverse authored Mar 8, 2022
1 parent d7c165c commit f375c5a
Show file tree
Hide file tree
Showing 7 changed files with 184 additions and 113 deletions.
35 changes: 19 additions & 16 deletions x/superfluid/keeper/distribution_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@ func (suite *KeeperTestSuite) allocateRewardsToValidator(valAddr sdk.ValAddress)

func (suite *KeeperTestSuite) TestMoveSuperfluidDelegationRewardToGauges() {
type gaugeChecker struct {
gaugeId uint64
valIndex int64
lpDenom string
rewarded bool
intermediaryAccIndex uint64
valIndex int64
lpIndex int64
rewarded bool
}
testCases := []struct {
name string
Expand All @@ -44,33 +44,33 @@ func (suite *KeeperTestSuite) TestMoveSuperfluidDelegationRewardToGauges() {
"happy path with single validator and delegator",
[]stakingtypes.BondStatus{stakingtypes.Bonded},
1,
[]superfluidDelegation{{0, 0, "gamm/pool/1", 1000000}},
[]superfluidDelegation{{0, 0, 0, 1000000}},
[]int64{0},
[]gaugeChecker{{4, 0, "gamm/pool/1", true}},
[]gaugeChecker{{0, 0, 0, true}},
},
{
"two LP tokens delegation to a single validator",
[]stakingtypes.BondStatus{stakingtypes.Bonded},
2,
[]superfluidDelegation{{0, 0, "gamm/pool/1", 1000000}, {0, 0, "gamm/pool/2", 1000000}},
[]superfluidDelegation{{0, 0, 0, 1000000}, {0, 0, 1, 1000000}},
[]int64{0},
[]gaugeChecker{{4, 0, "gamm/pool/1", true}, {5, 0, "gamm/pool/2", true}},
[]gaugeChecker{{0, 0, 0, true}, {1, 0, 1, true}},
},
{
"one LP token with two locks to a single validator",
[]stakingtypes.BondStatus{stakingtypes.Bonded},
2,
[]superfluidDelegation{{0, 0, "gamm/pool/1", 1000000}, {1, 0, "gamm/pool/1", 1000000}},
[]superfluidDelegation{{0, 0, 0, 1000000}, {1, 0, 0, 1000000}},
[]int64{0},
[]gaugeChecker{{4, 0, "gamm/pool/1", true}},
[]gaugeChecker{{0, 0, 0, true}},
},
{
"add unbonded validator case",
[]stakingtypes.BondStatus{stakingtypes.Bonded, stakingtypes.Unbonded},
2,
[]superfluidDelegation{{0, 0, "gamm/pool/1", 1000000}, {1, 1, "gamm/pool/1", 1000000}},
[]superfluidDelegation{{0, 0, 0, 1000000}, {1, 1, 0, 1000000}},
[]int64{0},
[]gaugeChecker{{4, 0, "gamm/pool/1", true}, {5, 1, "gamm/pool/1", false}},
[]gaugeChecker{{0, 0, 0, true}, {1, 1, 0, false}},
},
}

Expand All @@ -86,8 +86,10 @@ func (suite *KeeperTestSuite) TestMoveSuperfluidDelegationRewardToGauges() {
// setup validators
valAddrs := suite.SetupValidators(tc.validatorStats)

denoms, _ := suite.SetupGammPoolsAndSuperfluidAssets([]sdk.Dec{sdk.NewDec(20), sdk.NewDec(20)})

// setup superfluid delegations
suite.SetupSuperfluidDelegations(delAddrs, valAddrs, tc.superDelegations)
intermediaryAccs, _ := suite.SetupSuperfluidDelegations(delAddrs, valAddrs, tc.superDelegations, denoms)
unbondingDuration := suite.App.StakingKeeper.GetParams(suite.Ctx).UnbondingTime

// allocate rewards to first validator
Expand All @@ -100,13 +102,14 @@ func (suite *KeeperTestSuite) TestMoveSuperfluidDelegationRewardToGauges() {

// check gauge balance
for _, gaugeCheck := range tc.gaugeChecks {
gauge, err := suite.App.IncentivesKeeper.GetGaugeByID(suite.Ctx, gaugeCheck.gaugeId)
gaugeId := intermediaryAccs[gaugeCheck.intermediaryAccIndex].GaugeId
gauge, err := suite.App.IncentivesKeeper.GetGaugeByID(suite.Ctx, gaugeId)
suite.Require().NoError(err)
suite.Require().Equal(gauge.Id, gaugeCheck.gaugeId)
suite.Require().Equal(gauge.Id, gaugeId)
suite.Require().Equal(gauge.IsPerpetual, true)
suite.Require().Equal(lockuptypes.QueryCondition{
LockQueryType: lockuptypes.ByDuration,
Denom: keeper.StakingSyntheticDenom(gaugeCheck.lpDenom, valAddrs[gaugeCheck.valIndex].String()),
Denom: keeper.StakingSyntheticDenom(denoms[gaugeCheck.lpIndex], valAddrs[gaugeCheck.valIndex].String()),
Duration: unbondingDuration,
}, gauge.DistributeTo)
if gaugeCheck.rewarded {
Expand Down
42 changes: 18 additions & 24 deletions x/superfluid/keeper/grpc_query_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,31 +47,29 @@ func (suite *KeeperTestSuite) TestGRPCQuerySuperfluidDelegations() {
// setup 2 validators
valAddrs := suite.SetupValidators([]stakingtypes.BondStatus{stakingtypes.Bonded, stakingtypes.Bonded})

denoms := []string{"gamm/pool/1", "gamm/pool/2"}
denoms, _ := suite.SetupGammPoolsAndSuperfluidAssets([]sdk.Dec{sdk.NewDec(20), sdk.NewDec(20)})

// create a delegation of 1000000 for every combination of 2 delegations, 2 validators, and 2 superfluid denoms
superfluidDelegations := []superfluidDelegation{
{0, 0, denoms[0], 1000000},

{0, 1, denoms[1], 1000000},

{1, 0, denoms[1], 1000000},

{1, 1, denoms[0], 1000000},
{0, 0, 0, 1000000},
{0, 1, 1, 1000000},
{1, 0, 1, 1000000},
{1, 1, 0, 1000000},
}

// setup superfluid delegations
suite.SetupSuperfluidDelegations(delAddrs, valAddrs, superfluidDelegations)
suite.SetupSuperfluidDelegations(delAddrs, valAddrs, superfluidDelegations, denoms)

// for each superfluid delegation, query the amount and make sure it is 1000000
for _, delegation := range superfluidDelegations {
lpDenom := denoms[delegation.lpIndex]
res, err := suite.queryClient.SuperfluidDelegationAmount(sdk.WrapSDKContext(suite.Ctx), &types.SuperfluidDelegationAmountRequest{
DelegatorAddress: delAddrs[delegation.delIndex].String(),
ValidatorAddress: valAddrs[delegation.valIndex].String(),
Denom: delegation.lpDenom,
Denom: lpDenom,
})
suite.Require().NoError(err)
suite.Require().Equal(res.Amount.AmountOf(delegation.lpDenom).Int64(), delegation.lpAmount)
suite.Require().Equal(res.Amount.AmountOf(lpDenom).Int64(), delegation.lpAmount)
}

// for each delegator, query all their superfluid delegations and make sure they have 2 delegations
Expand All @@ -82,8 +80,8 @@ func (suite *KeeperTestSuite) TestGRPCQuerySuperfluidDelegations() {
suite.Require().NoError(err)
suite.Require().Len(res.SuperfluidDelegationRecords, 2)
suite.Require().True(res.TotalDelegatedCoins.IsEqual(sdk.NewCoins(
sdk.NewInt64Coin("gamm/pool/1", 1000000),
sdk.NewInt64Coin("gamm/pool/2", 1000000),
sdk.NewInt64Coin(denoms[0], 1000000),
sdk.NewInt64Coin(denoms[1], 1000000),
)))
}

Expand All @@ -110,7 +108,6 @@ func (suite *KeeperTestSuite) TestGRPCQuerySuperfluidDelegations() {
totalSuperfluidDelegationsRes, err := suite.queryClient.TotalSuperfluidDelegations(sdk.WrapSDKContext(suite.Ctx), &types.TotalSuperfluidDelegationsRequest{})
suite.Require().NoError(err)
suite.Require().Equal(sdk.NewInt(40000000), totalSuperfluidDelegationsRes.TotalDelegations)

}

func (suite *KeeperTestSuite) TestGRPCQuerySuperfluidDelegationsDontIncludeUnbonding() {
Expand All @@ -122,21 +119,18 @@ func (suite *KeeperTestSuite) TestGRPCQuerySuperfluidDelegationsDontIncludeUnbon
// setup 2 validators
valAddrs := suite.SetupValidators([]stakingtypes.BondStatus{stakingtypes.Bonded, stakingtypes.Bonded})

denoms := []string{"gamm/pool/1", "gamm/pool/2"}
denoms, _ := suite.SetupGammPoolsAndSuperfluidAssets([]sdk.Dec{sdk.NewDec(20), sdk.NewDec(20)})

// create a delegation of 1000000 for every combination of 2 delegations, 2 validators, and 2 superfluid denoms
superfluidDelegations := []superfluidDelegation{
{0, 0, denoms[0], 1000000},

{0, 1, denoms[1], 1000000},

{1, 0, denoms[1], 1000000},

{1, 1, denoms[0], 1000000},
{0, 0, 0, 1000000},
{0, 1, 1, 1000000},
{1, 0, 1, 1000000},
{1, 1, 0, 1000000},
}

// setup superfluid delegations
_, locks := suite.SetupSuperfluidDelegations(delAddrs, valAddrs, superfluidDelegations)
_, locks := suite.SetupSuperfluidDelegations(delAddrs, valAddrs, superfluidDelegations, denoms)

// start unbonding the superfluid delegations of denom0 from delegator0 to validator0
err := suite.App.SuperfluidKeeper.SuperfluidUndelegate(suite.Ctx, locks[0].Owner, locks[0].ID)
Expand All @@ -158,7 +152,7 @@ func (suite *KeeperTestSuite) TestGRPCQuerySuperfluidDelegationsDontIncludeUnbon
suite.Require().NoError(err)
suite.Require().Len(res2.SuperfluidDelegationRecords, 1)
suite.Require().Equal(sdk.NewCoins(
sdk.NewInt64Coin("gamm/pool/2", 1000000)), res2.TotalDelegatedCoins)
sdk.NewInt64Coin(denoms[1], 1000000)), res2.TotalDelegatedCoins)

// query to make sure that the unbonding delegation is not included in the validator denom pair query
amountRes, err := suite.queryClient.EstimateSuperfluidDelegatedAmountByValidatorDenom(sdk.WrapSDKContext(suite.Ctx), &types.EstimateSuperfluidDelegatedAmountByValidatorDenomRequest{
Expand Down
57 changes: 33 additions & 24 deletions x/superfluid/keeper/hooks_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ func (suite *KeeperTestSuite) TestSuperfluidAfterEpochEnd() {
{
"happy path with single validator and delegator",
[]stakingtypes.BondStatus{stakingtypes.Bonded},
[]superfluidDelegation{{0, 0, "gamm/pool/1", 1000000}},
[]superfluidDelegation{{0, 0, 0, 1000000}},
sdk.Coins{},
},
}
Expand All @@ -26,37 +26,43 @@ func (suite *KeeperTestSuite) TestSuperfluidAfterEpochEnd() {
suite.Run(tc.name, func() {
suite.SetupTest()
valAddrs := suite.SetupValidators(tc.validatorStats)
bondDenom := suite.App.StakingKeeper.BondDenom(suite.Ctx)

denoms, poolIds := suite.SetupGammPoolsAndSuperfluidAssets([]sdk.Dec{sdk.NewDec(20), sdk.NewDec(20)})

// Generate delegator addresses
delAddrs := CreateRandomAccounts(1)
intermediaryAccs, _ := suite.SetupSuperfluidDelegations(delAddrs, valAddrs, tc.superDelegations)
intermediaryAccs, _ := suite.SetupSuperfluidDelegations(delAddrs, valAddrs, tc.superDelegations, denoms)
suite.checkIntermediaryAccountDelegations(intermediaryAccs)

// gamm swap operation before refresh
suite.App.SuperfluidKeeper.SetOsmoEquivalentMultiplier(suite.Ctx, 2, "gamm/pool/1", sdk.NewDec(10))
acc1 := sdk.AccAddress(ed25519.GenPrivKey().PubKey().Address().Bytes())
pool, err := suite.App.GAMMKeeper.GetPool(suite.Ctx, poolIds[0])
suite.Require().NoError(err)
poolAssets := pool.GetAllPoolAssets()

coins := sdk.Coins{sdk.NewInt64Coin("foo", 100000000000000)}
err := simapp.FundAccount(suite.App.BankKeeper, suite.Ctx, acc1, coins)
coins := sdk.Coins{sdk.NewInt64Coin(poolAssets[1].Token.Denom, 100000000000000)}
err = simapp.FundAccount(suite.App.BankKeeper, suite.Ctx, acc1, coins)
suite.Require().NoError(err)
_, _, err = suite.App.GAMMKeeper.SwapExactAmountOut(suite.Ctx, acc1, 1, "foo", sdk.NewInt(100000000000000), sdk.NewInt64Coin(bondDenom, 250000000000))
_, _, err = suite.App.GAMMKeeper.SwapExactAmountOut(
suite.Ctx, acc1,
poolIds[0], poolAssets[1].Token.Denom, poolAssets[1].Token.Amount,
sdk.NewCoin(poolAssets[0].Token.Denom, poolAssets[0].Token.Amount.Quo(sdk.NewInt(4))))
suite.Require().NoError(err)

// run epoch actions
suite.BeginNewBlock(true)

// check lptoken twap value set
newEpochTwap := suite.App.SuperfluidKeeper.GetOsmoEquivalentMultiplier(suite.Ctx, "gamm/pool/1")
suite.Require().Equal(newEpochTwap.String(), "0.009999997500000000")
newEpochTwap := suite.App.SuperfluidKeeper.GetOsmoEquivalentMultiplier(suite.Ctx, denoms[0])
suite.Require().Equal(newEpochTwap.String(), "15.000000000000000000")

// check delegation changes
for _, acc := range intermediaryAccs {
valAddr, err := sdk.ValAddressFromBech32(acc.ValAddr)
suite.Require().NoError(err)
delegation, found := suite.App.StakingKeeper.GetDelegation(suite.Ctx, acc.GetAccAddress(), valAddr)
suite.Require().True(found)
suite.Require().Equal(sdk.NewDec(5000), delegation.Shares)
suite.Require().Equal(sdk.NewDec(7500000), delegation.Shares)
// TODO: Check reward distribution
// suite.Require().NotEqual(sdk.Coins{}, )
}
Expand Down Expand Up @@ -136,14 +142,14 @@ func (suite *KeeperTestSuite) TestSuperfluidAfterEpochEnd() {

// for index, lockId := range tc.unbondingLockIds {
// // get intermediary account
// accAddr := suite.app.SuperfluidKeeper.GetLockIdIntermediaryAccountConnection(suite.Ctx, lockId)
// intermediaryAcc := suite.app.SuperfluidKeeper.GetIntermediaryAccount(suite.Ctx, accAddr)
// accAddr := suite.App.SuperfluidKeeper.GetLockIdIntermediaryAccountConnection(suite.Ctx, lockId)
// intermediaryAcc := suite.App.SuperfluidKeeper.GetIntermediaryAccount(suite.Ctx, accAddr)
// valAddr := intermediaryAcc.ValAddr

// // unlock native lockup
// lock, err := suite.app.LockupKeeper.GetLockByID(suite.Ctx, lockId)
// lock, err := suite.App.LockupKeeper.GetLockByID(suite.Ctx, lockId)
// if err == nil {
// err = suite.app.LockupKeeper.BeginUnlock(suite.Ctx, *lock, nil)
// err = suite.App.LockupKeeper.BeginUnlock(suite.Ctx, *lock, nil)
// }

// if tc.expUnbondingErr[index] {
Expand All @@ -153,16 +159,16 @@ func (suite *KeeperTestSuite) TestSuperfluidAfterEpochEnd() {
// suite.Require().NoError(err)

// // check lockId and intermediary account connection deletion
// addr := suite.app.SuperfluidKeeper.GetLockIdIntermediaryAccountConnection(suite.Ctx, lockId)
// addr := suite.App.SuperfluidKeeper.GetLockIdIntermediaryAccountConnection(suite.Ctx, lockId)
// suite.Require().Equal(addr.String(), "")

// // check bonding synthetic lockup deletion
// _, err = suite.app.LockupKeeper.GetSyntheticLockup(suite.Ctx, lockId, keeper.StakingSyntheticDenom(lock.Coins[0].Denom, valAddr))
// _, err = suite.App.LockupKeeper.GetSyntheticLockup(suite.Ctx, lockId, keeper.StakingSyntheticDenom(lock.Coins[0].Denom, valAddr))
// suite.Require().Error(err)

// // check unbonding synthetic lockup creation
// unbondingDuration := suite.app.StakingKeeper.GetParams(suite.Ctx).UnbondingTime
// synthLock, err := suite.app.LockupKeeper.GetSyntheticLockup(suite.Ctx, lockId, keeper.UnstakingSyntheticDenom(lock.Coins[0].Denom, valAddr))
// unbondingDuration := suite.App.StakingKeeper.GetParams(suite.Ctx).UnbondingTime
// synthLock, err := suite.App.LockupKeeper.GetSyntheticLockup(suite.Ctx, lockId, keeper.UnstakingSyntheticDenom(lock.Coins[0].Denom, valAddr))
// suite.Require().NoError(err)
// suite.Require().Equal(synthLock.UnderlyingLockId, lockId)
// suite.Require().Equal(synthLock.SynthDenom, keeper.UnstakingSyntheticDenom(lock.Coins[0].Denom, valAddr))
Expand All @@ -187,7 +193,7 @@ func (suite *KeeperTestSuite) TestBeforeSlashingUnbondingDelegationHook() {
"happy path with single validator and multiple superfluid delegations",
[]stakingtypes.BondStatus{stakingtypes.Bonded},
1,
[]superfluidDelegation{{0, 0, "gamm/pool/1", 1000000}},
[]superfluidDelegation{{0, 0, 0, 1000000}},
[]uint64{1},
[]int64{0},
[]uint64{1},
Expand All @@ -197,7 +203,7 @@ func (suite *KeeperTestSuite) TestBeforeSlashingUnbondingDelegationHook() {
"with single validator and multiple superfluid delegations",
[]stakingtypes.BondStatus{stakingtypes.Bonded},
2,
[]superfluidDelegation{{0, 0, "gamm/pool/1", 1000000}, {1, 0, "gamm/pool/1", 1000000}},
[]superfluidDelegation{{0, 0, 0, 1000000}, {1, 0, 0, 1000000}},
[]uint64{1, 2},
[]int64{0},
[]uint64{1, 2},
Expand All @@ -207,7 +213,7 @@ func (suite *KeeperTestSuite) TestBeforeSlashingUnbondingDelegationHook() {
"with multiple validators and multiple superfluid delegations",
[]stakingtypes.BondStatus{stakingtypes.Bonded, stakingtypes.Bonded},
2,
[]superfluidDelegation{{0, 0, "gamm/pool/1", 1000000}, {1, 1, "gamm/pool/1", 1000000}},
[]superfluidDelegation{{0, 0, 0, 1000000}, {1, 1, 0, 1000000}},
[]uint64{1, 2},
[]int64{0},
[]uint64{1},
Expand All @@ -228,8 +234,11 @@ func (suite *KeeperTestSuite) TestBeforeSlashingUnbondingDelegationHook() {

// setup validators
valAddrs := suite.SetupValidators(tc.validatorStats)

denoms, _ := suite.SetupGammPoolsAndSuperfluidAssets([]sdk.Dec{sdk.NewDec(20), sdk.NewDec(20)})

// setup superfluid delegations
intermediaryAccs, _ := suite.SetupSuperfluidDelegations(delAddrs, valAddrs, tc.superDelegations)
intermediaryAccs, _ := suite.SetupSuperfluidDelegations(delAddrs, valAddrs, tc.superDelegations, denoms)
suite.checkIntermediaryAccountDelegations(intermediaryAccs)

for _, lockId := range tc.superUnbondingLockIds {
Expand Down Expand Up @@ -258,14 +267,14 @@ func (suite *KeeperTestSuite) TestBeforeSlashingUnbondingDelegationHook() {
for _, lockId := range tc.expSlashedLockIds {
gotLock, err := suite.App.LockupKeeper.GetLockByID(suite.Ctx, lockId)
suite.Require().NoError(err)
suite.Require().Equal(sdk.NewInt(950000).String(), gotLock.Coins.AmountOf("gamm/pool/1").String())
suite.Require().Equal(sdk.NewInt(950000).String(), gotLock.Coins.AmountOf(denoms[0]).String())
}

// check unslashed lockups
for _, lockId := range tc.expUnslashedLockIds {
gotLock, err := suite.App.LockupKeeper.GetLockByID(suite.Ctx, lockId)
suite.Require().NoError(err)
suite.Require().Equal(sdk.NewInt(1000000).String(), gotLock.Coins.AmountOf("gamm/pool/1").String())
suite.Require().Equal(sdk.NewInt(1000000).String(), gotLock.Coins.AmountOf(denoms[0]).String())
}
})
}
Expand Down
Loading

0 comments on commit f375c5a

Please sign in to comment.