Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fund Community Pool -- Part II #5384

Merged
merged 4 commits into from
Dec 11, 2019
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions simapp/params/weights.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const (
DefaultWeightMsgSetWithdrawAddress int = 50
DefaultWeightMsgWithdrawDelegationReward int = 50
DefaultWeightMsgWithdrawValidatorCommission int = 50
DefaultWeightMsgFundCommunityPool int = 50
DefaultWeightMsgDeposit int = 100
DefaultWeightMsgVote int = 67
DefaultWeightMsgUnjail int = 100
Expand Down
2 changes: 2 additions & 0 deletions x/distribution/alias.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ const (
ParamBaseProposerReward = types.ParamBaseProposerReward
ParamBonusProposerReward = types.ParamBonusProposerReward
ParamWithdrawAddrEnabled = types.ParamWithdrawAddrEnabled
TypeMsgFundCommunityPool = types.TypeMsgFundCommunityPool
)

var (
Expand Down Expand Up @@ -90,6 +91,7 @@ var (
NewMsgSetWithdrawAddress = types.NewMsgSetWithdrawAddress
NewMsgWithdrawDelegatorReward = types.NewMsgWithdrawDelegatorReward
NewMsgWithdrawValidatorCommission = types.NewMsgWithdrawValidatorCommission
MsgFundCommunityPool = types.NewMsgFundCommunityPool
NewCommunityPoolSpendProposal = types.NewCommunityPoolSpendProposal
NewQueryValidatorOutstandingRewardsParams = types.NewQueryValidatorOutstandingRewardsParams
NewQueryValidatorCommissionParams = types.NewQueryValidatorCommissionParams
Expand Down
11 changes: 8 additions & 3 deletions x/distribution/client/cli/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -261,12 +261,13 @@ Where proposal.json contains:
return cmd
}

// command to fund the community pool
// GetCmdFundCommunityPool returns a command implementation that supports directly
// funding the community pool.
func GetCmdFundCommunityPool(cdc *codec.Codec) *cobra.Command {
return &cobra.Command{
Use: "fund-community-pool [amount]",
Args: cobra.ExactArgs(1),
Short: "funds the community pool with the specified amount",
Short: "Funds the community pool with the specified amount",
Long: strings.TrimSpace(
fmt.Sprintf(`Funds the community pool with the specified amount
Expand All @@ -287,7 +288,11 @@ $ %s tx fund-community-pool 100uatom --from mykey
return err
}

msg := types.NewMsgDepositIntoCommunityPool(amount, depositorAddr)
msg := types.NewMsgFundCommunityPool(amount, depositorAddr)
if err := msg.ValidateBasic(); err != nil {
return err
}

return utils.GenerateOrBroadcastMsgs(cliCtx, txBldr, []sdk.Msg{msg})
},
}
Expand Down
8 changes: 6 additions & 2 deletions x/distribution/client/rest/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,6 @@ func withdrawValidatorRewardsHandlerFn(cliCtx context.CLIContext) http.HandlerFu
}
}

// Fund the community pool
func fundCommunityPoolHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req fundCommunityPoolReq
Expand All @@ -207,7 +206,12 @@ func fundCommunityPoolHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
return
}

msg := types.NewMsgDepositIntoCommunityPool(req.Amount, fromAddr)
msg := types.NewMsgFundCommunityPool(req.Amount, fromAddr)
if err := msg.ValidateBasic(); err != nil {
rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
return
}

utils.WriteGenerateStdTxResponse(w, cliCtx, req.BaseReq, []sdk.Msg{msg})
}
}
Expand Down
8 changes: 4 additions & 4 deletions x/distribution/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ func NewHandler(k keeper.Keeper) sdk.Handler {
case types.MsgWithdrawValidatorCommission:
return handleMsgWithdrawValidatorCommission(ctx, msg, k)

case types.MsgDepositIntoCommunityPool:
return handleMsgDepositIntoCommunityPool(ctx, msg, k)
case types.MsgFundCommunityPool:
return handleMsgFundCommunityPool(ctx, msg, k)

default:
errMsg := fmt.Sprintf("unrecognized distribution message type: %T", msg)
Expand Down Expand Up @@ -86,8 +86,8 @@ func handleMsgWithdrawValidatorCommission(ctx sdk.Context, msg types.MsgWithdraw
return sdk.Result{Events: ctx.EventManager().Events()}
}

func handleMsgDepositIntoCommunityPool(ctx sdk.Context, msg types.MsgDepositIntoCommunityPool, k keeper.Keeper) sdk.Result {
if err := k.DepositCommunityPoolFunds(ctx, msg.Amount, msg.Depositor); err != nil {
func handleMsgFundCommunityPool(ctx sdk.Context, msg types.MsgFundCommunityPool, k keeper.Keeper) sdk.Result {
if err := k.FundCommunityPool(ctx, msg.Amount, msg.Depositor); err != nil {
return sdk.ResultFromError(err)
}

Expand Down
7 changes: 5 additions & 2 deletions x/distribution/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,8 +150,11 @@ func (k Keeper) GetTotalRewards(ctx sdk.Context) (totalRewards sdk.DecCoins) {
return totalRewards
}

// DepositCommunityPoolFunds allows to transfer the specified amount from the sender into the community pool
func (k Keeper) DepositCommunityPoolFunds(ctx sdk.Context, amount sdk.Coins, sender sdk.AccAddress) error {
// FundCommunityPool allows an account to directly fund the community fund pool.
// The amount is first added to the distribution module account and then directly
// added to the pool. An error is returned if the amount cannot be sent to the
// module account.
func (k Keeper) FundCommunityPool(ctx sdk.Context, amount sdk.Coins, sender sdk.AccAddress) error {
if err := k.supplyKeeper.SendCoinsFromAccountToModule(ctx, sender, types.ModuleName, amount); err != nil {
return err
}
Expand Down
61 changes: 61 additions & 0 deletions x/distribution/simulation/operations.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const (
OpWeightMsgSetWithdrawAddress = "op_weight_msg_set_withdraw_address"
OpWeightMsgWithdrawDelegationReward = "op_weight_msg_withdraw_delegation_reward"
OpWeightMsgWithdrawValidatorCommission = "op_weight_msg_withdraw_validator_commission"
OpWeightMsgFundCommunityPool = "op_weight_msg_fund_community_pool"
)

// WeightedOperations returns all the operations from the module with their respective weights
Expand Down Expand Up @@ -50,6 +51,13 @@ func WeightedOperations(
},
)

var weightMsgFundCommunityPool int
appParams.GetOrGenerate(cdc, OpWeightMsgFundCommunityPool, &weightMsgFundCommunityPool, nil,
func(_ *rand.Rand) {
weightMsgFundCommunityPool = simappparams.DefaultWeightMsgFundCommunityPool
},
)

return simulation.WeightedOperations{
simulation.NewWeightedOperation(
weightMsgSetWithdrawAddress,
Expand All @@ -63,6 +71,10 @@ func WeightedOperations(
weightMsgWithdrawValidatorCommission,
SimulateMsgWithdrawValidatorCommission(ak, k, sk),
),
simulation.NewWeightedOperation(
weightMsgFundCommunityPool,
SimulateMsgFundCommunityPool(ak, k, sk),
),
}
}

Expand Down Expand Up @@ -197,3 +209,52 @@ func SimulateMsgWithdrawValidatorCommission(ak types.AccountKeeper, k keeper.Kee
return simulation.NewOperationMsg(msg, true, ""), nil, nil
}
}

// SimulateMsgFundCommunityPool simulates MsgFundCommunityPool execution where
// a random account sends a random amount of its funds to the community pool.
func SimulateMsgFundCommunityPool(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) {

funder, _ := simulation.RandomAcc(r, accs)

account := ak.GetAccount(ctx, funder.Address)
coins := account.SpendableCoins(ctx.BlockTime())

fundAmount := simulation.RandSubsetCoins(r, coins)
if fundAmount.Empty() {
return simulation.NoOpMsg(types.ModuleName), nil, nil
}

var (
fees sdk.Coins
err error
)

coins, hasNeg := coins.SafeSub(fundAmount)
if !hasNeg {
fees, err = simulation.RandomFees(r, ctx, coins)
if err != nil {
return simulation.NoOpMsg(types.ModuleName), nil, err
}
}

msg := types.NewMsgFundCommunityPool(fundAmount, funder.Address)
tx := helpers.GenTx(
[]sdk.Msg{msg},
fees,
chainID,
[]uint64{account.GetAccountNumber()},
[]uint64{account.GetSequence()},
funder.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
}
}
35 changes: 23 additions & 12 deletions x/distribution/types/msg.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,40 +117,51 @@ func (msg MsgWithdrawValidatorCommission) ValidateBasic() sdk.Error {
return nil
}

// msg struct for delegation withdraw from a single validator
type MsgDepositIntoCommunityPool struct {
const TypeMsgFundCommunityPool = "fund_community_pool"

// MsgFundCommunityPool defines a Msg type that allows an account to directly
// fund the community pool.
type MsgFundCommunityPool struct {
Amount sdk.Coins `json:"amount" yaml:"amount"`
Depositor sdk.AccAddress `json:"depositor" yaml:"depositor"`
}

func NewMsgDepositIntoCommunityPool(amount sdk.Coins, depositor sdk.AccAddress) MsgDepositIntoCommunityPool {
return MsgDepositIntoCommunityPool{
// NewMsgFundCommunityPool returns a new MsgFundCommunityPool with a sender and
// a funding amount.
func NewMsgFundCommunityPool(amount sdk.Coins, depositor sdk.AccAddress) MsgFundCommunityPool {
return MsgFundCommunityPool{
Amount: amount,
Depositor: depositor,
}
}

func (msg MsgDepositIntoCommunityPool) Route() string { return ModuleName }
func (msg MsgDepositIntoCommunityPool) Type() string { return "deposit_into_community_pool" }
// Route returns the MsgFundCommunityPool message route.
func (msg MsgFundCommunityPool) Route() string { return ModuleName }

// Return address that must sign over msg.GetSignBytes()
func (msg MsgDepositIntoCommunityPool) GetSigners() []sdk.AccAddress {
// Type returns the MsgFundCommunityPool message type.
func (msg MsgFundCommunityPool) Type() string { return TypeMsgFundCommunityPool }

// GetSigners returns the signer addresses that are expected to sign the result
// of GetSignBytes.
func (msg MsgFundCommunityPool) GetSigners() []sdk.AccAddress {
return []sdk.AccAddress{msg.Depositor}
}

// get the bytes for the message signer to sign on
func (msg MsgDepositIntoCommunityPool) GetSignBytes() []byte {
// GetSignBytes returns the raw bytes for a MsgFundCommunityPool message that
// the expected signer needs to sign.
func (msg MsgFundCommunityPool) GetSignBytes() []byte {
bz := ModuleCdc.MustMarshalJSON(msg)
return sdk.MustSortJSON(bz)
}

// quick validity check
func (msg MsgDepositIntoCommunityPool) ValidateBasic() sdk.Error {
// ValidateBasic performs basic MsgFundCommunityPool message validation.
func (msg MsgFundCommunityPool) ValidateBasic() sdk.Error {
if !msg.Amount.IsValid() {
return sdk.ErrInvalidCoins(msg.Amount.String())
}
if msg.Depositor.Empty() {
return sdk.ErrInvalidAddress(msg.Depositor.String())
}

return nil
}
2 changes: 1 addition & 1 deletion x/distribution/types/msg_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ func TestMsgDepositIntoCommunityPool(t *testing.T) {
{sdk.NewCoins(sdk.NewInt64Coin("uatom", 1000)), delAddr1, true},
}
for i, tc := range tests {
msg := NewMsgDepositIntoCommunityPool(tc.amount, tc.depositor)
msg := NewMsgFundCommunityPool(tc.amount, tc.depositor)
if tc.expectPass {
require.Nil(t, msg.ValidateBasic(), "test index: %v", i)
} else {
Expand Down