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

feat(community): add MsgUpdateParams for governance #1745

Merged
merged 10 commits into from
Oct 11, 2023
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
- (metrics) [#1669] Add performance timing metrics to all Begin/EndBlockers
- (community) [#1704] Add module params
- (community) [#1706] Add disable inflation upgrade
- (community) [#1745] Enable params update via governance with `MsgUpdateParams`

### Bug Fixes

Expand Down Expand Up @@ -292,6 +293,7 @@ the [changelog](https://github.com/cosmos/cosmos-sdk/blob/v0.38.4/CHANGELOG.md).
- [#257](https://github.com/Kava-Labs/kava/pulls/257) Include scripts to run
large-scale simulations remotely using aws-batch

[#1745]: https://github.com/Kava-Labs/kava/pull/1745
[#1707]: https://github.com/Kava-Labs/kava/pull/1707
[#1706]: https://github.com/Kava-Labs/kava/pull/1706
[#1668]: https://github.com/Kava-Labs/kava/pull/1668
Expand Down
19 changes: 11 additions & 8 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -251,8 +251,10 @@ var (
)

// Verify app interface at compile time
var _ servertypes.Application = (*App)(nil)
var _ servertypes.ApplicationQueryService = (*App)(nil)
var (
_ servertypes.Application = (*App)(nil)
_ servertypes.ApplicationQueryService = (*App)(nil)
)

// Options bundles several configuration params for an App.
type Options struct {
Expand Down Expand Up @@ -379,6 +381,9 @@ func NewApp(
tkeys := sdk.NewTransientStoreKeys(paramstypes.TStoreKey, evmtypes.TransientKey, feemarkettypes.TransientKey)
memKeys := sdk.NewMemoryStoreKeys(capabilitytypes.MemStoreKey)

// Authority for gov proposals, using the x/gov module account address
govAuthorityAddr := authtypes.NewModuleAddress(govtypes.ModuleName)

app := &App{
BaseApp: bApp,
legacyAmino: legacyAmino,
Expand Down Expand Up @@ -485,8 +490,7 @@ func NewApp(
appCodec,
homePath,
app.BaseApp,
// Authority
authtypes.NewModuleAddress(govtypes.ModuleName).String(),
govAuthorityAddr.String(),
)
app.evidenceKeeper = *evidencekeeper.NewKeeper(
appCodec,
Expand All @@ -507,8 +511,7 @@ func NewApp(
// Create Ethermint keepers
app.feeMarketKeeper = feemarketkeeper.NewKeeper(
appCodec,
// Authority
authtypes.NewModuleAddress(govtypes.ModuleName),
govAuthorityAddr,
keys[feemarkettypes.StoreKey],
tkeys[feemarkettypes.TransientKey],
feemarketSubspace,
Expand All @@ -525,8 +528,7 @@ func NewApp(
evmBankKeeper := evmutilkeeper.NewEvmBankKeeper(app.evmutilKeeper, app.bankKeeper, app.accountKeeper)
app.evmKeeper = evmkeeper.NewKeeper(
appCodec, keys[evmtypes.StoreKey], tkeys[evmtypes.TransientKey],
// Authority
authtypes.NewModuleAddress(govtypes.ModuleName),
govAuthorityAddr,
app.accountKeeper, evmBankKeeper, app.stakingKeeper, app.feeMarketKeeper,
nil, // precompiled contracts
geth.NewEVM,
Expand Down Expand Up @@ -667,6 +669,7 @@ func NewApp(
&app.mintKeeper,
&app.kavadistKeeper,
app.stakingKeeper,
govAuthorityAddr,
)

app.incentiveKeeper = incentivekeeper.NewKeeper(
Expand Down
29 changes: 29 additions & 0 deletions docs/core/proto-docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,8 @@
- [kava/community/v1beta1/tx.proto](#kava/community/v1beta1/tx.proto)
- [MsgFundCommunityPool](#kava.community.v1beta1.MsgFundCommunityPool)
- [MsgFundCommunityPoolResponse](#kava.community.v1beta1.MsgFundCommunityPoolResponse)
- [MsgUpdateParams](#kava.community.v1beta1.MsgUpdateParams)
- [MsgUpdateParamsResponse](#kava.community.v1beta1.MsgUpdateParamsResponse)

- [Msg](#kava.community.v1beta1.Msg)

Expand Down Expand Up @@ -3214,6 +3216,32 @@ MsgFundCommunityPoolResponse defines the Msg/FundCommunityPool response type.




<a name="kava.community.v1beta1.MsgUpdateParams"></a>

### MsgUpdateParams
MsgUpdateParams allows an account to update the community module parameters.


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `authority` | [string](#string) | | authority is the address that controls the module (defaults to x/gov unless overwritten). |
| `params` | [Params](#kava.community.v1beta1.Params) | | params defines the x/community parameters to update. |






<a name="kava.community.v1beta1.MsgUpdateParamsResponse"></a>

### MsgUpdateParamsResponse
MsgUpdateParamsResponse defines the Msg/UpdateParams response type.





<!-- end messages -->

<!-- end enums -->
Expand All @@ -3229,6 +3257,7 @@ Msg defines the community Msg service.
| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint |
| ----------- | ------------ | ------------- | ------------| ------- | -------- |
| `FundCommunityPool` | [MsgFundCommunityPool](#kava.community.v1beta1.MsgFundCommunityPool) | [MsgFundCommunityPoolResponse](#kava.community.v1beta1.MsgFundCommunityPoolResponse) | FundCommunityPool defines a method to allow an account to directly fund the community module account. | |
| `UpdateParams` | [MsgUpdateParams](#kava.community.v1beta1.MsgUpdateParams) | [MsgUpdateParamsResponse](#kava.community.v1beta1.MsgUpdateParamsResponse) | UpdateParams defines a method to allow an account to update the community module parameters. | |

<!-- end services -->

Expand Down
2 changes: 2 additions & 0 deletions proto/kava/community/v1beta1/params.proto
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ option go_package = "github.com/kava-labs/kava/x/community/types";

// Params defines the parameters of the community module.
message Params {
option (gogoproto.equal) = true;
drklee3 marked this conversation as resolved.
Show resolved Hide resolved

// upgrade_time_disable_inflation is the time at which to disable mint and kavadist module inflation.
// If set to 0, inflation will be disabled from block 1.
google.protobuf.Timestamp upgrade_time_disable_inflation = 1 [
Expand Down
18 changes: 18 additions & 0 deletions proto/kava/community/v1beta1/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ package kava.community.v1beta1;
import "cosmos/base/v1beta1/coin.proto";
import "cosmos_proto/cosmos.proto";
import "gogoproto/gogo.proto";
import "kava/community/v1beta1/params.proto";

option go_package = "github.com/kava-labs/kava/x/community/types";
option (gogoproto.equal_all) = true;
Expand All @@ -12,6 +13,9 @@ option (gogoproto.equal_all) = true;
service Msg {
// FundCommunityPool defines a method to allow an account to directly fund the community module account.
rpc FundCommunityPool(MsgFundCommunityPool) returns (MsgFundCommunityPoolResponse);

// UpdateParams defines a method to allow an account to update the community module parameters.
rpc UpdateParams(MsgUpdateParams) returns (MsgUpdateParamsResponse);
}

// MsgFundCommunityPool allows an account to directly fund the community module account.
Expand All @@ -27,3 +31,17 @@ message MsgFundCommunityPool {

// MsgFundCommunityPoolResponse defines the Msg/FundCommunityPool response type.
message MsgFundCommunityPoolResponse {}

// MsgUpdateParams allows an account to update the community module parameters.
message MsgUpdateParams {
option (gogoproto.goproto_getters) = false;

// authority is the address that controls the module (defaults to x/gov unless overwritten).
string authority = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"];

// params defines the x/community parameters to update.
Params params = 2 [(gogoproto.nullable) = false];
}

// MsgUpdateParamsResponse defines the Msg/UpdateParams response type.
message MsgUpdateParamsResponse {}
173 changes: 173 additions & 0 deletions tests/e2e/e2e_community_update_params_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
package e2e_test

import (
"context"
"encoding/hex"
"time"

sdkmath "cosmossdk.io/math"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
govv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1"

"github.com/kava-labs/kava/tests/e2e/testutil"
"github.com/kava-labs/kava/tests/util"
communitytypes "github.com/kava-labs/kava/x/community/types"
)

func (suite *IntegrationTestSuite) TestCommunityUpdateParams_NonAuthority() {
drklee3 marked this conversation as resolved.
Show resolved Hide resolved
// ARRANGE
// setup kava account
funds := ukava(1e5) // .1 KAVA
kavaAcc := suite.Kava.NewFundedAccount("community-non-authority", sdk.NewCoins(funds))

gasLimit := int64(2e5)
fee := ukava(200)

msg := communitytypes.NewMsgUpdateParams(
kavaAcc.SdkAddress,
communitytypes.DefaultParams(),
)

// ACT
req := util.KavaMsgRequest{
Msgs: []sdk.Msg{&msg},
GasLimit: uint64(gasLimit),
FeeAmount: sdk.NewCoins(fee),
Memo: "this is a failure!",
}
res := kavaAcc.SignAndBroadcastKavaTx(req)

// ASSERT
_, err := util.WaitForSdkTxCommit(suite.Kava.Tx, res.Result.TxHash, 6*time.Second)
suite.Require().Error(err)
suite.Require().ErrorContains(
err,
govtypes.ErrInvalidSigner.Error(),
"should return with authority check error",
)
}

func (suite *IntegrationTestSuite) TestCommunityUpdateParams_Authority() {
// ARRANGE
govParamsRes, err := suite.Kava.Gov.Params(context.Background(), &govv1.QueryParamsRequest{
ParamsType: govv1.ParamDeposit,
})
suite.NoError(err)

// Check initial params
communityParamsResInitial, err := suite.Kava.Community.Params(
context.Background(),
&communitytypes.QueryParamsRequest{},
)
suite.Require().NoError(err)

// setup kava account
// .1 KAVA + min deposit amount for proposal
funds := sdk.NewCoins(ukava(1e5)).Add(govParamsRes.DepositParams.MinDeposit...)
kavaAcc := suite.Kava.NewFundedAccount("community-update-params", funds)

gasLimit := int64(2e5)
fee := ukava(200)

upgradeTime := time.Now().Add(24 * time.Hour).UTC()

// 1. Proposal
updateParamsMsg := communitytypes.NewMsgUpdateParams(
authtypes.NewModuleAddress(govtypes.ModuleName), // authority
communitytypes.NewParams(
upgradeTime,
sdkmath.LegacyNewDec(1111), // stakingRewardsPerSecond
sdkmath.LegacyNewDec(2222), // upgradeTimeSetstakingRewardsPerSecond
),
)

// Make sure we're actually changing the params
suite.NotEqual(
updateParamsMsg.Params,
communityParamsResInitial.Params,
"new params should be different from existing",
)

proposalMsg, err := govv1.NewMsgSubmitProposal(
[]sdk.Msg{&updateParamsMsg},
govParamsRes.DepositParams.MinDeposit,
kavaAcc.SdkAddress.String(),
"community-update-params",
)
suite.NoError(err)

req := util.KavaMsgRequest{
Msgs: []sdk.Msg{proposalMsg},
GasLimit: uint64(gasLimit),
FeeAmount: sdk.NewCoins(fee),
Memo: "this is a proposal please accept me",
}
res := kavaAcc.SignAndBroadcastKavaTx(req)
suite.Require().NoError(res.Err)

// Wait for proposal to be submitted
txRes, err := util.WaitForSdkTxCommit(suite.Kava.Tx, res.Result.TxHash, 6*time.Second)
suite.Require().NoError(err)

// Parse tx response to get proposal id
var govRes govv1.MsgSubmitProposalResponse
suite.decodeTxMsgResponse(txRes, &govRes)

// 2. Vote for proposal from whale account
whale := suite.Kava.GetAccount(testutil.FundedAccountName)
voteMsg := govv1.NewMsgVote(
whale.SdkAddress,
govRes.ProposalId,
govv1.OptionYes,
"",
)

voteReq := util.KavaMsgRequest{
Msgs: []sdk.Msg{voteMsg},
GasLimit: uint64(gasLimit),
FeeAmount: sdk.NewCoins(fee),
Memo: "voting",
}
voteRes := whale.SignAndBroadcastKavaTx(voteReq)
suite.Require().NoError(voteRes.Err)

_, err = util.WaitForSdkTxCommit(suite.Kava.Tx, voteRes.Result.TxHash, 6*time.Second)
suite.Require().NoError(err)

// 3. Wait until proposal passes
suite.Require().Eventually(func() bool {
proposalRes, err := suite.Kava.Gov.Proposal(context.Background(), &govv1.QueryProposalRequest{
ProposalId: govRes.ProposalId,
})
suite.NoError(err)

return proposalRes.Proposal.Status == govv1.StatusPassed
}, 60*time.Second, 1*time.Second)

// Check parameters are updated
communityParamsRes, err := suite.Kava.Community.Params(
context.Background(),
&communitytypes.QueryParamsRequest{},
)
suite.Require().NoError(err)

suite.Equal(updateParamsMsg.Params, communityParamsRes.Params)
}

func (suite *IntegrationTestSuite) decodeTxMsgResponse(txRes *sdk.TxResponse, ptr codec.ProtoMarshaler) {
// convert txRes.Data hex string to bytes
txResBytes, err := hex.DecodeString(txRes.Data)
suite.Require().NoError(err)

// Unmarshal data to TxMsgData
var txMsgData sdk.TxMsgData
suite.Kava.EncodingConfig.Marshaler.MustUnmarshal(txResBytes, &txMsgData)
suite.T().Logf("txData.MsgResponses: %v", txMsgData.MsgResponses)

// Parse MsgResponse
suite.Kava.EncodingConfig.Marshaler.MustUnmarshal(txMsgData.MsgResponses[0].Value, ptr)
suite.Require().NoError(err)
}
3 changes: 3 additions & 0 deletions tests/e2e/testutil/chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
txtypes "github.com/cosmos/cosmos-sdk/types/tx"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
govv1types "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types"

"github.com/ethereum/go-ethereum"
Expand Down Expand Up @@ -55,6 +56,7 @@ type Chain struct {
Earn earntypes.QueryClient
Evm evmtypes.QueryClient
Evmutil evmutiltypes.QueryClient
Gov govv1types.QueryClient
Tm tmservice.ServiceClient
Tx txtypes.ServiceClient
Upgrade upgradetypes.QueryClient
Expand Down Expand Up @@ -91,6 +93,7 @@ func NewChain(t *testing.T, details *runner.ChainDetails, fundedAccountMnemonic
chain.Earn = earntypes.NewQueryClient(grpcConn)
chain.Evm = evmtypes.NewQueryClient(grpcConn)
chain.Evmutil = evmutiltypes.NewQueryClient(grpcConn)
chain.Gov = govv1types.NewQueryClient(grpcConn)
chain.Tm = tmservice.NewServiceClient(grpcConn)
chain.Tx = txtypes.NewServiceClient(grpcConn)
chain.Upgrade = upgradetypes.NewQueryClient(grpcConn)
Expand Down
Loading
Loading