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

Add update params to marker module #1991

Merged
Merged
Show file tree
Hide file tree
Changes from all 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 CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
* Add `UpdateParams` and `Params` query rpc endpoints to modules.
* `ibcratelimit` add `UpdateParams` endpoint and deprecate `GovUpdateParams` [#1984](https://github.com/provenance-io/provenance/pull/1984).
* `attribute` add `UpdateParams` endpoint and cli [#1987](https://github.com/provenance-io/provenance/pull/1987).
* `marker` add `UpdateParams` endpoint and cli [#1991](https://github.com/provenance-io/provenance/pull/1991).
* Update the exchange `commitment-settlement-fee-calc` cli query to utilize the keyring [#2001](https://github.com/provenance-io/provenance/pull/2001).

### Client Breaking
Expand Down
2 changes: 1 addition & 1 deletion client/docs/statik/statik.go

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions client/docs/swagger-ui/swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -106932,6 +106932,11 @@ definitions:
title: >-
MsgUpdateForcedTransferResponse defines the Msg/UpdateForcedTransfer
response type
provenance.marker.v1.MsgUpdateParamsResponse:
type: object
description: >-
MsgUpdateParamsResponse is a response message for the UpdateParams
endpoint.
provenance.marker.v1.MsgUpdateRequiredAttributesResponse:
type: object
title: >-
Expand Down
2 changes: 1 addition & 1 deletion proto/provenance/ibcratelimit/v1/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ service Msg {
option deprecated = true;
}

// UpdateParams is a governance proposal endpoint for updating the exchange module's params.
// UpdateParams is a governance proposal endpoint for updating the ibcratelimit module's params.
rpc UpdateParams(MsgUpdateParamsRequest) returns (MsgUpdateParamsResponse);
}

Expand Down
7 changes: 7 additions & 0 deletions proto/provenance/marker/v1/marker.proto
Original file line number Diff line number Diff line change
Expand Up @@ -208,3 +208,10 @@ message EventSetNetAssetValue {
string volume = 3;
string source = 4;
}

// EventMarkerParamsUpdated event emitted when marker params are updated.
message EventMarkerParamsUpdated {
Taztingo marked this conversation as resolved.
Show resolved Hide resolved
string enable_governance = 1;
string unrestricted_denom_regex = 2;
string max_supply = 3;
}
20 changes: 17 additions & 3 deletions proto/provenance/marker/v1/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,8 @@ service Msg {
rpc WithdrawEscrowProposal(MsgWithdrawEscrowProposalRequest) returns (MsgWithdrawEscrowProposalResponse);
// SetDenomMetadataProposal is a governance proposal to set marker metadata
rpc SetDenomMetadataProposal(MsgSetDenomMetadataProposalRequest) returns (MsgSetDenomMetadataProposalResponse);

// TODO: UpdateParams
// UpdateParams is a governance proposal endpoint for updating the marker module's params.
rpc UpdateParams(MsgUpdateParamsRequest) returns (MsgUpdateParamsResponse);
}

// MsgGrantAllowanceRequest validates permission to create a fee grant based on marker admin access. If
Expand Down Expand Up @@ -462,4 +462,18 @@ message MsgSetDenomMetadataProposalRequest {
}

// MsgSetDenomMetadataProposalResponse defines the Msg/SetDenomMetadataProposal response type
message MsgSetDenomMetadataProposalResponse {}
message MsgSetDenomMetadataProposalResponse {}

// MsgUpdateParamsRequest is a request message for the UpdateParams endpoint.
message MsgUpdateParamsRequest {
option (cosmos.msg.v1.signer) = "authority";

// authority should be the governance module account address.
string authority = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"];

// params are the new param values to set.
Params params = 2 [(gogoproto.nullable) = false];
}

// MsgUpdateParamsResponse is a response message for the UpdateParams endpoint.
message MsgUpdateParamsResponse {}
4 changes: 2 additions & 2 deletions x/ibcratelimit/tx.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

59 changes: 59 additions & 0 deletions x/marker/client/cli/cli_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2552,3 +2552,62 @@ func (s *IntegrationTestSuite) TestUpdateParamsProposal() {
})
}
}

func (s *IntegrationTestSuite) TestUpdateMarkerParamsCmd() {
testCases := []struct {
name string
cmd *cobra.Command
args []string
expectErr string
expectedCode uint32
}{
{
name: "update marker params, should succeed",
cmd: markercli.GetUpdateMarkerParamsCmd(),
args: []string{
"true",
"[a-zA-Z][a-zA-Z0-9\\-\\.]{2,83}",
"1000000",
},
expectedCode: 0,
},
{
name: "update marker params, should fail incorrect governance flag",
cmd: markercli.GetUpdateMarkerParamsCmd(),
args: []string{
"invalid",
"[a-zA-Z][a-zA-Z0-9\\-\\.]{2,83}",
"1000000",
},
expectErr: `invalid enable governance flag: strconv.ParseBool: parsing "invalid": invalid syntax`,
},
{
name: "update marker params, should fail incorrect maxSupply",
cmd: markercli.GetUpdateMarkerParamsCmd(),
args: []string{
"true",
"[a-zA-Z][a-zA-Z0-9\\-\\.]{2,83}",
"invalid",
},
expectErr: `invalid max supply: "invalid"`,
},
}

for _, tc := range testCases {
s.Run(tc.name, func() {
tc.args = append(tc.args,
"--title", fmt.Sprintf("title: %v", tc.name),
"--summary", fmt.Sprintf("summary: %v", tc.name),
"--deposit=1000000stake",
fmt.Sprintf("--%s=%s", flags.FlagFrom, s.testnet.Validators[0].Address.String()),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewInt64Coin(s.cfg.BondDenom, 10)).String()),
)
testcli.NewTxExecutor(tc.cmd, tc.args).
WithExpErrMsg(tc.expectErr).
WithExpCode(tc.expectedCode).
Execute(s.T(), s.testnet)
})
}
}
48 changes: 48 additions & 0 deletions x/marker/client/cli/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/spf13/pflag"

cerrs "cosmossdk.io/errors"
sdkmath "cosmossdk.io/math"
"cosmossdk.io/x/feegrant"

"github.com/cosmos/cosmos-sdk/client"
Expand Down Expand Up @@ -95,6 +96,7 @@ func NewTxCmd() *cobra.Command {
GetCmdRemoveAdministratorProposal(),
GetCmdChangeStatusProposal(),
GetCmdWithdrawEscrowProposal(),
GetUpdateMarkerParamsCmd(),
)
return txCmd
}
Expand Down Expand Up @@ -1551,3 +1553,49 @@ func generateOrBroadcastOptGovProp(clientCtx client.Context, flagSet *pflag.Flag
}
return tx.GenerateOrBroadcastTxCLI(clientCtx, flagSet, msg)
}

// GetUpdateMarkerParamsCmd creates a command to update the marker module's params via governance proposal.
func GetUpdateMarkerParamsCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "update-marker-params <enable-governance> <unrestricted-denom-regex> <max-supply>",
Short: "Update the marker module's params via governance proposal",
Long: "Submit an update marker params via governance proposal along with an initial deposit.",
Args: cobra.ExactArgs(3),
Example: fmt.Sprintf(`%[1]s tx marker update-marker-params true "[a-zA-Z][a-zA-Z0-9\\-\\.]{2,83}" 1000000000000 --deposit 50000nhash`, version.AppName),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
return err
}

flagSet := cmd.Flags()
authority := provcli.GetAuthority(flagSet)

enableGovernance, err := strconv.ParseBool(args[0])
if err != nil {
return fmt.Errorf("invalid enable governance flag: %w", err)
}

unrestrictedDenomRegex := args[1]

maxSupply, ok := sdkmath.NewIntFromString(args[2])
if !ok {
return fmt.Errorf("invalid max supply: %q", args[2])
}

msg := types.NewMsgUpdateParamsRequest(
enableGovernance,
unrestrictedDenomRegex,
maxSupply,
authority,
)
return provcli.GenerateOrBroadcastTxCLIAsGovProp(clientCtx, flagSet, msg)
},
}

govcli.AddGovPropFlagsToCmd(cmd)
provcli.AddAuthorityFlagToCmd(cmd)
flags.AddTxFlagsToCmd(cmd)

return cmd
}
14 changes: 14 additions & 0 deletions x/marker/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package keeper
import (
"errors"
"fmt"
"strings"

"cosmossdk.io/log"
storetypes "cosmossdk.io/store/types"
Expand Down Expand Up @@ -203,6 +204,19 @@ func (k Keeper) GetAuthority() string {
return k.authority
}

// IsAuthority returns true if the provided address bech32 string is the authority address.
func (k Keeper) IsAuthority(addr string) bool {
return strings.EqualFold(k.authority, addr)
}

// ValidateAuthority returns an error if the provided address is not the authority.
func (k Keeper) ValidateAuthority(addr string) error {
if !k.IsAuthority(addr) {
return govtypes.ErrInvalidSigner.Wrapf("expected %q got %q", k.GetAuthority(), addr)
}
return nil
}

// IsSendDeny returns true if sender address is denied for marker
func (k Keeper) IsSendDeny(ctx sdk.Context, markerAddr, senderAddr sdk.AccAddress) bool {
store := ctx.KVStore(k.storeKey)
Expand Down
2 changes: 1 addition & 1 deletion x/marker/keeper/marker.go
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,7 @@ func (k Keeper) IncreaseSupply(ctx sdk.Context, marker types.MarkerAccountI, coi

inCirculation := sdk.NewCoin(marker.GetDenom(), k.bankKeeper.GetSupply(ctx, marker.GetDenom()).Amount)
total := inCirculation.Add(coin)
maxAllowed := sdk.NewCoin(marker.GetDenom(), k.GetParams(ctx).MaxSupply)
maxAllowed := sdk.NewCoin(marker.GetDenom(), k.GetMaxSupply(ctx))
if total.Amount.GT(maxAllowed.Amount) {
return fmt.Errorf(
"requested supply %s exceeds maximum allowed value %s", total.Amount.String(), maxAllowed.Amount.String())
Expand Down
16 changes: 16 additions & 0 deletions x/marker/keeper/msg_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -820,3 +820,19 @@ func (k msgServer) SetDenomMetadataProposal(goCtx context.Context, msg *types.Ms

return &types.MsgSetDenomMetadataProposalResponse{}, nil
}

// UpdateParams is a governance proposal endpoint for updating the marker module's params.
func (k msgServer) UpdateParams(goCtx context.Context, msg *types.MsgUpdateParamsRequest) (*types.MsgUpdateParamsResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)

if err := k.ValidateAuthority(msg.Authority); err != nil {
return nil, err
}

k.SetParams(ctx, msg.Params)
if err := ctx.EventManager().EmitTypedEvent(types.NewEventMarkerParamsUpdated(msg.Params.EnableGovernance, msg.Params.GetUnrestrictedDenomRegex(), msg.Params.MaxSupply)); err != nil {
return nil, err
}

return &types.MsgUpdateParamsResponse{}, nil
}
48 changes: 48 additions & 0 deletions x/marker/keeper/msg_server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1845,3 +1845,51 @@ func (s *MsgServerTestSuite) TestSetDenomMetadataProposal() {
})
}
}

func (s *MsgServerTestSuite) TestMsgUpdateParamsRequest() {
authority := s.app.MarkerKeeper.GetAuthority()

testCases := []struct {
name string
msg *types.MsgUpdateParamsRequest
expErr string
}{
{
name: "successfully update params",
msg: &types.MsgUpdateParamsRequest{
Authority: authority,
Params: types.NewParams(
true,
"[a-zA-Z][a-zA-Z0-9\\-\\.]{2,83}",
sdkmath.NewInt(1000000000000),
),
},
},
{
name: "fail to update params, invalid authority",
msg: &types.MsgUpdateParamsRequest{
Authority: "invalidAuthority",
Params: types.NewParams(
true,
"[a-zA-Z][a-zA-Z0-9\\-\\.]{2,83}",
sdkmath.NewInt(1000000000000),
),
},
expErr: `expected "cosmos10d07y265gmmuvt4z0w9aw880jnsr700j6zn9kn" got "invalidAuthority": expected gov account as only signer for proposal message`,
},
}

for _, tc := range testCases {
s.Run(tc.name, func() {
ctx := sdk.WrapSDKContext(s.ctx)
res, err := s.msgServer.UpdateParams(ctx, tc.msg)
if len(tc.expErr) > 0 {
s.Require().EqualError(err, tc.expErr, "UpdateParams error")
s.Require().Nil(res, "UpdateParams response")
} else {
s.Require().NoError(err, "UpdateParams error")
s.Require().NotNil(res, "UpdateParams response")
}
})
}
}
5 changes: 0 additions & 5 deletions x/marker/keeper/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,6 @@ func (k Keeper) SetParams(ctx sdk.Context, params types.Params) {
store.Set(types.MarkerParamStoreKey, bz)
}

// Deprecated: GetMaxTotalSupply is kept for backwards compatibility.
func (k Keeper) GetMaxTotalSupply(ctx sdk.Context) (max uint64) {
return k.GetParams(ctx).MaxTotalSupply
}

// GetMaxSupply returns the current parameter value for the max allowed supply.
func (k Keeper) GetMaxSupply(ctx sdk.Context) (max sdkmath.Int) {
return k.GetParams(ctx).MaxSupply
Expand Down
5 changes: 1 addition & 4 deletions x/marker/keeper/params_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,18 +33,16 @@ func TestParamTestSuite(t *testing.T) {

func (s *ParamTestSuite) TestGetSetParams() {
defaultParams := s.app.MarkerKeeper.GetParams(s.ctx)
s.Require().Equal(types.DefaultMaxTotalSupply, defaultParams.MaxTotalSupply, "Default MaxTotalSupply should match")
s.Require().Equal(uint64(0), defaultParams.MaxTotalSupply, "MaxTotalSupply is deprecated and should not be set")
nullpointer0x00 marked this conversation as resolved.
Show resolved Hide resolved
s.Require().Equal(types.DefaultEnableGovernance, defaultParams.EnableGovernance, "Default EnableGovernance should match")
s.Require().Equal(types.DefaultUnrestrictedDenomRegex, defaultParams.UnrestrictedDenomRegex, "Default UnrestrictedDenomRegex should match")
s.Require().Equal(types.StringToBigInt(types.DefaultMaxSupply), defaultParams.MaxSupply, "Default MaxSupply should match")

newMaxTotalSupply := uint64(2000000)
newEnableGovernance := false
newUnrestrictedDenomRegex := "xyz.*"
newMaxSupply := "3000000"

newParams := types.Params{
MaxTotalSupply: newMaxTotalSupply,
EnableGovernance: newEnableGovernance,
UnrestrictedDenomRegex: newUnrestrictedDenomRegex,
MaxSupply: types.StringToBigInt(newMaxSupply),
Expand All @@ -53,7 +51,6 @@ func (s *ParamTestSuite) TestGetSetParams() {
s.app.MarkerKeeper.SetParams(s.ctx, newParams)

updatedParams := s.app.MarkerKeeper.GetParams(s.ctx)
s.Require().Equal(newMaxTotalSupply, updatedParams.MaxTotalSupply, "Updated MaxTotalSupply should match")
s.Require().Equal(newEnableGovernance, updatedParams.EnableGovernance, "Updated EnableGovernance should match")
s.Require().Equal(newUnrestrictedDenomRegex, updatedParams.UnrestrictedDenomRegex, "Updated UnrestrictedDenomRegex should match")
s.Require().Equal(types.StringToBigInt(newMaxSupply), updatedParams.MaxSupply, "Updated MaxSupply should match")
Expand Down
14 changes: 14 additions & 0 deletions x/marker/spec/07_events.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ The marker module emits the following events:
- [Transfer](#transfer)
- [Set Denom Metadata](#set-denom-metadata)
- [Set Net Asset Value](#set-net-asset-value)
- [Marker Params Updated](#marker-params-updated)



Expand Down Expand Up @@ -216,3 +217,16 @@ Type: `provenance.marker.v1.EventSetNetAssetValue`
| Price | \{token amount the marker is valued at for volume\} |
| Volume | \{total volume/shares associated with price\} |
| Source | \{source address of caller\} |

---
## Marker Params Updated
nullpointer0x00 marked this conversation as resolved.
Show resolved Hide resolved

Fires when an `EventMarkerParamsUpdated` event occurs, indicating that the marker module's parameters have been updated via a governance proposal.

Type: `provenance.marker.v1.EventMarkerParamsUpdated`

| Attribute Key | Attribute Value |
|-------------------------|-----------------------------------------------------|
| EnableGovernance | \{value for if governance control is enabled\} |
| UnrestrictedDenomRegex | \{regex for unrestricted denom validation\} |
| MaxSupply | \{value for the max allowed supply\} |
Loading
Loading