diff --git a/x/stake/handler_test.go b/x/stake/handler_test.go index b18b3c98b2..f08dc481a8 100644 --- a/x/stake/handler_test.go +++ b/x/stake/handler_test.go @@ -638,7 +638,7 @@ func TestBondUnbondRedelegateSlashTwice(t *testing.T) { require.Equal(t, sdk.NewRat(3), delegation.Shares) // validator power should have been reduced to zero - validator, found = keeper.GetValidator(ctx, valA) - require.True(t, found) - require.Equal(t, sdk.NewRat(0), validator.GetPower()) + // ergo validator should have been removed from the store + _, found = keeper.GetValidator(ctx, valA) + require.False(t, found) } diff --git a/x/stake/keeper/slash.go b/x/stake/keeper/slash.go index 2f620d9d47..263f55c1d8 100644 --- a/x/stake/keeper/slash.go +++ b/x/stake/keeper/slash.go @@ -35,8 +35,10 @@ func (k Keeper) Slash(ctx sdk.Context, pubkey crypto.PubKey, infractionHeight in // ref https://github.com/cosmos/cosmos-sdk/issues/1471 validator, found := k.GetValidatorByPubKey(ctx, pubkey) + // If not found, the validator must have been overslashed and removed - so we don't need to do anything if !found { - panic(fmt.Errorf("attempted to slash a nonexistent validator with address %s", pubkey.Address())) + logger.Info(fmt.Sprintf("Ignored attempt to slash a nonexistent validator with address %s", pubkey.Address())) + return } ownerAddress := validator.GetOwner() diff --git a/x/stake/keeper/slash_test.go b/x/stake/keeper/slash_test.go index dcd38e15e2..f9cd8229a0 100644 --- a/x/stake/keeper/slash_test.go +++ b/x/stake/keeper/slash_test.go @@ -291,10 +291,10 @@ func TestSlashWithUnbondingDelegation(t *testing.T) { // just 1 bonded token burned again since that's all the validator now has require.Equal(t, int64(10), oldPool.BondedTokens-newPool.BondedTokens) // read updated validator - validator, found = keeper.GetValidatorByPubKey(ctx, pk) - require.True(t, found) // power decreased by 1 again, validator is out of stake - require.Equal(t, sdk.NewRat(0), validator.GetPower()) + // ergo validator should have been removed from the store + _, found = keeper.GetValidatorByPubKey(ctx, pk) + require.False(t, found) } // tests Slash at a previous height with a redelegation @@ -387,16 +387,16 @@ func TestSlashWithRedelegation(t *testing.T) { // four more bonded tokens burned require.Equal(t, int64(16), oldPool.BondedTokens-newPool.BondedTokens) // read updated validator - validator, found = keeper.GetValidatorByPubKey(ctx, pk) - require.True(t, found) - // power decreased by 4, down to 0 - require.Equal(t, sdk.NewRat(0), validator.GetPower()) + // validator decreased to zero power, should have been removed from the store + _, found = keeper.GetValidatorByPubKey(ctx, pk) + require.False(t, found) // slash the validator again, by 100% // no stake remains to be slashed ctx = ctx.WithBlockHeight(12) - validator, found = keeper.GetValidatorByPubKey(ctx, pk) - require.True(t, found) + // validator no longer in the store + _, found = keeper.GetValidatorByPubKey(ctx, pk) + require.False(t, found) keeper.Slash(ctx, pk, 10, 10, sdk.OneRat()) // read updating redelegation @@ -409,10 +409,9 @@ func TestSlashWithRedelegation(t *testing.T) { // no more bonded tokens burned require.Equal(t, int64(16), oldPool.BondedTokens-newPool.BondedTokens) // read updated validator - validator, found = keeper.GetValidatorByPubKey(ctx, pk) - require.True(t, found) - // power still zero - require.Equal(t, sdk.NewRat(0), validator.GetPower()) + // power still zero, still not in the store + _, found = keeper.GetValidatorByPubKey(ctx, pk) + require.False(t, found) } // tests Slash at a previous height with both an unbonding delegation and a redelegation