Merge PR #5384: Fund Community Pool -- Part II

This commit is contained in:
Alexander Bezobchuk 2019-12-10 23:02:15 -05:00 committed by GitHub
parent 09bd174a49
commit bcca045caf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 113 additions and 26 deletions

View File

@ -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

View File

@ -37,6 +37,7 @@ const (
ParamBaseProposerReward = types.ParamBaseProposerReward
ParamBonusProposerReward = types.ParamBonusProposerReward
ParamWithdrawAddrEnabled = types.ParamWithdrawAddrEnabled
TypeMsgFundCommunityPool = types.TypeMsgFundCommunityPool
)
var (
@ -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

View File

@ -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
@ -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})
},
}

View File

@ -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
@ -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})
}
}

View File

@ -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)
@ -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)
}

View File

@ -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
}

View File

@ -92,7 +92,7 @@ func TestGetTotalRewards(t *testing.T) {
require.Equal(t, expectedRewards, totalRewards)
}
func TestDepositCommunityPoolFunds(t *testing.T) {
func TestFundCommunityPool(t *testing.T) {
// nolint dogsled
ctx, _, bk, keeper, _, _, _ := CreateTestInputAdvanced(t, false, 1000, sdk.NewDecWithPrec(2, 2))
@ -102,7 +102,7 @@ func TestDepositCommunityPoolFunds(t *testing.T) {
initPool := keeper.GetFeePool(ctx)
assert.Empty(t, initPool.CommunityPool)
err := keeper.DepositCommunityPoolFunds(ctx, amount, delAddr1)
err := keeper.FundCommunityPool(ctx, amount, delAddr1)
assert.Nil(t, err)
assert.Equal(t, initPool.CommunityPool.Add(sdk.NewDecCoins(amount)), keeper.GetFeePool(ctx).CommunityPool)

View File

@ -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
@ -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,
@ -63,6 +71,10 @@ func WeightedOperations(
weightMsgWithdrawValidatorCommission,
SimulateMsgWithdrawValidatorCommission(ak, k, sk),
),
simulation.NewWeightedOperation(
weightMsgFundCommunityPool,
SimulateMsgFundCommunityPool(ak, k, sk),
),
}
}
@ -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
}
}

View File

@ -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
}

View File

@ -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 {