diff --git a/app/app.go b/app/app.go index 2441c67fc..e3d96b4c7 100644 --- a/app/app.go +++ b/app/app.go @@ -1008,7 +1008,7 @@ func (app *App) preBlocker(ph *ProposalHandler) func(ctx sdk.Context, _ *abci.Re if err != nil { return nil, err } - if ctx.BlockHeight() == 1062219+1 { // todo: figure out height + if ctx.BlockHeight() == 1062219+1 { bondedPoolBal := app.BankKeeper.GetBalance(ctx, authtypes.NewModuleAddress(stakingtypes.BondedPoolName), "loya") vals, err := app.StakingKeeper.GetValidators(ctx, 7) // only 6 validators exist if err != nil { @@ -1027,8 +1027,6 @@ func (app *App) preBlocker(ph *ProposalHandler) func(ctx sdk.Context, _ *abci.Re // "spendable balance 97171770000loya is smaller than 99121770000loya transferAmt := bondedPoolBal.Amount.Sub(bondedtotal) if transferAmt.Equal(math.NewInt(1950000000)) { // manually checked amount - // last_block_height":"1062219" - err = app.BankKeeper.SendCoinsFromModuleToModule(ctx, stakingtypes.BondedPoolName, stakingtypes.NotBondedPoolName, sdk.NewCoins(sdk.NewCoin("loya", transferAmt))) if err != nil { return nil, err diff --git a/tests/integration/dispute_keeper_test.go b/tests/integration/dispute_keeper_test.go index 2395fe615..50138e121 100644 --- a/tests/integration/dispute_keeper_test.go +++ b/tests/integration/dispute_keeper_test.go @@ -1385,9 +1385,16 @@ func (s *IntegrationTestSuite) TestCurrentBug() { _, err = slashingServer.Unjail(ctx, slashingtypes.NewMsgUnjail(valAccs[2].String())) s.NoError(err) - _, err = simtestutil.NextBlock(s.Setup.App, ctx, time.Minute) - s.Error(err) + ctx, err = simtestutil.NextBlock(s.Setup.App, ctx, time.Minute) + s.NoError(err) - // _, err = slashingServer.Unjail(ctx, slashingtypes.NewMsgUnjail(valAccs[0].String())) - // s.NoError(err) + _, err = slashingServer.Unjail(ctx, slashingtypes.NewMsgUnjail(valAccs[0].String())) + s.NoError(err) + + ctx, err = simtestutil.NextBlock(s.Setup.App, ctx, time.Minute) + s.NoError(err) + // should be back to zero/nil + bal, err = s.Setup.Bankkeeper.Balances.Get(ctx, collections.Join(notbondedpool, "loya")) + s.Error(err, "balance should be zero") + s.True(bal.IsNil()) } diff --git a/x/dispute/keeper/dispute_fee.go b/x/dispute/keeper/dispute_fee.go index a679ff709..93ef6b791 100644 --- a/x/dispute/keeper/dispute_fee.go +++ b/x/dispute/keeper/dispute_fee.go @@ -48,13 +48,13 @@ func (k Keeper) PayDisputeFee(ctx sdk.Context, proposer sdk.AccAddress, fee sdk. // return slashed tokens when reporter either wins dispute or dispute is invalid func (k Keeper) ReturnSlashedTokens(ctx context.Context, dispute types.Dispute) error { - err := k.reporterKeeper.ReturnSlashedTokens(ctx, dispute.SlashAmount, dispute.HashId) + pool, err := k.reporterKeeper.ReturnSlashedTokens(ctx, dispute.SlashAmount, dispute.HashId) if err != nil { return err } coins := sdk.NewCoins(sdk.NewCoin(layertypes.BondDenom, dispute.SlashAmount)) - return k.bankKeeper.SendCoinsFromModuleToModule(ctx, types.ModuleName, stakingtypes.BondedPoolName, coins) + return k.bankKeeper.SendCoinsFromModuleToModule(ctx, types.ModuleName, pool, coins) } func (k Keeper) ReturnFeetoStake(ctx context.Context, hashId []byte, remainingAmt math.Int) error { diff --git a/x/dispute/keeper/dispute_fee_test.go b/x/dispute/keeper/dispute_fee_test.go index ebdde9f8d..6dbcd616d 100644 --- a/x/dispute/keeper/dispute_fee_test.go +++ b/x/dispute/keeper/dispute_fee_test.go @@ -44,8 +44,9 @@ func (s *KeeperTestSuite) TestPayDisputeFee() { func (k *KeeperTestSuite) TestReturnSlashedTokens() { dispute := k.dispute() - k.reporterKeeper.On("ReturnSlashedTokens", k.ctx, dispute.SlashAmount, dispute.HashId).Return(nil) - k.bankKeeper.On("SendCoinsFromModuleToModule", k.ctx, types.ModuleName, stakingtypes.BondedPoolName, sdk.NewCoins(sdk.NewCoin(layer.BondDenom, dispute.SlashAmount))).Return(nil) + pool := stakingtypes.BondedPoolName + k.reporterKeeper.On("ReturnSlashedTokens", k.ctx, dispute.SlashAmount, dispute.HashId).Return(pool, nil) + k.bankKeeper.On("SendCoinsFromModuleToModule", k.ctx, types.ModuleName, pool, sdk.NewCoins(sdk.NewCoin(layer.BondDenom, dispute.SlashAmount))).Return(nil) k.NoError(k.disputeKeeper.ReturnSlashedTokens(k.ctx, dispute)) } diff --git a/x/dispute/mocks/ReporterKeeper.go b/x/dispute/mocks/ReporterKeeper.go index b2cb5e1b0..86552b83f 100644 --- a/x/dispute/mocks/ReporterKeeper.go +++ b/x/dispute/mocks/ReporterKeeper.go @@ -162,17 +162,27 @@ func (_m *ReporterKeeper) JailReporter(ctx context.Context, reporterAddr types.A } // ReturnSlashedTokens provides a mock function with given fields: ctx, amt, hashId -func (_m *ReporterKeeper) ReturnSlashedTokens(ctx context.Context, amt math.Int, hashId []byte) error { +func (_m *ReporterKeeper) ReturnSlashedTokens(ctx context.Context, amt math.Int, hashId []byte) (string, error) { ret := _m.Called(ctx, amt, hashId) - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, math.Int, []byte) error); ok { + var r0 string + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, math.Int, []byte) (string, error)); ok { + return rf(ctx, amt, hashId) + } + if rf, ok := ret.Get(0).(func(context.Context, math.Int, []byte) string); ok { r0 = rf(ctx, amt, hashId) } else { - r0 = ret.Error(0) + r0 = ret.Get(0).(string) } - return r0 + if rf, ok := ret.Get(1).(func(context.Context, math.Int, []byte) error); ok { + r1 = rf(ctx, amt, hashId) + } else { + r1 = ret.Error(1) + } + + return r0, r1 } // TotalReporterPower provides a mock function with given fields: ctx diff --git a/x/dispute/types/expected_keepers.go b/x/dispute/types/expected_keepers.go index bfaa800a6..6bacfc77f 100644 --- a/x/dispute/types/expected_keepers.go +++ b/x/dispute/types/expected_keepers.go @@ -46,7 +46,7 @@ type ReporterKeeper interface { JailReporter(ctx context.Context, reporterAddr sdk.AccAddress, jailDuration uint64) error TotalReporterPower(ctx context.Context) (math.Int, error) FeefromReporterStake(ctx context.Context, reporterAddr sdk.AccAddress, amt math.Int, hashId []byte) error - ReturnSlashedTokens(ctx context.Context, amt math.Int, hashId []byte) error + ReturnSlashedTokens(ctx context.Context, amt math.Int, hashId []byte) (string, error) AddAmountToStake(ctx context.Context, acc sdk.AccAddress, amt math.Int) error Delegation(ctx context.Context, delegator sdk.AccAddress) (reportertypes.Selection, error) GetReporterTokensAtBlock(ctx context.Context, reporter []byte, blockNumber uint64) (math.Int, error) diff --git a/x/reporter/keeper/distribution.go b/x/reporter/keeper/distribution.go index 7587c10a4..5aff3ffa1 100644 --- a/x/reporter/keeper/distribution.go +++ b/x/reporter/keeper/distribution.go @@ -13,11 +13,12 @@ import ( // ReturnSlashedTokens returns the slashed tokens to the delegators, // called in dispute module after dispute is resolved with result invalid or reporter wins -func (k Keeper) ReturnSlashedTokens(ctx context.Context, amt math.Int, hashId []byte) error { +func (k Keeper) ReturnSlashedTokens(ctx context.Context, amt math.Int, hashId []byte) (string, error) { + var pool string // get the snapshot of the metadata of the tokens that were slashed ie selectors' shares amounts and validator they were delegated to snapshot, err := k.DisputedDelegationAmounts.Get(ctx, hashId) if err != nil { - return err + return "", err } // winningpurse represents the amount of tokens that a disputed reporter possibly receives for winning a dispute @@ -31,15 +32,15 @@ func (k Keeper) ReturnSlashedTokens(ctx context.Context, amt math.Int, hashId [] val, err = k.stakingKeeper.GetValidator(ctx, valAddr) if err != nil { if !errors.Is(err, stakingtypes.ErrNoValidatorFound) { - return err + return "", err } vals, err := k.GetBondedValidators(ctx, 1) if err != nil { - return err + return "", err } // this should never happen since there should always be a bonded validator if len(vals) == 0 { - return errors.New("no validators found in staking module to return tokens to") + return "", errors.New("no validators found in staking module to return tokens to") } val = vals[0] } @@ -59,16 +60,17 @@ func (k Keeper) ReturnSlashedTokens(ctx context.Context, amt math.Int, hashId [] var tokenSrc stakingtypes.BondStatus if val.IsBonded() { tokenSrc = stakingtypes.Bonded + pool = stakingtypes.BondedPoolName } else { tokenSrc = stakingtypes.Unbonded + pool = stakingtypes.NotBondedPoolName } _, err = k.stakingKeeper.Delegate(ctx, delAddr, shareAmt.TruncateInt(), tokenSrc, val, false) // false means to not subtract tokens from an account if err != nil { - return err + return "", err } } - - return k.DisputedDelegationAmounts.Remove(ctx, hashId) + return pool, k.DisputedDelegationAmounts.Remove(ctx, hashId) } // called in dispute module after dispute is resolved diff --git a/x/reporter/keeper/distribution_test.go b/x/reporter/keeper/distribution_test.go index ab88518ed..33fc83ad6 100644 --- a/x/reporter/keeper/distribution_test.go +++ b/x/reporter/keeper/distribution_test.go @@ -76,8 +76,8 @@ func TestReturnSlashedTokens(t *testing.T) { sk.On("GetValidator", ctx, val2Address).Return(validator2, nil) sk.On("Delegate", ctx, delAddr1, tokenOrigin1.Amount, stakingtypes.Bonded, validator1, false).Return(math.LegacyZeroDec(), nil) sk.On("Delegate", ctx, delAddr2, tokenOrigin2.Amount, stakingtypes.Bonded, validator2, false).Return(math.LegacyZeroDec(), nil) - - require.NoError(t, k.ReturnSlashedTokens(ctx, math.NewIntWithDecimal(2000, 6), []byte("hashId"))) + _, err = k.ReturnSlashedTokens(ctx, math.NewIntWithDecimal(2000, 6), []byte("hashId")) + require.NoError(t, err) } func TestFeeRefund(t *testing.T) {