package simulation import ( "errors" "fmt" "math/rand" "github.com/cosmos/cosmos-sdk/baseapp" "github.com/cosmos/cosmos-sdk/simapp/helpers" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/distribution/keeper" "github.com/cosmos/cosmos-sdk/x/distribution/types" govsim "github.com/cosmos/cosmos-sdk/x/gov/simulation" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" "github.com/cosmos/cosmos-sdk/x/simulation" stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" ) // SimulateMsgSetWithdrawAddress generates a MsgSetWithdrawAddress with random values. // nolint: funlen func SimulateMsgSetWithdrawAddress(ak types.AccountKeeper, k keeper.Keeper) simulation.Operation { return func( r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simulation.Account, chainID string, ) (simulation.OperationMsg, []simulation.FutureOperation, error) { if !k.GetWithdrawAddrEnabled(ctx) { return simulation.NoOpMsg(types.ModuleName), nil, nil } simAccount, _ := simulation.RandomAcc(r, accs) simToAccount, _ := simulation.RandomAcc(r, accs) account := ak.GetAccount(ctx, simAccount.Address) fees, err := simulation.RandomFees(r, ctx, account.SpendableCoins(ctx.BlockTime())) if err != nil { return simulation.NoOpMsg(types.ModuleName), nil, err } msg := types.NewMsgSetWithdrawAddress(simAccount.Address, simToAccount.Address) tx := helpers.GenTx( []sdk.Msg{msg}, fees, chainID, []uint64{account.GetAccountNumber()}, []uint64{account.GetSequence()}, simAccount.PrivKey, ) res := app.Deliver(tx) if !res.IsOK() { return simulation.NoOpMsg(types.ModuleName), nil, errors.New(res.Log) } return simulation.NewOperationMsg(msg, true, ""), nil, nil } } // SimulateMsgWithdrawDelegatorReward generates a MsgWithdrawDelegatorReward with random values. // nolint: funlen func SimulateMsgWithdrawDelegatorReward(ak types.AccountKeeper, k keeper.Keeper, sk stakingkeeper.Keeper) simulation.Operation { return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simulation.Account, chainID string, ) (simulation.OperationMsg, []simulation.FutureOperation, error) { simAccount, _ := simulation.RandomAcc(r, accs) delegations := sk.GetAllDelegatorDelegations(ctx, simAccount.Address) if len(delegations) == 0 { return simulation.NoOpMsg(types.ModuleName), nil, nil } delegation := delegations[r.Intn(len(delegations))] validator := sk.Validator(ctx, delegation.GetValidatorAddr()) if validator == nil { return simulation.NoOpMsg(types.ModuleName), nil, fmt.Errorf("validator %s not found", delegation.GetValidatorAddr()) } account := ak.GetAccount(ctx, simAccount.Address) fees, err := simulation.RandomFees(r, ctx, account.SpendableCoins(ctx.BlockTime())) if err != nil { return simulation.NoOpMsg(types.ModuleName), nil, err } msg := types.NewMsgWithdrawDelegatorReward(simAccount.Address, validator.GetOperator()) tx := helpers.GenTx( []sdk.Msg{msg}, fees, chainID, []uint64{account.GetAccountNumber()}, []uint64{account.GetSequence()}, simAccount.PrivKey, ) res := app.Deliver(tx) if !res.IsOK() { return simulation.NoOpMsg(types.ModuleName), nil, errors.New(res.Log) } return simulation.NewOperationMsg(msg, true, ""), nil, nil } } // SimulateMsgWithdrawValidatorCommission generates a MsgWithdrawValidatorCommission with random values. // nolint: funlen func SimulateMsgWithdrawValidatorCommission(ak types.AccountKeeper, k keeper.Keeper, sk stakingkeeper.Keeper) simulation.Operation { return func( r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simulation.Account, chainID string, ) (simulation.OperationMsg, []simulation.FutureOperation, error) { validator, ok := stakingkeeper.RandomValidator(r, sk, ctx) if !ok { return simulation.NoOpMsg(types.ModuleName), nil, nil } commission := k.GetValidatorAccumulatedCommission(ctx, validator.GetOperator()) if commission.IsZero() { return simulation.NoOpMsg(types.ModuleName), nil, nil } simAccount, found := simulation.FindAccount(accs, sdk.AccAddress(validator.GetOperator())) if !found { return simulation.NoOpMsg(types.ModuleName), nil, fmt.Errorf("validator %s not found", validator.GetOperator()) } account := ak.GetAccount(ctx, simAccount.Address) fees, err := simulation.RandomFees(r, ctx, account.SpendableCoins(ctx.BlockTime())) if err != nil { return simulation.NoOpMsg(types.ModuleName), nil, err } msg := types.NewMsgWithdrawValidatorCommission(validator.GetOperator()) tx := helpers.GenTx( []sdk.Msg{msg}, fees, chainID, []uint64{account.GetAccountNumber()}, []uint64{account.GetSequence()}, simAccount.PrivKey, ) res := app.Deliver(tx) if !res.IsOK() { return simulation.NoOpMsg(types.ModuleName), nil, errors.New(res.Log) } return simulation.NewOperationMsg(msg, true, ""), nil, nil } } // SimulateCommunityPoolSpendProposalContent generates random community-pool-spend proposal content // nolint: funlen func SimulateCommunityPoolSpendProposalContent(k keeper.Keeper) govsim.ContentSimulator { return func(r *rand.Rand, ctx sdk.Context, accs []simulation.Account) govtypes.Content { simAccount, _ := simulation.RandomAcc(r, accs) balance := k.GetFeePool(ctx).CommunityPool if balance.Empty() { return nil } denomIndex := r.Intn(len(balance)) amount, err := simulation.RandPositiveInt(r, balance[denomIndex].Amount.TruncateInt()) if err != nil { return nil } return types.NewCommunityPoolSpendProposal( simulation.RandStringOfLength(r, 10), simulation.RandStringOfLength(r, 100), simAccount.Address, sdk.NewCoins(sdk.NewCoin(balance[denomIndex].Denom, amount)), ) } }