120 lines
5.2 KiB
Go
120 lines
5.2 KiB
Go
package staking
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
|
|
"gotest.tools/v3/assert"
|
|
|
|
"cosmossdk.io/core/header"
|
|
"cosmossdk.io/math"
|
|
banktestutil "cosmossdk.io/x/bank/testutil"
|
|
"cosmossdk.io/x/staking/keeper"
|
|
"cosmossdk.io/x/staking/testutil"
|
|
"cosmossdk.io/x/staking/types"
|
|
|
|
"github.com/cosmos/cosmos-sdk/tests/integration/v2"
|
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
|
)
|
|
|
|
func TestUnbondingDelegationsMaxEntries(t *testing.T) {
|
|
t.Parallel()
|
|
f := initFixture(t, false)
|
|
|
|
ctx := f.ctx
|
|
|
|
initTokens := f.stakingKeeper.TokensFromConsensusPower(ctx, int64(1000))
|
|
assert.NilError(t, f.bankKeeper.MintCoins(ctx, types.ModuleName, sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, initTokens))))
|
|
|
|
addrDel := sdk.AccAddress([]byte("addr"))
|
|
accAmt := math.NewInt(10000)
|
|
bondDenom, err := f.stakingKeeper.BondDenom(ctx)
|
|
assert.NilError(t, err)
|
|
|
|
initCoins := sdk.NewCoins(sdk.NewCoin(bondDenom, accAmt))
|
|
assert.NilError(t, f.bankKeeper.MintCoins(ctx, types.ModuleName, initCoins))
|
|
assert.NilError(t, f.bankKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleName, addrDel, initCoins))
|
|
addrVal := sdk.ValAddress(addrDel)
|
|
|
|
startTokens := f.stakingKeeper.TokensFromConsensusPower(ctx, 10)
|
|
|
|
notBondedPool := f.stakingKeeper.GetNotBondedPool(ctx)
|
|
|
|
assert.NilError(t, banktestutil.FundModuleAccount(ctx, f.bankKeeper, notBondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(bondDenom, startTokens))))
|
|
f.accountKeeper.SetModuleAccount(ctx, notBondedPool)
|
|
|
|
// create a validator and a delegator to that validator
|
|
validator := testutil.NewValidator(t, addrVal, PKs[0])
|
|
|
|
validator, issuedShares := validator.AddTokensFromDel(startTokens)
|
|
assert.DeepEqual(t, startTokens, issuedShares.RoundInt())
|
|
|
|
validator, _ = keeper.TestingUpdateValidatorV2(f.stakingKeeper, ctx, validator, true)
|
|
assert.Assert(math.IntEq(t, startTokens, validator.BondedTokens()))
|
|
assert.Assert(t, validator.IsBonded())
|
|
|
|
delegation := types.NewDelegation(addrDel.String(), addrVal.String(), issuedShares)
|
|
assert.NilError(t, f.stakingKeeper.SetDelegation(ctx, delegation))
|
|
|
|
maxEntries, err := f.stakingKeeper.MaxEntries(ctx)
|
|
assert.NilError(t, err)
|
|
|
|
oldBonded := f.bankKeeper.GetBalance(ctx, f.stakingKeeper.GetBondedPool(ctx).GetAddress(), bondDenom).Amount
|
|
oldNotBonded := f.bankKeeper.GetBalance(ctx, f.stakingKeeper.GetNotBondedPool(ctx).GetAddress(), bondDenom).Amount
|
|
|
|
// should all pass
|
|
var completionTime time.Time
|
|
totalUnbonded := math.NewInt(0)
|
|
for i := int64(0); i < int64(maxEntries); i++ {
|
|
var err error
|
|
ctx = integration.SetHeaderInfo(ctx, header.Info{Height: i})
|
|
var amount math.Int
|
|
completionTime, amount, err = f.stakingKeeper.Undelegate(ctx, addrDel, addrVal, math.LegacyNewDec(1))
|
|
assert.NilError(t, err)
|
|
totalUnbonded = totalUnbonded.Add(amount)
|
|
}
|
|
|
|
newBonded := f.bankKeeper.GetBalance(ctx, f.stakingKeeper.GetBondedPool(ctx).GetAddress(), bondDenom).Amount
|
|
newNotBonded := f.bankKeeper.GetBalance(ctx, f.stakingKeeper.GetNotBondedPool(ctx).GetAddress(), bondDenom).Amount
|
|
assert.Assert(math.IntEq(t, newBonded, oldBonded.SubRaw(int64(maxEntries))))
|
|
assert.Assert(math.IntEq(t, newNotBonded, oldNotBonded.AddRaw(int64(maxEntries))))
|
|
assert.Assert(math.IntEq(t, totalUnbonded, oldBonded.Sub(newBonded)))
|
|
assert.Assert(math.IntEq(t, totalUnbonded, newNotBonded.Sub(oldNotBonded)))
|
|
|
|
oldBonded = f.bankKeeper.GetBalance(ctx, f.stakingKeeper.GetBondedPool(ctx).GetAddress(), bondDenom).Amount
|
|
oldNotBonded = f.bankKeeper.GetBalance(ctx, f.stakingKeeper.GetNotBondedPool(ctx).GetAddress(), bondDenom).Amount
|
|
|
|
// an additional unbond should fail due to max entries
|
|
_, _, err = f.stakingKeeper.Undelegate(ctx, addrDel, addrVal, math.LegacyNewDec(1))
|
|
assert.Error(t, err, "too many unbonding delegation entries for (delegator, validator) tuple")
|
|
|
|
newBonded = f.bankKeeper.GetBalance(ctx, f.stakingKeeper.GetBondedPool(ctx).GetAddress(), bondDenom).Amount
|
|
newNotBonded = f.bankKeeper.GetBalance(ctx, f.stakingKeeper.GetNotBondedPool(ctx).GetAddress(), bondDenom).Amount
|
|
|
|
assert.Assert(math.IntEq(t, newBonded, oldBonded))
|
|
assert.Assert(math.IntEq(t, newNotBonded, oldNotBonded))
|
|
|
|
// mature unbonding delegations
|
|
ctx = integration.SetHeaderInfo(ctx, header.Info{Time: completionTime})
|
|
acc := f.accountKeeper.NewAccountWithAddress(ctx, addrDel)
|
|
f.accountKeeper.SetAccount(ctx, acc)
|
|
_, err = f.stakingKeeper.CompleteUnbonding(ctx, addrDel, addrVal)
|
|
assert.NilError(t, err)
|
|
|
|
newBonded = f.bankKeeper.GetBalance(ctx, f.stakingKeeper.GetBondedPool(ctx).GetAddress(), bondDenom).Amount
|
|
newNotBonded = f.bankKeeper.GetBalance(ctx, f.stakingKeeper.GetNotBondedPool(ctx).GetAddress(), bondDenom).Amount
|
|
assert.Assert(math.IntEq(t, newBonded, oldBonded))
|
|
assert.Assert(math.IntEq(t, newNotBonded, oldNotBonded.SubRaw(int64(maxEntries))))
|
|
|
|
oldNotBonded = f.bankKeeper.GetBalance(ctx, f.stakingKeeper.GetNotBondedPool(ctx).GetAddress(), bondDenom).Amount
|
|
|
|
// unbonding should work again
|
|
_, _, err = f.stakingKeeper.Undelegate(ctx, addrDel, addrVal, math.LegacyNewDec(1))
|
|
assert.NilError(t, err)
|
|
|
|
newBonded = f.bankKeeper.GetBalance(ctx, f.stakingKeeper.GetBondedPool(ctx).GetAddress(), bondDenom).Amount
|
|
newNotBonded = f.bankKeeper.GetBalance(ctx, f.stakingKeeper.GetNotBondedPool(ctx).GetAddress(), bondDenom).Amount
|
|
assert.Assert(math.IntEq(t, newBonded, oldBonded.SubRaw(1)))
|
|
assert.Assert(math.IntEq(t, newNotBonded, oldNotBonded.AddRaw(1)))
|
|
}
|