From 9f7a80193ed57e07b67d7dadb5fd9fa57078fe0a Mon Sep 17 00:00:00 2001 From: Facundo Date: Wed, 15 May 2024 09:37:01 +0200 Subject: [PATCH 1/3] fix\(sims\): skip operations that use denoms that can\'t be sent --- x/distribution/simulation/operations.go | 12 ++++++++++++ x/distribution/types/expected_keepers.go | 1 + x/simulation/simulate.go | 4 ++-- x/staking/simulation/operations.go | 8 ++++++++ x/staking/types/expected_keepers.go | 1 + 5 files changed, 24 insertions(+), 2 deletions(-) diff --git a/x/distribution/simulation/operations.go b/x/distribution/simulation/operations.go index 6fdecf6e3c63..7b210bdf95ee 100644 --- a/x/distribution/simulation/operations.go +++ b/x/distribution/simulation/operations.go @@ -158,6 +158,18 @@ func SimulateMsgWithdrawDelegatorReward(txConfig client.TxConfig, ak types.Accou msg := types.NewMsgWithdrawDelegatorReward(addr, validator.GetOperator()) + // get outstanding rewards so we can first check if the withdrawable coins are sendable + outstanding, err := k.GetValidatorOutstandingRewardsCoins(ctx, sdk.ValAddress(delAddr)) + if err != nil { + return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(&types.MsgWithdrawDelegatorReward{}), "error getting outstanding rewards"), nil, err + } + + for _, v := range outstanding { + if !bk.IsSendEnabledDenom(ctx, v.Denom) { + return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(msg), "denom send not enabled: "+v.Denom), nil, nil + } + } + txCtx := simulation.OperationInput{ R: r, App: app, diff --git a/x/distribution/types/expected_keepers.go b/x/distribution/types/expected_keepers.go index 89fb84b75d62..e0fa03dbb1e5 100644 --- a/x/distribution/types/expected_keepers.go +++ b/x/distribution/types/expected_keepers.go @@ -31,6 +31,7 @@ type BankKeeper interface { SendCoinsFromAccountToModule(ctx context.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) error BlockedAddr(addr sdk.AccAddress) bool + IsSendEnabledDenom(ctx context.Context, denom string) bool } // PoolKeeper defines the expected interface needed to fund & distribute pool balances. diff --git a/x/simulation/simulate.go b/x/simulation/simulate.go index ddfe004a7ed5..ed41ffd043c6 100644 --- a/x/simulation/simulate.go +++ b/x/simulation/simulate.go @@ -354,8 +354,8 @@ func createBlockSimulator(tb testing.TB, testingMode bool, w io.Writer, params P logWriter.PrintLogs() tb.Fatalf(`error on block %d/%d, operation (%d/%d) from x/%s: %v -Comment: %s`, - header.Height, config.NumBlocks, opCount, blocksize, opMsg.Route, err, opMsg.Comment) +Comment: %s, Name: %s`, + header.Height, config.NumBlocks, opCount, blocksize, opMsg.Route, err, opMsg.Comment, opMsg.Name) } queueOperations(operationQueue, timeOperationQueue, futureOps) diff --git a/x/staking/simulation/operations.go b/x/staking/simulation/operations.go index 5358c910a900..bf2919257840 100644 --- a/x/staking/simulation/operations.go +++ b/x/staking/simulation/operations.go @@ -450,6 +450,10 @@ func SimulateMsgUndelegate( delAddr, val.GetOperator(), sdk.NewCoin(bondDenom, unbondAmt), ) + if !bk.IsSendEnabledDenom(ctx, bondDenom) { + return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(msg), "bond denom send not enabled"), nil, nil + } + // need to retrieve the simulation account associated with delegation to retrieve PrivKey var simAccount simtypes.Account @@ -712,6 +716,10 @@ func SimulateMsgBeginRedelegate( return simtypes.NoOpMsg(types.ModuleName, msgType, "bond denom not found"), nil, err } + if !bk.IsSendEnabledDenom(ctx, bondDenom) { + return simtypes.NoOpMsg(types.ModuleName, msgType, "bond denom send not enabled"), nil, nil + } + msg := types.NewMsgBeginRedelegate( delAddr, srcVal.GetOperator(), destVal.GetOperator(), sdk.NewCoin(bondDenom, redAmt), diff --git a/x/staking/types/expected_keepers.go b/x/staking/types/expected_keepers.go index 5a274e275142..bd246775a8b6 100644 --- a/x/staking/types/expected_keepers.go +++ b/x/staking/types/expected_keepers.go @@ -40,6 +40,7 @@ type BankKeeper interface { DelegateCoinsFromAccountToModule(ctx context.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) error BurnCoins(context.Context, []byte, sdk.Coins) error + IsSendEnabledDenom(ctx context.Context, denom string) bool } // ValidatorSet expected properties for the set of all validators (noalias) From 9560be76cc75575c35ed5cb0a4d23225f12abd90 Mon Sep 17 00:00:00 2001 From: Facundo Date: Wed, 15 May 2024 09:40:57 +0200 Subject: [PATCH 2/3] remove test print --- x/simulation/simulate.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x/simulation/simulate.go b/x/simulation/simulate.go index ed41ffd043c6..ddfe004a7ed5 100644 --- a/x/simulation/simulate.go +++ b/x/simulation/simulate.go @@ -354,8 +354,8 @@ func createBlockSimulator(tb testing.TB, testingMode bool, w io.Writer, params P logWriter.PrintLogs() tb.Fatalf(`error on block %d/%d, operation (%d/%d) from x/%s: %v -Comment: %s, Name: %s`, - header.Height, config.NumBlocks, opCount, blocksize, opMsg.Route, err, opMsg.Comment, opMsg.Name) +Comment: %s`, + header.Height, config.NumBlocks, opCount, blocksize, opMsg.Route, err, opMsg.Comment) } queueOperations(operationQueue, timeOperationQueue, futureOps) From 80f57e23531ecb66b2c36cc28b07ce7ca6480cf0 Mon Sep 17 00:00:00 2001 From: Facundo Date: Wed, 15 May 2024 09:48:19 +0200 Subject: [PATCH 3/3] make mocks --- testutil/mock/types_module_module.go | 6 +++--- x/distribution/testutil/expected_keepers_mocks.go | 14 ++++++++++++++ x/staking/testutil/expected_keepers_mocks.go | 14 ++++++++++++++ 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/testutil/mock/types_module_module.go b/testutil/mock/types_module_module.go index 94a1d56b4f37..e3327ca7b30d 100644 --- a/testutil/mock/types_module_module.go +++ b/testutil/mock/types_module_module.go @@ -9,8 +9,8 @@ import ( json "encoding/json" reflect "reflect" + legacy "cosmossdk.io/core/legacy" client "github.com/cosmos/cosmos-sdk/client" - codec "github.com/cosmos/cosmos-sdk/codec" types "github.com/cosmos/cosmos-sdk/types" module "github.com/cosmos/cosmos-sdk/types/module" gomock "github.com/golang/mock/gomock" @@ -67,7 +67,7 @@ func (mr *MockAppModuleBasicMockRecorder) RegisterGRPCGatewayRoutes(arg0, arg1 i } // RegisterLegacyAminoCodec mocks base method. -func (m *MockAppModuleBasic) RegisterLegacyAminoCodec(arg0 *codec.LegacyAmino) { +func (m *MockAppModuleBasic) RegisterLegacyAminoCodec(arg0 legacy.Amino) { m.ctrl.T.Helper() m.ctrl.Call(m, "RegisterLegacyAminoCodec", arg0) } @@ -265,7 +265,7 @@ func (m *MockHasAminoCodec) EXPECT() *MockHasAminoCodecMockRecorder { } // RegisterLegacyAminoCodec mocks base method. -func (m *MockHasAminoCodec) RegisterLegacyAminoCodec(arg0 *codec.LegacyAmino) { +func (m *MockHasAminoCodec) RegisterLegacyAminoCodec(arg0 legacy.Amino) { m.ctrl.T.Helper() m.ctrl.Call(m, "RegisterLegacyAminoCodec", arg0) } diff --git a/x/distribution/testutil/expected_keepers_mocks.go b/x/distribution/testutil/expected_keepers_mocks.go index e92ed7d0e12e..a2a2d669f861 100644 --- a/x/distribution/testutil/expected_keepers_mocks.go +++ b/x/distribution/testutil/expected_keepers_mocks.go @@ -156,6 +156,20 @@ func (mr *MockBankKeeperMockRecorder) GetAllBalances(ctx, addr interface{}) *gom return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAllBalances", reflect.TypeOf((*MockBankKeeper)(nil).GetAllBalances), ctx, addr) } +// IsSendEnabledDenom mocks base method. +func (m *MockBankKeeper) IsSendEnabledDenom(ctx context.Context, denom string) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "IsSendEnabledDenom", ctx, denom) + ret0, _ := ret[0].(bool) + return ret0 +} + +// IsSendEnabledDenom indicates an expected call of IsSendEnabledDenom. +func (mr *MockBankKeeperMockRecorder) IsSendEnabledDenom(ctx, denom interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsSendEnabledDenom", reflect.TypeOf((*MockBankKeeper)(nil).IsSendEnabledDenom), ctx, denom) +} + // MintCoins mocks base method. func (m *MockBankKeeper) MintCoins(ctx context.Context, moduleName string, amt types0.Coins) error { m.ctrl.T.Helper() diff --git a/x/staking/testutil/expected_keepers_mocks.go b/x/staking/testutil/expected_keepers_mocks.go index 75b2cfef212b..152d25e217f3 100644 --- a/x/staking/testutil/expected_keepers_mocks.go +++ b/x/staking/testutil/expected_keepers_mocks.go @@ -202,6 +202,20 @@ func (mr *MockBankKeeperMockRecorder) GetSupply(ctx, denom interface{}) *gomock. return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSupply", reflect.TypeOf((*MockBankKeeper)(nil).GetSupply), ctx, denom) } +// IsSendEnabledDenom mocks base method. +func (m *MockBankKeeper) IsSendEnabledDenom(ctx context.Context, denom string) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "IsSendEnabledDenom", ctx, denom) + ret0, _ := ret[0].(bool) + return ret0 +} + +// IsSendEnabledDenom indicates an expected call of IsSendEnabledDenom. +func (mr *MockBankKeeperMockRecorder) IsSendEnabledDenom(ctx, denom interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsSendEnabledDenom", reflect.TypeOf((*MockBankKeeper)(nil).IsSendEnabledDenom), ctx, denom) +} + // LockedCoins mocks base method. func (m *MockBankKeeper) LockedCoins(ctx context.Context, addr types2.AccAddress) types2.Coins { m.ctrl.T.Helper()