diff --git a/CHANGELOG.md b/CHANGELOG.md index ab51717b08..7d1068cfab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -170,6 +170,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### State Machine Breaking +* (x/gov) [#18146](https://github.com/cosmos/cosmos-sdk/pull/18146) Add denom check to reject denoms outside of those listed in `MinDeposit`. A new `MinDepositRatio` param is added (with a default value of `0.001`) and now deposits are required to be at least `MinDepositRatio*MinDeposit` to be accepted. * (x/group,x/gov) [#16235](https://github.com/cosmos/cosmos-sdk/pull/16235) A group and gov proposal is rejected if the proposal metadata title and summary do not match the proposal title and summary. * (baseapp) [#15930](https://github.com/cosmos/cosmos-sdk/pull/15930) change vote info provided by prepare and process proposal to the one in the block. * (x/staking) [#15731](https://github.com/cosmos/cosmos-sdk/pull/15731) Introducing a new index to retrieve the delegations by validator efficiently. diff --git a/api/cosmos/gov/v1/gov.pulsar.go b/api/cosmos/gov/v1/gov.pulsar.go index 175c72422a..1200fbc1e4 100644 --- a/api/cosmos/gov/v1/gov.pulsar.go +++ b/api/cosmos/gov/v1/gov.pulsar.go @@ -5547,6 +5547,7 @@ var ( fd_Params_burn_vote_quorum protoreflect.FieldDescriptor fd_Params_burn_proposal_deposit_prevote protoreflect.FieldDescriptor fd_Params_burn_vote_veto protoreflect.FieldDescriptor + fd_Params_min_deposit_ratio protoreflect.FieldDescriptor ) func init() { @@ -5567,6 +5568,7 @@ func init() { fd_Params_burn_vote_quorum = md_Params.Fields().ByName("burn_vote_quorum") fd_Params_burn_proposal_deposit_prevote = md_Params.Fields().ByName("burn_proposal_deposit_prevote") fd_Params_burn_vote_veto = md_Params.Fields().ByName("burn_vote_veto") + fd_Params_min_deposit_ratio = md_Params.Fields().ByName("min_deposit_ratio") } var _ protoreflect.Message = (*fastReflection_Params)(nil) @@ -5724,6 +5726,12 @@ func (x *fastReflection_Params) Range(f func(protoreflect.FieldDescriptor, proto return } } + if x.MinDepositRatio != "" { + value := protoreflect.ValueOfString(x.MinDepositRatio) + if !f(fd_Params_min_deposit_ratio, value) { + return + } + } } // Has reports whether a field is populated. @@ -5769,6 +5777,8 @@ func (x *fastReflection_Params) Has(fd protoreflect.FieldDescriptor) bool { return x.BurnProposalDepositPrevote != false case "cosmos.gov.v1.Params.burn_vote_veto": return x.BurnVoteVeto != false + case "cosmos.gov.v1.Params.min_deposit_ratio": + return x.MinDepositRatio != "" default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.gov.v1.Params")) @@ -5815,6 +5825,8 @@ func (x *fastReflection_Params) Clear(fd protoreflect.FieldDescriptor) { x.BurnProposalDepositPrevote = false case "cosmos.gov.v1.Params.burn_vote_veto": x.BurnVoteVeto = false + case "cosmos.gov.v1.Params.min_deposit_ratio": + x.MinDepositRatio = "" default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.gov.v1.Params")) @@ -5882,6 +5894,9 @@ func (x *fastReflection_Params) Get(descriptor protoreflect.FieldDescriptor) pro case "cosmos.gov.v1.Params.burn_vote_veto": value := x.BurnVoteVeto return protoreflect.ValueOfBool(value) + case "cosmos.gov.v1.Params.min_deposit_ratio": + value := x.MinDepositRatio + return protoreflect.ValueOfString(value) default: if descriptor.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.gov.v1.Params")) @@ -5936,6 +5951,8 @@ func (x *fastReflection_Params) Set(fd protoreflect.FieldDescriptor, value proto x.BurnProposalDepositPrevote = value.Bool() case "cosmos.gov.v1.Params.burn_vote_veto": x.BurnVoteVeto = value.Bool() + case "cosmos.gov.v1.Params.min_deposit_ratio": + x.MinDepositRatio = value.Interface().(string) default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.gov.v1.Params")) @@ -6003,6 +6020,8 @@ func (x *fastReflection_Params) Mutable(fd protoreflect.FieldDescriptor) protore panic(fmt.Errorf("field burn_proposal_deposit_prevote of message cosmos.gov.v1.Params is not mutable")) case "cosmos.gov.v1.Params.burn_vote_veto": panic(fmt.Errorf("field burn_vote_veto of message cosmos.gov.v1.Params is not mutable")) + case "cosmos.gov.v1.Params.min_deposit_ratio": + panic(fmt.Errorf("field min_deposit_ratio of message cosmos.gov.v1.Params is not mutable")) default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.gov.v1.Params")) @@ -6051,6 +6070,8 @@ func (x *fastReflection_Params) NewField(fd protoreflect.FieldDescriptor) protor return protoreflect.ValueOfBool(false) case "cosmos.gov.v1.Params.burn_vote_veto": return protoreflect.ValueOfBool(false) + case "cosmos.gov.v1.Params.min_deposit_ratio": + return protoreflect.ValueOfString("") default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.gov.v1.Params")) @@ -6181,6 +6202,10 @@ func (x *fastReflection_Params) ProtoMethods() *protoiface.Methods { if x.BurnVoteVeto { n += 2 } + l = len(x.MinDepositRatio) + if l > 0 { + n += 2 + l + runtime.Sov(uint64(l)) + } if x.unknownFields != nil { n += len(x.unknownFields) } @@ -6210,6 +6235,15 @@ func (x *fastReflection_Params) ProtoMethods() *protoiface.Methods { i -= len(x.unknownFields) copy(dAtA[i:], x.unknownFields) } + if len(x.MinDepositRatio) > 0 { + i -= len(x.MinDepositRatio) + copy(dAtA[i:], x.MinDepositRatio) + i = runtime.EncodeVarint(dAtA, i, uint64(len(x.MinDepositRatio))) + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0x82 + } if x.BurnVoteVeto { i-- if x.BurnVoteVeto { @@ -6872,6 +6906,38 @@ func (x *fastReflection_Params) ProtoMethods() *protoiface.Methods { } } x.BurnVoteVeto = bool(v != 0) + case 16: + if wireType != 2 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field MinDepositRatio", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if postIndex > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + x.MinDepositRatio = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex default: iNdEx = preIndex skippy, err := runtime.Skip(dAtA[iNdEx:]) @@ -7659,6 +7725,12 @@ type Params struct { BurnProposalDepositPrevote bool `protobuf:"varint,14,opt,name=burn_proposal_deposit_prevote,json=burnProposalDepositPrevote,proto3" json:"burn_proposal_deposit_prevote,omitempty"` // burn deposits if quorum with vote type no_veto is met BurnVoteVeto bool `protobuf:"varint,15,opt,name=burn_vote_veto,json=burnVoteVeto,proto3" json:"burn_vote_veto,omitempty"` + // The ratio representing the proportion of the deposit value minimum that must be met when making a deposit. + // Default value: 0.01. Meaning that for a chain with a min_deposit of 100stake, a deposit of 1stake would be + // required. + // + // Since: cosmos-sdk 0.50 + MinDepositRatio string `protobuf:"bytes,16,opt,name=min_deposit_ratio,json=minDepositRatio,proto3" json:"min_deposit_ratio,omitempty"` } func (x *Params) Reset() { @@ -7786,6 +7858,13 @@ func (x *Params) GetBurnVoteVeto() bool { return false } +func (x *Params) GetMinDepositRatio() string { + if x != nil { + return x.MinDepositRatio + } + return "" +} + var File_cosmos_gov_v1_gov_proto protoreflect.FileDescriptor var file_cosmos_gov_v1_gov_proto_rawDesc = []byte{ @@ -7924,7 +8003,7 @@ var file_cosmos_gov_v1_gov_proto_rawDesc = []byte{ 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x0e, 0xd2, 0xb4, 0x2d, 0x0a, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x44, 0x65, 0x63, 0x52, 0x0d, 0x76, 0x65, 0x74, 0x6f, 0x54, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x3a, 0x02, 0x18, - 0x01, 0x22, 0xd3, 0x07, 0x0a, 0x06, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x45, 0x0a, 0x0b, + 0x01, 0x22, 0x8f, 0x08, 0x0a, 0x06, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x45, 0x0a, 0x0b, 0x6d, 0x69, 0x6e, 0x5f, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x42, 0x09, 0xc8, 0xde, @@ -7985,39 +8064,43 @@ var file_cosmos_gov_v1_gov_proto_rawDesc = []byte{ 0x73, 0x61, 0x6c, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x50, 0x72, 0x65, 0x76, 0x6f, 0x74, 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x62, 0x75, 0x72, 0x6e, 0x5f, 0x76, 0x6f, 0x74, 0x65, 0x5f, 0x76, 0x65, 0x74, 0x6f, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x62, 0x75, 0x72, 0x6e, 0x56, - 0x6f, 0x74, 0x65, 0x56, 0x65, 0x74, 0x6f, 0x2a, 0x89, 0x01, 0x0a, 0x0a, 0x56, 0x6f, 0x74, 0x65, - 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1b, 0x0a, 0x17, 0x56, 0x4f, 0x54, 0x45, 0x5f, 0x4f, - 0x50, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, - 0x44, 0x10, 0x00, 0x12, 0x13, 0x0a, 0x0f, 0x56, 0x4f, 0x54, 0x45, 0x5f, 0x4f, 0x50, 0x54, 0x49, - 0x4f, 0x4e, 0x5f, 0x59, 0x45, 0x53, 0x10, 0x01, 0x12, 0x17, 0x0a, 0x13, 0x56, 0x4f, 0x54, 0x45, - 0x5f, 0x4f, 0x50, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x41, 0x42, 0x53, 0x54, 0x41, 0x49, 0x4e, 0x10, - 0x02, 0x12, 0x12, 0x0a, 0x0e, 0x56, 0x4f, 0x54, 0x45, 0x5f, 0x4f, 0x50, 0x54, 0x49, 0x4f, 0x4e, - 0x5f, 0x4e, 0x4f, 0x10, 0x03, 0x12, 0x1c, 0x0a, 0x18, 0x56, 0x4f, 0x54, 0x45, 0x5f, 0x4f, 0x50, - 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x4e, 0x4f, 0x5f, 0x57, 0x49, 0x54, 0x48, 0x5f, 0x56, 0x45, 0x54, - 0x4f, 0x10, 0x04, 0x2a, 0xce, 0x01, 0x0a, 0x0e, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, - 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1f, 0x0a, 0x1b, 0x50, 0x52, 0x4f, 0x50, 0x4f, 0x53, - 0x41, 0x4c, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, - 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x22, 0x0a, 0x1e, 0x50, 0x52, 0x4f, 0x50, 0x4f, - 0x53, 0x41, 0x4c, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x44, 0x45, 0x50, 0x4f, 0x53, - 0x49, 0x54, 0x5f, 0x50, 0x45, 0x52, 0x49, 0x4f, 0x44, 0x10, 0x01, 0x12, 0x21, 0x0a, 0x1d, 0x50, - 0x52, 0x4f, 0x50, 0x4f, 0x53, 0x41, 0x4c, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x56, - 0x4f, 0x54, 0x49, 0x4e, 0x47, 0x5f, 0x50, 0x45, 0x52, 0x49, 0x4f, 0x44, 0x10, 0x02, 0x12, 0x1a, - 0x0a, 0x16, 0x50, 0x52, 0x4f, 0x50, 0x4f, 0x53, 0x41, 0x4c, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, - 0x53, 0x5f, 0x50, 0x41, 0x53, 0x53, 0x45, 0x44, 0x10, 0x03, 0x12, 0x1c, 0x0a, 0x18, 0x50, 0x52, - 0x4f, 0x50, 0x4f, 0x53, 0x41, 0x4c, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x52, 0x45, - 0x4a, 0x45, 0x43, 0x54, 0x45, 0x44, 0x10, 0x04, 0x12, 0x1a, 0x0a, 0x16, 0x50, 0x52, 0x4f, 0x50, - 0x4f, 0x53, 0x41, 0x4c, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x46, 0x41, 0x49, 0x4c, - 0x45, 0x44, 0x10, 0x05, 0x42, 0x99, 0x01, 0x0a, 0x11, 0x63, 0x6f, 0x6d, 0x2e, 0x63, 0x6f, 0x73, - 0x6d, 0x6f, 0x73, 0x2e, 0x67, 0x6f, 0x76, 0x2e, 0x76, 0x31, 0x42, 0x08, 0x47, 0x6f, 0x76, 0x50, - 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x24, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, - 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, - 0x67, 0x6f, 0x76, 0x2f, 0x76, 0x31, 0x3b, 0x67, 0x6f, 0x76, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x43, - 0x47, 0x58, 0xaa, 0x02, 0x0d, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x47, 0x6f, 0x76, 0x2e, - 0x56, 0x31, 0xca, 0x02, 0x0d, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x5c, 0x47, 0x6f, 0x76, 0x5c, - 0x56, 0x31, 0xe2, 0x02, 0x19, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x5c, 0x47, 0x6f, 0x76, 0x5c, - 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, - 0x0f, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x3a, 0x3a, 0x47, 0x6f, 0x76, 0x3a, 0x3a, 0x56, 0x31, - 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x6f, 0x74, 0x65, 0x56, 0x65, 0x74, 0x6f, 0x12, 0x3a, 0x0a, 0x11, 0x6d, 0x69, 0x6e, 0x5f, 0x64, + 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x5f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x18, 0x10, 0x20, 0x01, + 0x28, 0x09, 0x42, 0x0e, 0xd2, 0xb4, 0x2d, 0x0a, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x44, + 0x65, 0x63, 0x52, 0x0f, 0x6d, 0x69, 0x6e, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x52, 0x61, + 0x74, 0x69, 0x6f, 0x2a, 0x89, 0x01, 0x0a, 0x0a, 0x56, 0x6f, 0x74, 0x65, 0x4f, 0x70, 0x74, 0x69, + 0x6f, 0x6e, 0x12, 0x1b, 0x0a, 0x17, 0x56, 0x4f, 0x54, 0x45, 0x5f, 0x4f, 0x50, 0x54, 0x49, 0x4f, + 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, + 0x13, 0x0a, 0x0f, 0x56, 0x4f, 0x54, 0x45, 0x5f, 0x4f, 0x50, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x59, + 0x45, 0x53, 0x10, 0x01, 0x12, 0x17, 0x0a, 0x13, 0x56, 0x4f, 0x54, 0x45, 0x5f, 0x4f, 0x50, 0x54, + 0x49, 0x4f, 0x4e, 0x5f, 0x41, 0x42, 0x53, 0x54, 0x41, 0x49, 0x4e, 0x10, 0x02, 0x12, 0x12, 0x0a, + 0x0e, 0x56, 0x4f, 0x54, 0x45, 0x5f, 0x4f, 0x50, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x4e, 0x4f, 0x10, + 0x03, 0x12, 0x1c, 0x0a, 0x18, 0x56, 0x4f, 0x54, 0x45, 0x5f, 0x4f, 0x50, 0x54, 0x49, 0x4f, 0x4e, + 0x5f, 0x4e, 0x4f, 0x5f, 0x57, 0x49, 0x54, 0x48, 0x5f, 0x56, 0x45, 0x54, 0x4f, 0x10, 0x04, 0x2a, + 0xce, 0x01, 0x0a, 0x0e, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x53, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x12, 0x1f, 0x0a, 0x1b, 0x50, 0x52, 0x4f, 0x50, 0x4f, 0x53, 0x41, 0x4c, 0x5f, 0x53, + 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, + 0x44, 0x10, 0x00, 0x12, 0x22, 0x0a, 0x1e, 0x50, 0x52, 0x4f, 0x50, 0x4f, 0x53, 0x41, 0x4c, 0x5f, + 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x44, 0x45, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x5f, 0x50, + 0x45, 0x52, 0x49, 0x4f, 0x44, 0x10, 0x01, 0x12, 0x21, 0x0a, 0x1d, 0x50, 0x52, 0x4f, 0x50, 0x4f, + 0x53, 0x41, 0x4c, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x56, 0x4f, 0x54, 0x49, 0x4e, + 0x47, 0x5f, 0x50, 0x45, 0x52, 0x49, 0x4f, 0x44, 0x10, 0x02, 0x12, 0x1a, 0x0a, 0x16, 0x50, 0x52, + 0x4f, 0x50, 0x4f, 0x53, 0x41, 0x4c, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x50, 0x41, + 0x53, 0x53, 0x45, 0x44, 0x10, 0x03, 0x12, 0x1c, 0x0a, 0x18, 0x50, 0x52, 0x4f, 0x50, 0x4f, 0x53, + 0x41, 0x4c, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x52, 0x45, 0x4a, 0x45, 0x43, 0x54, + 0x45, 0x44, 0x10, 0x04, 0x12, 0x1a, 0x0a, 0x16, 0x50, 0x52, 0x4f, 0x50, 0x4f, 0x53, 0x41, 0x4c, + 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x45, 0x44, 0x10, 0x05, + 0x42, 0x99, 0x01, 0x0a, 0x11, 0x63, 0x6f, 0x6d, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, + 0x67, 0x6f, 0x76, 0x2e, 0x76, 0x31, 0x42, 0x08, 0x47, 0x6f, 0x76, 0x50, 0x72, 0x6f, 0x74, 0x6f, + 0x50, 0x01, 0x5a, 0x24, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, + 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x67, 0x6f, 0x76, 0x2f, + 0x76, 0x31, 0x3b, 0x67, 0x6f, 0x76, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x43, 0x47, 0x58, 0xaa, 0x02, + 0x0d, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x47, 0x6f, 0x76, 0x2e, 0x56, 0x31, 0xca, 0x02, + 0x0d, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x5c, 0x47, 0x6f, 0x76, 0x5c, 0x56, 0x31, 0xe2, 0x02, + 0x19, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x5c, 0x47, 0x6f, 0x76, 0x5c, 0x56, 0x31, 0x5c, 0x47, + 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x0f, 0x43, 0x6f, 0x73, + 0x6d, 0x6f, 0x73, 0x3a, 0x3a, 0x47, 0x6f, 0x76, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/proto/cosmos/gov/v1/gov.proto b/proto/cosmos/gov/v1/gov.proto index c6ec98a414..0ebfbc1d1f 100644 --- a/proto/cosmos/gov/v1/gov.proto +++ b/proto/cosmos/gov/v1/gov.proto @@ -261,4 +261,11 @@ message Params { // burn deposits if quorum with vote type no_veto is met bool burn_vote_veto = 15; + + // The ratio representing the proportion of the deposit value minimum that must be met when making a deposit. + // Default value: 0.01. Meaning that for a chain with a min_deposit of 100stake, a deposit of 1stake would be + // required. + // + // Since: cosmos-sdk 0.50 + string min_deposit_ratio = 16 [(cosmos_proto.scalar) = "cosmos.Dec"]; } diff --git a/tests/e2e/gov/deposits.go b/tests/e2e/gov/deposits.go index ee291abae2..9a4a1b34a8 100644 --- a/tests/e2e/gov/deposits.go +++ b/tests/e2e/gov/deposits.go @@ -71,33 +71,6 @@ func (s *DepositTestSuite) TearDownSuite() { s.network.Cleanup() } -func (s *DepositTestSuite) TestQueryDepositsWithoutInitialDeposit() { - val := s.network.Validators[0] - clientCtx := val.ClientCtx - - // submit proposal without initial deposit - id := s.submitProposal(val, sdk.NewCoin(s.cfg.BondDenom, math.NewInt(0)), "TestQueryDepositsWithoutInitialDeposit") - proposalID := strconv.FormatUint(id, 10) - - // deposit amount - depositAmount := sdk.NewCoin(s.cfg.BondDenom, v1.DefaultMinDepositTokens.Add(math.NewInt(50))).String() - _, err := govclitestutil.MsgDeposit(clientCtx, val.Address.String(), proposalID, depositAmount) - s.Require().NoError(err) - s.Require().NoError(s.network.WaitForNextBlock()) - - // query deposit - deposit := s.queryDeposit(val, proposalID, false, "") - s.Require().NotNil(deposit) - s.Require().Equal(depositAmount, sdk.Coins(deposit.Deposit.Amount).String()) - - // query deposits - deposits := s.queryDeposits(val, proposalID, false, "") - s.Require().NotNil(deposits) - s.Require().Len(deposits.Deposits, 1) - // verify initial deposit - s.Require().Equal(depositAmount, sdk.Coins(deposits.Deposits[0].Amount).String()) -} - func (s *DepositTestSuite) TestQueryDepositsWithInitialDeposit() { val := s.network.Validators[0] depositAmount := sdk.NewCoin(s.cfg.BondDenom, v1.DefaultMinDepositTokens) diff --git a/tests/e2e/gov/tx.go b/tests/e2e/gov/tx.go index 8c37f1342f..5bcff67937 100644 --- a/tests/e2e/gov/tx.go +++ b/tests/e2e/gov/tx.go @@ -60,9 +60,12 @@ func (s *E2ETestSuite) SetupSuite() { s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &resp), out.String()) s.Require().NoError(clitestutil.CheckTxCode(s.network, clientCtx, resp.TxHash, 0)) - // create a proposal without deposit + // create a proposal with a small deposit + minimumAcceptedDep := v1.DefaultMinDepositTokens.ToLegacyDec().Mul(v1.DefaultMinDepositRatio).Ceil().TruncateInt() out, err = govclitestutil.MsgSubmitLegacyProposal(val.ClientCtx, val.Address.String(), - "Text Proposal 2", "Where is the title!?", v1beta1.ProposalTypeText) + "Text Proposal 2", "Where is the title!?", v1beta1.ProposalTypeText, + fmt.Sprintf("--%s=%s", cli.FlagDeposit, sdk.NewCoin(s.cfg.BondDenom, minimumAcceptedDep).String())) + s.Require().NoError(err) s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &resp), out.String()) s.Require().NoError(clitestutil.CheckTxCode(s.network, clientCtx, resp.TxHash, 0)) @@ -128,7 +131,7 @@ func (s *E2ETestSuite) TestNewCmdSubmitProposal() { "summary": "My awesome description", "metadata": "%s", "deposit": "%s" -}`, authtypes.NewModuleAddress(types.ModuleName), base64.StdEncoding.EncodeToString(propMetadata), sdk.NewCoin(s.cfg.BondDenom, math.NewInt(5431))) +}`, authtypes.NewModuleAddress(types.ModuleName), base64.StdEncoding.EncodeToString(propMetadata), sdk.NewCoin(s.cfg.BondDenom, math.NewInt(100000))) validPropFile := testutil.WriteToNewTempFile(s.T(), validProp) defer validPropFile.Close() @@ -196,7 +199,7 @@ func (s *E2ETestSuite) TestNewCmdSubmitLegacyProposal() { "description": "Hello, World!", "type": "Text", "deposit": "%s" - }`, sdk.NewCoin(s.cfg.BondDenom, math.NewInt(5431))) + }`, sdk.NewCoin(s.cfg.BondDenom, math.NewInt(154310))) validPropFile := testutil.WriteToNewTempFile(s.T(), validProp) defer validPropFile.Close() @@ -222,7 +225,7 @@ func (s *E2ETestSuite) TestNewCmdSubmitLegacyProposal() { []string{ fmt.Sprintf("--%s='Where is the title!?'", cli.FlagDescription), //nolint:staticcheck // we are intentionally using a deprecated flag here. fmt.Sprintf("--%s=%s", cli.FlagProposalType, v1beta1.ProposalTypeText), //nolint:staticcheck // we are intentionally using a deprecated flag here. - fmt.Sprintf("--%s=%s", cli.FlagDeposit, sdk.NewCoin(s.cfg.BondDenom, math.NewInt(5431)).String()), + fmt.Sprintf("--%s=%s", cli.FlagDeposit, sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10000)).String()), fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), @@ -247,7 +250,7 @@ func (s *E2ETestSuite) TestNewCmdSubmitLegacyProposal() { fmt.Sprintf("--%s='Text Proposal'", cli.FlagTitle), fmt.Sprintf("--%s='Where is the title!?'", cli.FlagDescription), //nolint:staticcheck // we are intentionally using a deprecated flag here. fmt.Sprintf("--%s=%s", cli.FlagProposalType, v1beta1.ProposalTypeText), //nolint:staticcheck // we are intentionally using a deprecated flag here. - fmt.Sprintf("--%s=%s", cli.FlagDeposit, sdk.NewCoin(s.cfg.BondDenom, math.NewInt(5431)).String()), + fmt.Sprintf("--%s=%s", cli.FlagDeposit, sdk.NewCoin(s.cfg.BondDenom, math.NewInt(100000)).String()), fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), @@ -388,84 +391,6 @@ func (s *E2ETestSuite) TestNewCmdCancelProposal() { } } -func (s *E2ETestSuite) TestNewCmdDeposit() { - val := s.network.Validators[0] - - testCases := []struct { - name string - args []string - expectErr bool - expectedCode uint32 - }{ - { - "without proposal id", - []string{ - sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10)).String(), // 10stake - fmt.Sprintf("--%s=%s", flags.FlagFrom, val.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.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - }, - true, 0, - }, - { - "without deposit amount", - []string{ - "1", - fmt.Sprintf("--%s=%s", flags.FlagFrom, val.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.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - }, - true, 0, - }, - { - "deposit on non existing proposal", - []string{ - "10", - sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10)).String(), // 10stake - fmt.Sprintf("--%s=%s", flags.FlagFrom, val.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.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - }, - false, 1, - }, - { - "deposit on existing proposal", - []string{ - "1", - sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10)).String(), // 10stake - fmt.Sprintf("--%s=%s", flags.FlagFrom, val.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.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - }, - false, 0, - }, - } - - for _, tc := range testCases { - tc := tc - var resp sdk.TxResponse - - s.Run(tc.name, func() { - cmd := cli.NewCmdDeposit() - clientCtx := val.ClientCtx - - out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) - if tc.expectErr { - s.Require().Error(err) - } else { - s.Require().NoError(err) - - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &resp), out.String()) - s.Require().NoError(clitestutil.CheckTxCode(s.network, clientCtx, resp.TxHash, tc.expectedCode)) - } - }) - } -} - func (s *E2ETestSuite) TestNewCmdVote() { val := s.network.Validators[0] diff --git a/x/bank/app_test.go b/x/bank/app_test.go index b00b67cd6a..2099b5981f 100644 --- a/x/bank/app_test.go +++ b/x/bank/app_test.go @@ -371,14 +371,15 @@ func TestMsgSetSendEnabled(t *testing.T) { s := createTestSuite(t, genAccs) ctx := s.App.BaseApp.NewContext(false) - require.NoError(t, testutil.FundAccount(ctx, s.BankKeeper, addr1, sdk.NewCoins(sdk.NewInt64Coin("stake", 101)))) + require.NoError(t, testutil.FundAccount(ctx, s.BankKeeper, addr1, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 101)))) + require.NoError(t, testutil.FundAccount(ctx, s.BankKeeper, addr1, sdk.NewCoins(sdk.NewInt64Coin("stake", 100000)))) addr1Str := addr1.String() govAddr := s.BankKeeper.GetAuthority() goodGovProp, err := govv1.NewMsgSubmitProposal( []sdk.Msg{ types.NewMsgSetSendEnabled(govAddr, nil, nil), }, - sdk.Coins{{Denom: "stake", Amount: sdkmath.NewInt(5)}}, + sdk.Coins{{Denom: "stake", Amount: sdkmath.NewInt(100000)}}, addr1Str, "set default send enabled to true", "Change send enabled", diff --git a/x/bank/migrations/v4/gen_state_test.go b/x/bank/migrations/v4/gen_state_test.go index 3cbd40b86e..1283e65b78 100644 --- a/x/bank/migrations/v4/gen_state_test.go +++ b/x/bank/migrations/v4/gen_state_test.go @@ -156,6 +156,6 @@ func TestMigrateGenState(t *testing.T) { }, } _ = v4.MigrateGenState(&origState) - assert.Len(t, origState.Params.SendEnabled, 2) //nolint:staticcheck // keep for test + assert.Len(t, origState.Params.SendEnabled, 2) //nolint:staticcheck // keep for test (linter sometimes fails) }) } diff --git a/x/gov/abci_test.go b/x/gov/abci_test.go index 8601839414..6c8a009fa2 100644 --- a/x/gov/abci_test.go +++ b/x/gov/abci_test.go @@ -98,7 +98,7 @@ func TestTickExpiredDepositPeriod(t *testing.T) { newProposalMsg, err := v1.NewMsgSubmitProposal( []sdk.Msg{mkTestLegacyContent(t)}, - sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, 5)}, + sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, 100000)}, addrs[0].String(), "", "Proposal", @@ -149,7 +149,7 @@ func TestTickMultipleExpiredDepositPeriod(t *testing.T) { newProposalMsg, err := v1.NewMsgSubmitProposal( []sdk.Msg{mkTestLegacyContent(t)}, - sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, 5)}, + sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, 100000)}, addrs[0].String(), "", "Proposal", @@ -172,7 +172,7 @@ func TestTickMultipleExpiredDepositPeriod(t *testing.T) { newProposalMsg2, err := v1.NewMsgSubmitProposal( []sdk.Msg{mkTestLegacyContent(t)}, - sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, 5)}, + sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, 100000)}, addrs[0].String(), "", "Proposal", @@ -218,7 +218,7 @@ func TestTickPassedDepositPeriod(t *testing.T) { newProposalMsg, err := v1.NewMsgSubmitProposal( []sdk.Msg{mkTestLegacyContent(t)}, - sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, 5)}, + sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, 100000)}, addrs[0].String(), "", "Proposal", @@ -241,7 +241,7 @@ func TestTickPassedDepositPeriod(t *testing.T) { checkInactiveProposalsQueue(t, ctx, suite.GovKeeper) - newDepositMsg := v1.NewMsgDeposit(addrs[1], proposalID, sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, 5)}) + newDepositMsg := v1.NewMsgDeposit(addrs[1], proposalID, sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, 100000)}) res1, err := govMsgSvr.Deposit(ctx, newDepositMsg) require.NoError(t, err) diff --git a/x/gov/keeper/deposit.go b/x/gov/keeper/deposit.go index 4b45ce628a..9693c5168e 100644 --- a/x/gov/keeper/deposit.go +++ b/x/gov/keeper/deposit.go @@ -3,12 +3,14 @@ package keeper import ( "context" "fmt" + "strings" "cosmossdk.io/collections" "cosmossdk.io/errors" sdkmath "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" disttypes "github.com/cosmos/cosmos-sdk/x/distribution/types" "github.com/cosmos/cosmos-sdk/x/gov/types" v1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1" @@ -76,10 +78,48 @@ func (keeper Keeper) AddDeposit(ctx context.Context, proposalID uint64, deposito return false, err } + minDepositAmount := proposal.GetMinDepositFromParams(params) + minDepositRatio, err := sdkmath.LegacyNewDecFromStr(params.GetMinDepositRatio()) + if err != nil { + return false, err + } + + // the deposit must only contain valid denoms (listed in the min deposit param) if err := keeper.validateDepositDenom(ctx, params, depositAmount); err != nil { return false, err } + // If minDepositRatio is set, the deposit must be equal or greater than minDepositAmount*minDepositRatio + // for at least one denom. If minDepositRatio is zero we skip this check. + if !minDepositRatio.IsZero() { + var ( + depositThresholdMet bool + thresholds []string + ) + for _, minDep := range minDepositAmount { + // calculate the threshold for this denom, and hold a list to later return a useful error message + threshold := sdk.NewCoin(minDep.GetDenom(), minDep.Amount.ToLegacyDec().Mul(minDepositRatio).TruncateInt()) + thresholds = append(thresholds, threshold.String()) + + found, deposit := depositAmount.Find(minDep.Denom) + if !found { // if not found, continue, as we know the deposit contains at least 1 valid denom + continue + } + + // Once we know at least one threshold has been met, we can break. The deposit + // might contain other denoms but we don't care. + if deposit.IsGTE(threshold) { + depositThresholdMet = true + break + } + } + + // the threshold must be met with at least one denom, if not, return the list of minimum deposits + if !depositThresholdMet { + return false, errors.Wrapf(types.ErrMinDepositTooSmall, "received %s but need at least one of the following: %s", depositAmount, strings.Join(thresholds, ",")) + } + } + // update the governance module's account coins pool err = keeper.bankKeeper.SendCoinsFromAccountToModule(ctx, depositorAddr, types.ModuleName, depositAmount) if err != nil { @@ -94,8 +134,6 @@ func (keeper Keeper) AddDeposit(ctx context.Context, proposalID uint64, deposito } // Check if deposit has provided sufficient total funds to transition the proposal into the voting period - minDepositAmount := proposal.GetMinDepositFromParams(params) - activatedVotingPeriod := false if proposal.Status == v1.StatusDepositPeriod && sdk.NewCoins(proposal.TotalDeposit...).IsAllGTE(minDepositAmount) { err = keeper.ActivateVotingPeriod(ctx, proposal) @@ -244,6 +282,10 @@ func (keeper Keeper) RefundAndDeleteDeposits(ctx context.Context, proposalID uin // required at the time of proposal submission. This threshold amount is determined by // the deposit parameters. Returns nil on success, error otherwise. func (keeper Keeper) validateInitialDeposit(ctx context.Context, params v1.Params, initialDeposit sdk.Coins, expedited bool) error { + if !initialDeposit.IsValid() || initialDeposit.IsAnyNegative() { + return errors.Wrap(sdkerrors.ErrInvalidCoins, initialDeposit.String()) + } + minInitialDepositRatio, err := sdkmath.LegacyNewDecFromStr(params.MinInitialDepositRatio) if err != nil { return err @@ -279,7 +321,7 @@ func (keeper Keeper) validateDepositDenom(ctx context.Context, params v1.Params, for _, coin := range depositAmount { if _, ok := acceptedDenoms[coin.Denom]; !ok { - return errors.Wrapf(types.ErrInvalidDepositDenom, "deposited %s, but gov accepts only the following denom(s): %v", coin, denoms) + return errors.Wrapf(types.ErrInvalidDepositDenom, "deposited %s, but gov accepts only the following denom(s): %v", depositAmount, denoms) } } diff --git a/x/gov/keeper/deposit_test.go b/x/gov/keeper/deposit_test.go index ddbd7e5d86..4438bc494d 100644 --- a/x/gov/keeper/deposit_test.go +++ b/x/gov/keeper/deposit_test.go @@ -156,6 +156,85 @@ func TestDeposits(t *testing.T) { } } +func TestDepositAmount(t *testing.T) { + testcases := []struct { + name string + deposit sdk.Coins + minDepositRatio string + err string + }{ + { + name: "good amount and denoms", + deposit: sdk.NewCoins(sdk.NewInt64Coin("stake", 10000)), + minDepositRatio: "0.001", + }, + { + name: "good amount and denoms but not enough balance for zcoin", + deposit: sdk.NewCoins(sdk.NewInt64Coin("stake", 10000), sdk.NewInt64Coin("zcoin", 1)), + minDepositRatio: "0.001", + err: "not enough balance", + }, + { + name: "too small amount", + deposit: sdk.NewCoins(sdk.NewInt64Coin("stake", 10)), + minDepositRatio: "0.001", + err: "received 10stake but need at least one of the following: 10000stake,10zcoin: minimum deposit is too small", + }, + { + name: "too small amount with another coin", + deposit: sdk.NewCoins(sdk.NewInt64Coin("zcoin", 1)), + minDepositRatio: "0.001", + err: "received 1zcoin but need at least one of the following: 10000stake,10zcoin: minimum deposit is too small", + }, + { + name: "bad denom", + deposit: sdk.NewCoins(sdk.NewInt64Coin("euro", 10000)), + minDepositRatio: "0.001", + err: "deposited 10000euro, but gov accepts only the following denom(s): [stake zcoin]: invalid deposit denom", + }, + { + name: "mix containing bad and good denom", + deposit: sdk.NewCoins(sdk.NewInt64Coin("stake", 10000), sdk.NewInt64Coin("euro", 10000)), + minDepositRatio: "0.001", + err: "deposited 10000euro,10000stake, but gov accepts only the following denom(s): [stake zcoin]: invalid deposit denom", + }, + { + name: "minDepositRatio is zero", + deposit: sdk.NewCoins(sdk.NewInt64Coin("stake", 10)), + minDepositRatio: "0.0", + }, + } + + for _, tc := range testcases { + t.Run(tc.name, func(t *testing.T) { + govKeeper, authKeeper, bankKeeper, stakingKeeper, distrKeeper, _, ctx := setupGovKeeper(t) + trackMockBalances(bankKeeper, distrKeeper) + + testAddrs := simtestutil.AddTestAddrsIncremental(bankKeeper, stakingKeeper, ctx, 2, sdkmath.NewInt(1000000000000000)) + authKeeper.EXPECT().AddressCodec().Return(address.NewBech32Codec("cosmos")).AnyTimes() + + params, _ := govKeeper.Params.Get(ctx) + params.MinDepositRatio = tc.minDepositRatio + params.MinDeposit = sdk.NewCoins(params.MinDeposit...).Add(sdk.NewCoin("zcoin", sdkmath.NewInt(10000))) // coins must be sorted by denom + err := govKeeper.Params.Set(ctx, params) + require.NoError(t, err) + + tp := TestProposal + proposal, err := govKeeper.SubmitProposal(ctx, tp, "", "title", "summary", testAddrs[0], false) + require.NoError(t, err) + proposalID := proposal.Id + + _, err = govKeeper.AddDeposit(ctx, proposalID, testAddrs[0], tc.deposit) + if tc.err != "" { + require.Error(t, err) + require.Equal(t, tc.err, err.Error()) + } else { + require.NoError(t, err) + } + }) + } +} + func TestValidateInitialDeposit(t *testing.T) { testcases := map[string]struct { minDeposit sdk.Coins diff --git a/x/gov/keeper/msg_server.go b/x/gov/keeper/msg_server.go index d833d46108..875b491369 100644 --- a/x/gov/keeper/msg_server.go +++ b/x/gov/keeper/msg_server.go @@ -41,10 +41,6 @@ func (k msgServer) SubmitProposal(goCtx context.Context, msg *v1.MsgSubmitPropos return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid proposer address: %s", err) } - if err := validateDeposit(sdk.NewCoins(msg.InitialDeposit...)); err != nil { - return nil, err - } - // check that either metadata or Msgs length is non nil. if len(msg.Messages) == 0 && len(msg.Metadata) == 0 { return nil, errors.Wrap(govtypes.ErrNoProposalMsgs, "either metadata or Msgs length must be non-nil") @@ -248,7 +244,7 @@ func (k msgServer) Deposit(goCtx context.Context, msg *v1.MsgDeposit) (*v1.MsgDe return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid depositor address: %s", err) } - if err := validateAmount(sdk.NewCoins(msg.Amount...)); err != nil { + if err := validateDeposit(msg.Amount); err != nil { return nil, err } @@ -383,26 +379,11 @@ func (k legacyMsgServer) Deposit(goCtx context.Context, msg *v1beta1.MsgDeposit) return &v1beta1.MsgDepositResponse{}, nil } -func validateAmount(amount sdk.Coins) error { - if !amount.IsValid() { - return sdkerrors.ErrInvalidCoins.Wrap(amount.String()) - } - - if !amount.IsAllPositive() { +// validateDeposit validates the deposit amount, do not use for initial deposit. +func validateDeposit(amount sdk.Coins) error { + if !amount.IsValid() || !amount.IsAllPositive() { return sdkerrors.ErrInvalidCoins.Wrap(amount.String()) } return nil } - -func validateDeposit(deposit sdk.Coins) error { - if !deposit.IsValid() { - return errors.Wrap(sdkerrors.ErrInvalidCoins, deposit.String()) - } - - if deposit.IsAnyNegative() { - return errors.Wrap(sdkerrors.ErrInvalidCoins, deposit.String()) - } - - return nil -} diff --git a/x/gov/keeper/msg_server_test.go b/x/gov/keeper/msg_server_test.go index b30dd2559b..7274ba89cd 100644 --- a/x/gov/keeper/msg_server_test.go +++ b/x/gov/keeper/msg_server_test.go @@ -27,7 +27,7 @@ func (suite *KeeperTestSuite) TestSubmitProposalReq() { addrs := suite.addrs proposer := addrs[0] - coins := sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(100))) + coins := sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(100000))) initialDeposit := coins params, _ := suite.govKeeper.Params.Get(suite.ctx) minDeposit := params.MinDeposit @@ -226,7 +226,7 @@ func (suite *KeeperTestSuite) TestSubmitProposalReq() { preRun: func() (*v1.MsgSubmitProposal, error) { return v1.NewMsgSubmitProposal( []sdk.Msg{bankMsg}, - append(initialDeposit, sdk.NewCoin("invalid", sdkmath.NewInt(100))), + initialDeposit.Add(sdk.NewCoin("invalid", sdkmath.NewInt(100))), proposer.String(), "", "Proposal", @@ -235,7 +235,7 @@ func (suite *KeeperTestSuite) TestSubmitProposalReq() { ) }, expErr: true, - expErrMsg: "deposited 100invalid, but gov accepts only the following denom(s): [stake]: invalid deposit denom", + expErrMsg: "deposited 100invalid,100000stake, but gov accepts only the following denom(s): [stake]: invalid deposit denom", }, "all good": { preRun: func() (*v1.MsgSubmitProposal, error) { @@ -288,7 +288,7 @@ func (suite *KeeperTestSuite) TestCancelProposalReq() { addrs := suite.addrs proposer := addrs[0] - coins := sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(100))) + coins := sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(100000))) bankMsg := &banktypes.MsgSend{ FromAddress: govAcct.String(), ToAddress: proposer.String(), @@ -384,7 +384,7 @@ func (suite *KeeperTestSuite) TestVoteReq() { addrs := suite.addrs proposer := addrs[0] - coins := sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(100))) + coins := sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(100000))) params, _ := suite.govKeeper.Params.Get(suite.ctx) minDeposit := params.MinDeposit bankMsg := &banktypes.MsgSend{ @@ -527,7 +527,7 @@ func (suite *KeeperTestSuite) TestVoteWeightedReq() { proposer := simtestutil.AddTestAddrsIncremental(suite.bankKeeper, suite.stakingKeeper, suite.ctx, 1, sdkmath.NewInt(50000000))[0] - coins := sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(100))) + coins := sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(100000))) params, _ := suite.govKeeper.Params.Get(suite.ctx) minDeposit := params.MinDeposit bankMsg := &banktypes.MsgSend{ @@ -770,9 +770,9 @@ func (suite *KeeperTestSuite) TestDepositReq() { addrs := suite.addrs proposer := addrs[0] - coins := sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(100))) + coins := sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(100000))) params, _ := suite.govKeeper.Params.Get(suite.ctx) - minDeposit := params.MinDeposit + minDeposit := sdk.Coins(params.MinDeposit) bankMsg := &banktypes.MsgSend{ FromAddress: govAcct.String(), ToAddress: proposer.String(), @@ -835,9 +835,9 @@ func (suite *KeeperTestSuite) TestDepositReq() { return pID }, depositor: proposer, - deposit: append(minDeposit, sdk.NewCoin("ibc/badcoin", sdkmath.NewInt(1000))), + deposit: minDeposit.Add(sdk.NewCoin("ibc/badcoin", sdkmath.NewInt(1000))), expErr: true, - expErrMsg: "deposited 1000ibc/badcoin, but gov accepts only the following denom(s): [stake]", + expErrMsg: "deposited 1000ibc/badcoin,10000000stake, but gov accepts only the following denom(s): [stake]: invalid deposit denom", }, "all good": { preRun: func() uint64 { @@ -867,7 +867,7 @@ func (suite *KeeperTestSuite) TestDepositReq() { // legacy msg server tests func (suite *KeeperTestSuite) TestLegacyMsgSubmitProposal() { proposer := simtestutil.AddTestAddrsIncremental(suite.bankKeeper, suite.stakingKeeper, suite.ctx, 1, sdkmath.NewInt(50000000))[0] - coins := sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(100))) + coins := sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(100000))) initialDeposit := coins params, _ := suite.govKeeper.Params.Get(suite.ctx) minDeposit := params.MinDeposit @@ -980,7 +980,7 @@ func (suite *KeeperTestSuite) TestLegacyMsgVote() { addrs := suite.addrs proposer := addrs[0] - coins := sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(100))) + coins := sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(100000))) params, _ := suite.govKeeper.Params.Get(suite.ctx) minDeposit := params.MinDeposit bankMsg := &banktypes.MsgSend{ @@ -1113,7 +1113,7 @@ func (suite *KeeperTestSuite) TestLegacyVoteWeighted() { addrs := suite.addrs proposer := addrs[0] - coins := sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(100))) + coins := sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(100000))) params, _ := suite.govKeeper.Params.Get(suite.ctx) minDeposit := params.MinDeposit bankMsg := &banktypes.MsgSend{ @@ -1364,7 +1364,7 @@ func (suite *KeeperTestSuite) TestLegacyMsgDeposit() { addrs := suite.addrs proposer := addrs[0] - coins := sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(100))) + coins := sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(100000))) params, _ := suite.govKeeper.Params.Get(suite.ctx) minDeposit := params.MinDeposit bankMsg := &banktypes.MsgSend{ diff --git a/x/gov/migrations/v4/json.go b/x/gov/migrations/v4/json.go index 62d7ee9bd9..bed36ff144 100644 --- a/x/gov/migrations/v4/json.go +++ b/x/gov/migrations/v4/json.go @@ -29,6 +29,7 @@ func MigrateJSON(oldState *v1.GenesisState) (*v1.GenesisState, error) { defaultParams.BurnProposalDepositPrevote, defaultParams.BurnVoteQuorum, defaultParams.BurnVoteVeto, + defaultParams.MinDepositRatio, ) return &v1.GenesisState{ diff --git a/x/gov/migrations/v4/json_test.go b/x/gov/migrations/v4/json_test.go index 4f85c284e3..18ef6dba37 100644 --- a/x/gov/migrations/v4/json_test.go +++ b/x/gov/migrations/v4/json_test.go @@ -79,6 +79,7 @@ func TestMigrateJSON(t *testing.T) { "denom": "stake" } ], + "min_deposit_ratio": "0.010000000000000000", "min_initial_deposit_ratio": "0.000000000000000000", "proposal_cancel_dest": "", "proposal_cancel_ratio": "0.500000000000000000", diff --git a/x/gov/migrations/v4/store.go b/x/gov/migrations/v4/store.go index cb41e51222..7a5857dd2a 100644 --- a/x/gov/migrations/v4/store.go +++ b/x/gov/migrations/v4/store.go @@ -42,6 +42,7 @@ func migrateParams(ctx sdk.Context, store storetypes.KVStore, legacySubspace exp defaultParams.BurnProposalDepositPrevote, defaultParams.BurnVoteQuorum, defaultParams.BurnVoteVeto, + defaultParams.MinDepositRatio, ) bz, err := cdc.Marshal(¶ms) diff --git a/x/gov/migrations/v5/store.go b/x/gov/migrations/v5/store.go index 9451ab3b45..22e336a418 100644 --- a/x/gov/migrations/v5/store.go +++ b/x/gov/migrations/v5/store.go @@ -41,6 +41,7 @@ func MigrateStore(ctx sdk.Context, storeService corestoretypes.KVStoreService, c params.ExpeditedThreshold = defaultParams.ExpeditedThreshold params.ProposalCancelRatio = defaultParams.ProposalCancelRatio params.ProposalCancelDest = defaultParams.ProposalCancelDest + params.MinDepositRatio = defaultParams.MinDepositRatio bz, err := cdc.Marshal(¶ms) if err != nil { diff --git a/x/gov/migrations/v5/store_test.go b/x/gov/migrations/v5/store_test.go index 5040f10b8e..550b77d065 100644 --- a/x/gov/migrations/v5/store_test.go +++ b/x/gov/migrations/v5/store_test.go @@ -46,6 +46,7 @@ func TestMigrateStore(t *testing.T) { require.Equal(t, v1.DefaultParams().ExpeditedMinDeposit, params.ExpeditedMinDeposit) require.Equal(t, v1.DefaultParams().ExpeditedThreshold, params.ExpeditedThreshold) require.Equal(t, v1.DefaultParams().ExpeditedVotingPeriod, params.ExpeditedVotingPeriod) + require.Equal(t, v1.DefaultParams().MinDepositRatio, params.MinDepositRatio) // Check constitution result, err := constitutionCollection.Get(ctx) diff --git a/x/gov/simulation/genesis.go b/x/gov/simulation/genesis.go index 16c58a914c..1606688484 100644 --- a/x/gov/simulation/genesis.go +++ b/x/gov/simulation/genesis.go @@ -28,6 +28,7 @@ const ( ExpeditedThreshold = "expedited_threshold" Veto = "veto" ProposalCancelRate = "proposal_cancel_rate" + MinDepositRatio = "min_deposit_ratio" // ExpeditedThreshold must be at least as large as the regular Threshold // Therefore, we use this break out point in randomization. @@ -94,6 +95,11 @@ func GenVeto(r *rand.Rand) sdkmath.LegacyDec { return sdkmath.LegacyNewDecWithPrec(int64(simulation.RandIntBetween(r, 250, 334)), 3) } +// GenMinDepositRatio returns randomized DepositMinRatio +func GenMinDepositRatio(r *rand.Rand) sdkmath.LegacyDec { + return sdkmath.LegacyMustNewDecFromStr("0.01") +} + // RandomizedGenState generates a random GenesisState for gov func RandomizedGenState(simState *module.SimulationState) { startingProposalID := uint64(simState.Rand.Intn(100)) @@ -131,9 +137,12 @@ func RandomizedGenState(simState *module.SimulationState) { var veto sdkmath.LegacyDec simState.AppParams.GetOrGenerate(Veto, &veto, simState.Rand, func(r *rand.Rand) { veto = GenVeto(r) }) + var minDepositRatio sdkmath.LegacyDec + simState.AppParams.GetOrGenerate(MinDepositRatio, &minDepositRatio, simState.Rand, func(r *rand.Rand) { minDepositRatio = GenMinDepositRatio(r) }) + govGenesis := v1.NewGenesisState( startingProposalID, - v1.NewParams(minDeposit, expeditedMinDeposit, depositPeriod, votingPeriod, expeditedVotingPeriod, quorum.String(), threshold.String(), expitedVotingThreshold.String(), veto.String(), minInitialDepositRatio.String(), proposalCancelRate.String(), "", simState.Rand.Intn(2) == 0, simState.Rand.Intn(2) == 0, simState.Rand.Intn(2) == 0), + v1.NewParams(minDeposit, expeditedMinDeposit, depositPeriod, votingPeriod, expeditedVotingPeriod, quorum.String(), threshold.String(), expitedVotingThreshold.String(), veto.String(), minInitialDepositRatio.String(), proposalCancelRate.String(), "", simState.Rand.Intn(2) == 0, simState.Rand.Intn(2) == 0, simState.Rand.Intn(2) == 0, minDepositRatio.String()), ) bz, err := json.MarshalIndent(&govGenesis, "", " ") diff --git a/x/gov/simulation/operations.go b/x/gov/simulation/operations.go index 1b4784752e..013e89fd52 100644 --- a/x/gov/simulation/operations.go +++ b/x/gov/simulation/operations.go @@ -322,7 +322,12 @@ func SimulateMsgDeposit( return simtypes.NoOpMsg(types.ModuleName, TypeMsgDeposit, "unable to generate proposalID"), nil, nil } - deposit, skip, err := randomDeposit(r, ctx, ak, bk, k, simAccount.Address, false, false) + p, err := k.Proposals.Get(ctx, proposalID) + if err != nil { + return simtypes.NoOpMsg(types.ModuleName, TypeMsgDeposit, "unable to get proposal"), nil, err + } + + deposit, skip, err := randomDeposit(r, ctx, ak, bk, k, simAccount.Address, false, p.Expedited) switch { case skip: return simtypes.NoOpMsg(types.ModuleName, TypeMsgDeposit, "skip deposit"), nil, nil @@ -570,6 +575,13 @@ func randomDeposit( minDepositAmount := minDeposit[denomIndex].Amount + minDepositRatio, err := sdkmath.LegacyNewDecFromStr(params.GetMinDepositRatio()) + if err != nil { + return nil, false, err + } + + threshold := minDepositAmount.ToLegacyDec().Mul(minDepositRatio).TruncateInt() + minAmount := sdkmath.ZeroInt() if useMinAmount { minDepositPercent, err := sdkmath.LegacyNewDecFromStr(params.MinInitialDepositRatio) @@ -586,7 +598,7 @@ func randomDeposit( } amount = amount.Add(minAmount) - if amount.GT(spendableBalance) { + if amount.GT(spendableBalance) || amount.LT(threshold) { return nil, true, nil } diff --git a/x/gov/types/v1/gov.pb.go b/x/gov/types/v1/gov.pb.go index 3929e47c9d..06eb08581f 100644 --- a/x/gov/types/v1/gov.pb.go +++ b/x/gov/types/v1/gov.pb.go @@ -795,6 +795,12 @@ type Params struct { BurnProposalDepositPrevote bool `protobuf:"varint,14,opt,name=burn_proposal_deposit_prevote,json=burnProposalDepositPrevote,proto3" json:"burn_proposal_deposit_prevote,omitempty"` // burn deposits if quorum with vote type no_veto is met BurnVoteVeto bool `protobuf:"varint,15,opt,name=burn_vote_veto,json=burnVoteVeto,proto3" json:"burn_vote_veto,omitempty"` + // The ratio representing the proportion of the deposit value minimum that must be met when making a deposit. + // Default value: 0.01. Meaning that for a chain with a min_deposit of 100stake, a deposit of 1stake would be + // required. + // + // Since: cosmos-sdk 0.50 + MinDepositRatio string `protobuf:"bytes,16,opt,name=min_deposit_ratio,json=minDepositRatio,proto3" json:"min_deposit_ratio,omitempty"` } func (m *Params) Reset() { *m = Params{} } @@ -935,6 +941,13 @@ func (m *Params) GetBurnVoteVeto() bool { return false } +func (m *Params) GetMinDepositRatio() string { + if m != nil { + return m.MinDepositRatio + } + return "" +} + func init() { proto.RegisterEnum("cosmos.gov.v1.VoteOption", VoteOption_name, VoteOption_value) proto.RegisterEnum("cosmos.gov.v1.ProposalStatus", ProposalStatus_name, ProposalStatus_value) @@ -952,96 +965,97 @@ func init() { func init() { proto.RegisterFile("cosmos/gov/v1/gov.proto", fileDescriptor_e05cb1c0d030febb) } var fileDescriptor_e05cb1c0d030febb = []byte{ - // 1415 bytes of a gzipped FileDescriptorProto + // 1432 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x57, 0x4b, 0x6f, 0xdb, 0xc6, 0x16, 0x36, 0x25, 0x59, 0x96, 0x8f, 0x1e, 0x56, 0xc6, 0x4e, 0x4c, 0x3b, 0xb1, 0xec, 0xe8, 0x06, - 0x81, 0x6f, 0x1e, 0xd2, 0x75, 0x72, 0xd3, 0x45, 0x53, 0xa0, 0x90, 0x2d, 0xa6, 0xa1, 0x91, 0x58, - 0x2a, 0xa5, 0xd8, 0x49, 0x37, 0x04, 0x6d, 0x4e, 0xe4, 0x41, 0x45, 0x8e, 0xca, 0x19, 0x29, 0xd6, - 0xbe, 0x9b, 0xee, 0xb2, 0xec, 0xaa, 0xe8, 0xb2, 0xcb, 0x2e, 0x82, 0xfe, 0x86, 0xac, 0x8a, 0x20, - 0x5d, 0xb4, 0x9b, 0xa6, 0x45, 0xb2, 0x28, 0x90, 0x5f, 0x51, 0x70, 0x38, 0x14, 0x25, 0x59, 0xad, - 0xed, 0x6c, 0x6c, 0xf1, 0x9c, 0xef, 0xfb, 0xe6, 0xcc, 0x79, 0xcc, 0x90, 0xb0, 0x78, 0x40, 0x99, - 0x43, 0x59, 0xb9, 0x45, 0x7b, 0xe5, 0xde, 0x86, 0xff, 0xaf, 0xd4, 0xf1, 0x28, 0xa7, 0x28, 0x1b, - 0x38, 0x4a, 0xbe, 0xa5, 0xb7, 0xb1, 0x5c, 0x90, 0xb8, 0x7d, 0x8b, 0xe1, 0x72, 0x6f, 0x63, 0x1f, - 0x73, 0x6b, 0xa3, 0x7c, 0x40, 0x89, 0x1b, 0xc0, 0x97, 0x17, 0x5a, 0xb4, 0x45, 0xc5, 0xcf, 0xb2, - 0xff, 0x4b, 0x5a, 0x57, 0x5b, 0x94, 0xb6, 0xda, 0xb8, 0x2c, 0x9e, 0xf6, 0xbb, 0x4f, 0xcb, 0x9c, - 0x38, 0x98, 0x71, 0xcb, 0xe9, 0x48, 0xc0, 0xd2, 0x38, 0xc0, 0x72, 0xfb, 0xd2, 0x55, 0x18, 0x77, - 0xd9, 0x5d, 0xcf, 0xe2, 0x84, 0x86, 0x2b, 0x2e, 0x05, 0x11, 0x99, 0xc1, 0xa2, 0x32, 0xda, 0xc0, - 0x75, 0xce, 0x72, 0x88, 0x4b, 0xcb, 0xe2, 0x6f, 0x60, 0x2a, 0x52, 0x40, 0x7b, 0x98, 0xb4, 0x0e, - 0x39, 0xb6, 0x77, 0x29, 0xc7, 0xb5, 0x8e, 0xaf, 0x84, 0x36, 0x20, 0x49, 0xc5, 0x2f, 0x55, 0x59, - 0x53, 0xd6, 0x73, 0xb7, 0x96, 0x4a, 0x23, 0xbb, 0x2e, 0x45, 0x50, 0x43, 0x02, 0xd1, 0x55, 0x48, - 0x3e, 0x13, 0x42, 0x6a, 0x6c, 0x4d, 0x59, 0x9f, 0xdd, 0xcc, 0xbd, 0x7e, 0x71, 0x13, 0x24, 0xab, - 0x8a, 0x0f, 0x0c, 0xe9, 0x2d, 0x7e, 0xaf, 0xc0, 0x4c, 0x15, 0x77, 0x28, 0x23, 0x1c, 0xad, 0x42, - 0xba, 0xe3, 0xd1, 0x0e, 0x65, 0x56, 0xdb, 0x24, 0xb6, 0x58, 0x2b, 0x61, 0x40, 0x68, 0xd2, 0x6d, - 0xf4, 0x11, 0xcc, 0xda, 0x01, 0x96, 0x7a, 0x52, 0x57, 0x7d, 0xfd, 0xe2, 0xe6, 0x82, 0xd4, 0xad, - 0xd8, 0xb6, 0x87, 0x19, 0x6b, 0x70, 0x8f, 0xb8, 0x2d, 0x23, 0x82, 0xa2, 0x4f, 0x20, 0x69, 0x39, - 0xb4, 0xeb, 0x72, 0x35, 0xbe, 0x16, 0x5f, 0x4f, 0x47, 0xf1, 0xfb, 0x65, 0x2a, 0xc9, 0x32, 0x95, - 0xb6, 0x28, 0x71, 0x37, 0x67, 0x5f, 0xbe, 0x59, 0x9d, 0xfa, 0xe1, 0xaf, 0x1f, 0xaf, 0x29, 0x86, - 0xe4, 0x14, 0xbf, 0x4e, 0x42, 0xaa, 0x2e, 0x83, 0x40, 0x39, 0x88, 0x0d, 0x42, 0x8b, 0x11, 0x1b, - 0xfd, 0x0f, 0x52, 0x0e, 0x66, 0xcc, 0x6a, 0x61, 0xa6, 0xc6, 0x84, 0xf8, 0x42, 0x29, 0xa8, 0x48, - 0x29, 0xac, 0x48, 0xa9, 0xe2, 0xf6, 0x8d, 0x01, 0x0a, 0xdd, 0x81, 0x24, 0xe3, 0x16, 0xef, 0x32, - 0x35, 0x2e, 0x92, 0xb9, 0x32, 0x96, 0xcc, 0x70, 0xa9, 0x86, 0x00, 0x19, 0x12, 0x8c, 0xee, 0x03, - 0x7a, 0x4a, 0x5c, 0xab, 0x6d, 0x72, 0xab, 0xdd, 0xee, 0x9b, 0x1e, 0x66, 0xdd, 0x36, 0x57, 0x13, - 0x6b, 0xca, 0x7a, 0xfa, 0xd6, 0xf2, 0x98, 0x44, 0xd3, 0x87, 0x18, 0x02, 0x61, 0xe4, 0x05, 0x6b, - 0xc8, 0x82, 0x2a, 0x90, 0x66, 0xdd, 0x7d, 0x87, 0x70, 0xd3, 0x6f, 0x33, 0x75, 0x5a, 0x4a, 0x8c, - 0x47, 0xdd, 0x0c, 0x7b, 0x70, 0x33, 0xf1, 0xfc, 0x8f, 0x55, 0xc5, 0x80, 0x80, 0xe4, 0x9b, 0xd1, - 0x36, 0xe4, 0x65, 0x76, 0x4d, 0xec, 0xda, 0x81, 0x4e, 0xf2, 0x94, 0x3a, 0x39, 0xc9, 0xd4, 0x5c, - 0x5b, 0x68, 0xe9, 0x90, 0xe5, 0x94, 0x5b, 0x6d, 0x53, 0xda, 0xd5, 0x99, 0x33, 0xd4, 0x28, 0x23, - 0xa8, 0x61, 0x03, 0x3d, 0x80, 0x73, 0x3d, 0xca, 0x89, 0xdb, 0x32, 0x19, 0xb7, 0x3c, 0xb9, 0xbf, - 0xd4, 0x29, 0xe3, 0x9a, 0x0b, 0xa8, 0x0d, 0x9f, 0x29, 0x02, 0xbb, 0x0f, 0xd2, 0x14, 0xed, 0x71, - 0xf6, 0x94, 0x5a, 0xd9, 0x80, 0x18, 0x6e, 0x71, 0xd9, 0x6f, 0x12, 0x6e, 0xd9, 0x16, 0xb7, 0x54, - 0xf0, 0xdb, 0xd6, 0x18, 0x3c, 0xa3, 0x05, 0x98, 0xe6, 0x84, 0xb7, 0xb1, 0x9a, 0x16, 0x8e, 0xe0, - 0x01, 0xa9, 0x30, 0xc3, 0xba, 0x8e, 0x63, 0x79, 0x7d, 0x35, 0x23, 0xec, 0xe1, 0x23, 0xfa, 0x3f, - 0xa4, 0x82, 0x89, 0xc0, 0x9e, 0x9a, 0x3d, 0x61, 0x04, 0x06, 0x48, 0x74, 0x09, 0x66, 0xf1, 0x51, - 0x07, 0xdb, 0x84, 0x63, 0x5b, 0xcd, 0xad, 0x29, 0xeb, 0x29, 0x23, 0x32, 0xa0, 0xff, 0x40, 0xf6, - 0xa9, 0x45, 0xda, 0xd8, 0x36, 0x3d, 0x6c, 0x31, 0xea, 0xaa, 0x73, 0x62, 0xcd, 0x4c, 0x60, 0x34, - 0x84, 0xad, 0xf8, 0xab, 0x02, 0xe9, 0xe1, 0x36, 0xba, 0x0e, 0xb3, 0x7d, 0xcc, 0xcc, 0x03, 0x31, - 0x57, 0xca, 0xb1, 0x21, 0xd7, 0x5d, 0x6e, 0xa4, 0xfa, 0x98, 0x6d, 0xf9, 0x7e, 0x74, 0x1b, 0xb2, - 0xd6, 0x3e, 0xe3, 0x16, 0x71, 0x25, 0x21, 0x36, 0x91, 0x90, 0x91, 0xa0, 0x80, 0xf4, 0x5f, 0x48, - 0xb9, 0x54, 0xe2, 0xe3, 0x13, 0xf1, 0x33, 0x2e, 0x0d, 0xa0, 0x77, 0x01, 0xb9, 0xd4, 0x7c, 0x46, - 0xf8, 0xa1, 0xd9, 0xc3, 0x3c, 0x24, 0x25, 0x26, 0x92, 0xe6, 0x5c, 0xba, 0x47, 0xf8, 0xe1, 0x2e, - 0xe6, 0x01, 0xb9, 0xf8, 0x93, 0x02, 0x09, 0xff, 0x08, 0x3b, 0xf9, 0x00, 0x2a, 0xc1, 0x74, 0x8f, - 0x72, 0x7c, 0xf2, 0xe1, 0x13, 0xc0, 0xd0, 0x5d, 0x98, 0x09, 0xce, 0x43, 0xa6, 0x26, 0x44, 0x57, - 0x5f, 0x1e, 0x9b, 0xd4, 0xe3, 0x87, 0xad, 0x11, 0x32, 0x46, 0xba, 0x66, 0x7a, 0xb4, 0x6b, 0xb6, - 0x13, 0xa9, 0x78, 0x3e, 0x51, 0xfc, 0x5d, 0x81, 0xac, 0xec, 0xfd, 0xba, 0xe5, 0x59, 0x0e, 0x43, - 0x4f, 0x20, 0xed, 0x10, 0x77, 0x30, 0x4a, 0xca, 0x49, 0xa3, 0xb4, 0xe2, 0x8f, 0xd2, 0xfb, 0x37, - 0xab, 0xe7, 0x87, 0x58, 0x37, 0xa8, 0x43, 0x38, 0x76, 0x3a, 0xbc, 0x6f, 0x80, 0x43, 0xdc, 0x70, - 0xb8, 0x1c, 0x40, 0x8e, 0x75, 0x14, 0x82, 0xcc, 0x0e, 0xf6, 0x08, 0xb5, 0x45, 0x22, 0xfc, 0x15, - 0xc6, 0x27, 0xa2, 0x2a, 0x6f, 0xa1, 0xcd, 0x2b, 0xef, 0xdf, 0xac, 0x5e, 0x3a, 0x4e, 0x8c, 0x16, - 0xf9, 0xd6, 0x1f, 0x98, 0xbc, 0x63, 0x1d, 0x85, 0x3b, 0x11, 0xfe, 0x8f, 0x63, 0xaa, 0x52, 0x7c, - 0x0c, 0x99, 0x5d, 0x31, 0x48, 0x72, 0x77, 0x55, 0x90, 0x83, 0x15, 0xae, 0xae, 0x9c, 0xb4, 0x7a, - 0x42, 0xa8, 0x67, 0x02, 0xd6, 0x90, 0xf2, 0x77, 0x61, 0x33, 0x4b, 0xe5, 0xab, 0x90, 0xfc, 0xaa, - 0x4b, 0xbd, 0xae, 0x33, 0xa1, 0x93, 0xc5, 0x75, 0x15, 0x78, 0xd1, 0x0d, 0x98, 0xe5, 0x87, 0x1e, - 0x66, 0x87, 0xb4, 0x6d, 0xff, 0xc3, 0xcd, 0x16, 0x01, 0xd0, 0x1d, 0xc8, 0x89, 0x6e, 0x8c, 0x28, - 0xf1, 0x89, 0x94, 0xac, 0x8f, 0x6a, 0x86, 0x20, 0x11, 0xe0, 0x2f, 0x33, 0x90, 0x94, 0xb1, 0x69, - 0x67, 0xac, 0xe9, 0xd0, 0xf1, 0x38, 0x5c, 0xbf, 0x87, 0x1f, 0x56, 0xbf, 0xc4, 0xe4, 0xfa, 0x1c, - 0xaf, 0x45, 0xfc, 0x03, 0x6a, 0x31, 0x94, 0xf7, 0xc4, 0xe9, 0xf3, 0x3e, 0x7d, 0xf6, 0xbc, 0x27, - 0x4f, 0x91, 0x77, 0xa4, 0xc3, 0x92, 0x9f, 0x68, 0xe2, 0x12, 0x4e, 0xa2, 0xfb, 0xc8, 0x14, 0xe1, - 0xab, 0x33, 0x13, 0x15, 0x2e, 0x38, 0xc4, 0xd5, 0x03, 0xbc, 0x4c, 0x8f, 0xe1, 0xa3, 0xd1, 0x26, - 0x9c, 0x1f, 0x9c, 0x24, 0x07, 0x96, 0x7b, 0x80, 0xdb, 0x52, 0x26, 0x35, 0x51, 0x66, 0x3e, 0x04, - 0x6f, 0x09, 0x6c, 0xa0, 0xb1, 0x0d, 0x0b, 0xe3, 0x1a, 0x36, 0x66, 0x5c, 0x5c, 0x42, 0xff, 0x76, - 0xf6, 0xa0, 0x51, 0xb1, 0x2a, 0x66, 0x1c, 0xed, 0xc1, 0xe2, 0xe0, 0xb8, 0x37, 0x47, 0xeb, 0x06, - 0xa7, 0xab, 0xdb, 0xf9, 0x01, 0x7f, 0x77, 0xb8, 0x80, 0x9f, 0xc2, 0x7c, 0x24, 0x1c, 0xe5, 0x3b, - 0x3d, 0x71, 0x9b, 0x68, 0x00, 0x8d, 0x92, 0xfe, 0x18, 0x22, 0x65, 0x73, 0xb8, 0xcf, 0x33, 0x67, - 0xe8, 0xf3, 0x28, 0x86, 0x87, 0x51, 0xc3, 0xaf, 0x43, 0x7e, 0xbf, 0xeb, 0xb9, 0xfe, 0x76, 0xb1, - 0x29, 0xbb, 0x2c, 0x2b, 0xae, 0xbe, 0x9c, 0x6f, 0xf7, 0x8f, 0xdc, 0xcf, 0x83, 0xee, 0xaa, 0xc0, - 0x8a, 0x40, 0x0e, 0xd2, 0x3d, 0x18, 0x12, 0x0f, 0xfb, 0x6c, 0x79, 0x63, 0x2e, 0xfb, 0xa0, 0xf0, - 0xf5, 0x2c, 0x9c, 0x86, 0x00, 0x81, 0xae, 0x40, 0x2e, 0x5a, 0xcc, 0x6f, 0x2b, 0x71, 0x87, 0xa6, - 0x8c, 0x4c, 0xb8, 0x94, 0x7f, 0xdd, 0x5c, 0xfb, 0x46, 0x01, 0x18, 0x7a, 0xaf, 0xbe, 0x08, 0x8b, - 0xbb, 0xb5, 0xa6, 0x66, 0xd6, 0xea, 0x4d, 0xbd, 0xb6, 0x63, 0x3e, 0xda, 0x69, 0xd4, 0xb5, 0x2d, - 0xfd, 0x9e, 0xae, 0x55, 0xf3, 0x53, 0x68, 0x1e, 0xe6, 0x86, 0x9d, 0x4f, 0xb4, 0x46, 0x5e, 0x41, - 0x8b, 0x30, 0x3f, 0x6c, 0xac, 0x6c, 0x36, 0x9a, 0x15, 0x7d, 0x27, 0x1f, 0x43, 0x08, 0x72, 0xc3, - 0x8e, 0x9d, 0x5a, 0x3e, 0x8e, 0x2e, 0x81, 0x3a, 0x6a, 0x33, 0xf7, 0xf4, 0xe6, 0x7d, 0x73, 0x57, - 0x6b, 0xd6, 0xf2, 0x89, 0x6b, 0x3f, 0x2b, 0x90, 0x1b, 0x7d, 0xd7, 0x44, 0xab, 0x70, 0xb1, 0x6e, - 0xd4, 0xea, 0xb5, 0x46, 0xe5, 0x81, 0xd9, 0x68, 0x56, 0x9a, 0x8f, 0x1a, 0x63, 0x31, 0x15, 0xa1, - 0x30, 0x0e, 0xa8, 0x6a, 0xf5, 0x5a, 0x43, 0x6f, 0x9a, 0x75, 0xcd, 0xd0, 0x6b, 0xd5, 0xbc, 0x82, - 0x2e, 0xc3, 0xca, 0x38, 0x66, 0xb7, 0xd6, 0xd4, 0x77, 0x3e, 0x0b, 0x21, 0x31, 0xb4, 0x0c, 0x17, - 0xc6, 0x21, 0xf5, 0x4a, 0xa3, 0xa1, 0x55, 0x83, 0xa0, 0xc7, 0x7d, 0x86, 0xb6, 0xad, 0x6d, 0x35, - 0xb5, 0x6a, 0x3e, 0x31, 0x89, 0x79, 0xaf, 0xa2, 0x3f, 0xd0, 0xaa, 0xf9, 0xe9, 0x4d, 0xed, 0xe5, - 0xdb, 0x82, 0xf2, 0xea, 0x6d, 0x41, 0xf9, 0xf3, 0x6d, 0x41, 0x79, 0xfe, 0xae, 0x30, 0xf5, 0xea, - 0x5d, 0x61, 0xea, 0xb7, 0x77, 0x85, 0xa9, 0x2f, 0xae, 0xb7, 0x08, 0x3f, 0xec, 0xee, 0x97, 0x0e, - 0xa8, 0x23, 0xbf, 0x80, 0xe4, 0xbf, 0x9b, 0xcc, 0xfe, 0xb2, 0x7c, 0x24, 0xbe, 0xea, 0x78, 0xbf, - 0x83, 0x99, 0xff, 0xc9, 0x96, 0x14, 0x13, 0x70, 0xfb, 0xef, 0x00, 0x00, 0x00, 0xff, 0xff, 0xc2, - 0x33, 0x69, 0x7d, 0xf3, 0x0d, 0x00, 0x00, + 0x81, 0x6f, 0x1e, 0xd2, 0x75, 0x72, 0x73, 0x17, 0xc9, 0x05, 0x0a, 0xd9, 0x62, 0x1a, 0x1a, 0x89, + 0xa5, 0x52, 0x8a, 0x9d, 0x74, 0x43, 0xd0, 0xe6, 0x44, 0x1e, 0x54, 0xe4, 0xa8, 0x9c, 0x91, 0x63, + 0xed, 0xbb, 0xe9, 0xaa, 0x59, 0x76, 0x55, 0x74, 0xd9, 0x65, 0x17, 0x41, 0x7f, 0x43, 0x56, 0x45, + 0x90, 0x4d, 0xbb, 0x69, 0x5a, 0x24, 0x8b, 0x02, 0xf9, 0x15, 0x05, 0x87, 0x43, 0x91, 0x96, 0xd5, + 0xda, 0xce, 0xc6, 0x16, 0xcf, 0xf9, 0xbe, 0x6f, 0xce, 0x9c, 0xc7, 0x0c, 0x09, 0xf3, 0x7b, 0x94, + 0x39, 0x94, 0x55, 0x3b, 0xf4, 0xa0, 0x7a, 0xb0, 0xe6, 0xff, 0xab, 0xf4, 0x3c, 0xca, 0x29, 0xca, + 0x07, 0x8e, 0x8a, 0x6f, 0x39, 0x58, 0x5b, 0x2c, 0x49, 0xdc, 0xae, 0xc5, 0x70, 0xf5, 0x60, 0x6d, + 0x17, 0x73, 0x6b, 0xad, 0xba, 0x47, 0x89, 0x1b, 0xc0, 0x17, 0xe7, 0x3a, 0xb4, 0x43, 0xc5, 0xcf, + 0xaa, 0xff, 0x4b, 0x5a, 0x97, 0x3b, 0x94, 0x76, 0xba, 0xb8, 0x2a, 0x9e, 0x76, 0xfb, 0xcf, 0xaa, + 0x9c, 0x38, 0x98, 0x71, 0xcb, 0xe9, 0x49, 0xc0, 0xc2, 0x28, 0xc0, 0x72, 0x07, 0xd2, 0x55, 0x1a, + 0x75, 0xd9, 0x7d, 0xcf, 0xe2, 0x84, 0x86, 0x2b, 0x2e, 0x04, 0x11, 0x99, 0xc1, 0xa2, 0x32, 0xda, + 0xc0, 0x75, 0xce, 0x72, 0x88, 0x4b, 0xab, 0xe2, 0x6f, 0x60, 0x2a, 0x53, 0x40, 0x3b, 0x98, 0x74, + 0xf6, 0x39, 0xb6, 0xb7, 0x29, 0xc7, 0x8d, 0x9e, 0xaf, 0x84, 0xd6, 0x20, 0x4d, 0xc5, 0x2f, 0x55, + 0x59, 0x51, 0x56, 0x0b, 0xb7, 0x16, 0x2a, 0x47, 0x76, 0x5d, 0x89, 0xa0, 0x86, 0x04, 0xa2, 0xab, + 0x90, 0x7e, 0x2e, 0x84, 0xd4, 0xc4, 0x8a, 0xb2, 0x3a, 0xbd, 0x5e, 0x78, 0xf3, 0xf2, 0x26, 0x48, + 0x56, 0x1d, 0xef, 0x19, 0xd2, 0x5b, 0xfe, 0x5e, 0x81, 0xa9, 0x3a, 0xee, 0x51, 0x46, 0x38, 0x5a, + 0x86, 0x6c, 0xcf, 0xa3, 0x3d, 0xca, 0xac, 0xae, 0x49, 0x6c, 0xb1, 0x56, 0xca, 0x80, 0xd0, 0xa4, + 0xdb, 0xe8, 0x7f, 0x30, 0x6d, 0x07, 0x58, 0xea, 0x49, 0x5d, 0xf5, 0xcd, 0xcb, 0x9b, 0x73, 0x52, + 0xb7, 0x66, 0xdb, 0x1e, 0x66, 0xac, 0xc5, 0x3d, 0xe2, 0x76, 0x8c, 0x08, 0x8a, 0xfe, 0x0f, 0x69, + 0xcb, 0xa1, 0x7d, 0x97, 0xab, 0xc9, 0x95, 0xe4, 0x6a, 0x36, 0x8a, 0xdf, 0x2f, 0x53, 0x45, 0x96, + 0xa9, 0xb2, 0x41, 0x89, 0xbb, 0x3e, 0xfd, 0xea, 0xed, 0xf2, 0xc4, 0x0f, 0x7f, 0xfe, 0x78, 0x4d, + 0x31, 0x24, 0xa7, 0xfc, 0x55, 0x1a, 0x32, 0x4d, 0x19, 0x04, 0x2a, 0x40, 0x62, 0x18, 0x5a, 0x82, + 0xd8, 0xe8, 0x3f, 0x90, 0x71, 0x30, 0x63, 0x56, 0x07, 0x33, 0x35, 0x21, 0xc4, 0xe7, 0x2a, 0x41, + 0x45, 0x2a, 0x61, 0x45, 0x2a, 0x35, 0x77, 0x60, 0x0c, 0x51, 0xe8, 0x0e, 0xa4, 0x19, 0xb7, 0x78, + 0x9f, 0xa9, 0x49, 0x91, 0xcc, 0xa5, 0x91, 0x64, 0x86, 0x4b, 0xb5, 0x04, 0xc8, 0x90, 0x60, 0xf4, + 0x00, 0xd0, 0x33, 0xe2, 0x5a, 0x5d, 0x93, 0x5b, 0xdd, 0xee, 0xc0, 0xf4, 0x30, 0xeb, 0x77, 0xb9, + 0x9a, 0x5a, 0x51, 0x56, 0xb3, 0xb7, 0x16, 0x47, 0x24, 0xda, 0x3e, 0xc4, 0x10, 0x08, 0xa3, 0x28, + 0x58, 0x31, 0x0b, 0xaa, 0x41, 0x96, 0xf5, 0x77, 0x1d, 0xc2, 0x4d, 0xbf, 0xcd, 0xd4, 0x49, 0x29, + 0x31, 0x1a, 0x75, 0x3b, 0xec, 0xc1, 0xf5, 0xd4, 0x8b, 0xdf, 0x97, 0x15, 0x03, 0x02, 0x92, 0x6f, + 0x46, 0x9b, 0x50, 0x94, 0xd9, 0x35, 0xb1, 0x6b, 0x07, 0x3a, 0xe9, 0x53, 0xea, 0x14, 0x24, 0x53, + 0x73, 0x6d, 0xa1, 0xa5, 0x43, 0x9e, 0x53, 0x6e, 0x75, 0x4d, 0x69, 0x57, 0xa7, 0xce, 0x50, 0xa3, + 0x9c, 0xa0, 0x86, 0x0d, 0xf4, 0x10, 0xce, 0x1d, 0x50, 0x4e, 0xdc, 0x8e, 0xc9, 0xb8, 0xe5, 0xc9, + 0xfd, 0x65, 0x4e, 0x19, 0xd7, 0x4c, 0x40, 0x6d, 0xf9, 0x4c, 0x11, 0xd8, 0x03, 0x90, 0xa6, 0x68, + 0x8f, 0xd3, 0xa7, 0xd4, 0xca, 0x07, 0xc4, 0x70, 0x8b, 0x8b, 0x7e, 0x93, 0x70, 0xcb, 0xb6, 0xb8, + 0xa5, 0x82, 0xdf, 0xb6, 0xc6, 0xf0, 0x19, 0xcd, 0xc1, 0x24, 0x27, 0xbc, 0x8b, 0xd5, 0xac, 0x70, + 0x04, 0x0f, 0x48, 0x85, 0x29, 0xd6, 0x77, 0x1c, 0xcb, 0x1b, 0xa8, 0x39, 0x61, 0x0f, 0x1f, 0xd1, + 0x7f, 0x21, 0x13, 0x4c, 0x04, 0xf6, 0xd4, 0xfc, 0x09, 0x23, 0x30, 0x44, 0xa2, 0x4b, 0x30, 0x8d, + 0x0f, 0x7b, 0xd8, 0x26, 0x1c, 0xdb, 0x6a, 0x61, 0x45, 0x59, 0xcd, 0x18, 0x91, 0x01, 0xfd, 0x0b, + 0xf2, 0xcf, 0x2c, 0xd2, 0xc5, 0xb6, 0xe9, 0x61, 0x8b, 0x51, 0x57, 0x9d, 0x11, 0x6b, 0xe6, 0x02, + 0xa3, 0x21, 0x6c, 0xe5, 0x5f, 0x14, 0xc8, 0xc6, 0xdb, 0xe8, 0x3a, 0x4c, 0x0f, 0x30, 0x33, 0xf7, + 0xc4, 0x5c, 0x29, 0xc7, 0x86, 0x5c, 0x77, 0xb9, 0x91, 0x19, 0x60, 0xb6, 0xe1, 0xfb, 0xd1, 0x6d, + 0xc8, 0x5b, 0xbb, 0x8c, 0x5b, 0xc4, 0x95, 0x84, 0xc4, 0x58, 0x42, 0x4e, 0x82, 0x02, 0xd2, 0xbf, + 0x21, 0xe3, 0x52, 0x89, 0x4f, 0x8e, 0xc5, 0x4f, 0xb9, 0x34, 0x80, 0xde, 0x03, 0xe4, 0x52, 0xf3, + 0x39, 0xe1, 0xfb, 0xe6, 0x01, 0xe6, 0x21, 0x29, 0x35, 0x96, 0x34, 0xe3, 0xd2, 0x1d, 0xc2, 0xf7, + 0xb7, 0x31, 0x0f, 0xc8, 0xe5, 0x9f, 0x14, 0x48, 0xf9, 0x47, 0xd8, 0xc9, 0x07, 0x50, 0x05, 0x26, + 0x0f, 0x28, 0xc7, 0x27, 0x1f, 0x3e, 0x01, 0x0c, 0xdd, 0x83, 0xa9, 0xe0, 0x3c, 0x64, 0x6a, 0x4a, + 0x74, 0xf5, 0xe5, 0x91, 0x49, 0x3d, 0x7e, 0xd8, 0x1a, 0x21, 0xe3, 0x48, 0xd7, 0x4c, 0x1e, 0xed, + 0x9a, 0xcd, 0x54, 0x26, 0x59, 0x4c, 0x95, 0x7f, 0x53, 0x20, 0x2f, 0x7b, 0xbf, 0x69, 0x79, 0x96, + 0xc3, 0xd0, 0x53, 0xc8, 0x3a, 0xc4, 0x1d, 0x8e, 0x92, 0x72, 0xd2, 0x28, 0x2d, 0xf9, 0xa3, 0xf4, + 0xe1, 0xed, 0xf2, 0xf9, 0x18, 0xeb, 0x06, 0x75, 0x08, 0xc7, 0x4e, 0x8f, 0x0f, 0x0c, 0x70, 0x88, + 0x1b, 0x0e, 0x97, 0x03, 0xc8, 0xb1, 0x0e, 0x43, 0x90, 0xd9, 0xc3, 0x1e, 0xa1, 0xb6, 0x48, 0x84, + 0xbf, 0xc2, 0xe8, 0x44, 0xd4, 0xe5, 0x2d, 0xb4, 0x7e, 0xe5, 0xc3, 0xdb, 0xe5, 0x4b, 0xc7, 0x89, + 0xd1, 0x22, 0xdf, 0xfa, 0x03, 0x53, 0x74, 0xac, 0xc3, 0x70, 0x27, 0xc2, 0x7f, 0x37, 0xa1, 0x2a, + 0xe5, 0x27, 0x90, 0xdb, 0x16, 0x83, 0x24, 0x77, 0x57, 0x07, 0x39, 0x58, 0xe1, 0xea, 0xca, 0x49, + 0xab, 0xa7, 0x84, 0x7a, 0x2e, 0x60, 0xc5, 0x94, 0xbf, 0x0b, 0x9b, 0x59, 0x2a, 0x5f, 0x85, 0xf4, + 0x97, 0x7d, 0xea, 0xf5, 0x9d, 0x31, 0x9d, 0x2c, 0xae, 0xab, 0xc0, 0x8b, 0x6e, 0xc0, 0x34, 0xdf, + 0xf7, 0x30, 0xdb, 0xa7, 0x5d, 0xfb, 0x6f, 0x6e, 0xb6, 0x08, 0x80, 0xee, 0x40, 0x41, 0x74, 0x63, + 0x44, 0x49, 0x8e, 0xa5, 0xe4, 0x7d, 0x54, 0x3b, 0x04, 0x89, 0x00, 0xbf, 0xc9, 0x40, 0x5a, 0xc6, + 0xa6, 0x9d, 0xb1, 0xa6, 0xb1, 0xe3, 0x31, 0x5e, 0xbf, 0x47, 0x1f, 0x57, 0xbf, 0xd4, 0xf8, 0xfa, + 0x1c, 0xaf, 0x45, 0xf2, 0x23, 0x6a, 0x11, 0xcb, 0x7b, 0xea, 0xf4, 0x79, 0x9f, 0x3c, 0x7b, 0xde, + 0xd3, 0xa7, 0xc8, 0x3b, 0xd2, 0x61, 0xc1, 0x4f, 0x34, 0x71, 0x09, 0x27, 0xd1, 0x7d, 0x64, 0x8a, + 0xf0, 0xd5, 0xa9, 0xb1, 0x0a, 0x17, 0x1c, 0xe2, 0xea, 0x01, 0x5e, 0xa6, 0xc7, 0xf0, 0xd1, 0x68, + 0x1d, 0xce, 0x0f, 0x4f, 0x92, 0x3d, 0xcb, 0xdd, 0xc3, 0x5d, 0x29, 0x93, 0x19, 0x2b, 0x33, 0x1b, + 0x82, 0x37, 0x04, 0x36, 0xd0, 0xd8, 0x84, 0xb9, 0x51, 0x0d, 0x1b, 0x33, 0x2e, 0x2e, 0xa1, 0x7f, + 0x3a, 0x7b, 0xd0, 0x51, 0xb1, 0x3a, 0x66, 0x1c, 0xed, 0xc0, 0xfc, 0xf0, 0xb8, 0x37, 0x8f, 0xd6, + 0x0d, 0x4e, 0x57, 0xb7, 0xf3, 0x43, 0xfe, 0x76, 0xbc, 0x80, 0x9f, 0xc0, 0x6c, 0x24, 0x1c, 0xe5, + 0x3b, 0x3b, 0x76, 0x9b, 0x68, 0x08, 0x8d, 0x92, 0xfe, 0x04, 0x22, 0x65, 0x33, 0xde, 0xe7, 0xb9, + 0x33, 0xf4, 0x79, 0x14, 0xc3, 0xa3, 0xa8, 0xe1, 0x57, 0xa1, 0xb8, 0xdb, 0xf7, 0x5c, 0x7f, 0xbb, + 0xd8, 0x94, 0x5d, 0x96, 0x17, 0x57, 0x5f, 0xc1, 0xb7, 0xfb, 0x47, 0xee, 0x67, 0x41, 0x77, 0xd5, + 0x60, 0x49, 0x20, 0x87, 0xe9, 0x1e, 0x0e, 0x89, 0x87, 0x7d, 0xb6, 0xbc, 0x31, 0x17, 0x7d, 0x50, + 0xf8, 0x7a, 0x16, 0x4e, 0x43, 0x80, 0x40, 0x57, 0xa0, 0x10, 0x2d, 0xe6, 0xb7, 0x95, 0xb8, 0x43, + 0x33, 0x46, 0x2e, 0x5c, 0xca, 0xbf, 0x6e, 0xd0, 0x5d, 0x38, 0x17, 0xdb, 0xa2, 0x6c, 0x89, 0xe2, + 0xd8, 0x5c, 0xcd, 0x44, 0xa3, 0x2b, 0xda, 0xe1, 0xda, 0xd7, 0x0a, 0x40, 0xec, 0x9d, 0xfc, 0x22, + 0xcc, 0x6f, 0x37, 0xda, 0x9a, 0xd9, 0x68, 0xb6, 0xf5, 0xc6, 0x96, 0xf9, 0x78, 0xab, 0xd5, 0xd4, + 0x36, 0xf4, 0xfb, 0xba, 0x56, 0x2f, 0x4e, 0xa0, 0x59, 0x98, 0x89, 0x3b, 0x9f, 0x6a, 0xad, 0xa2, + 0x82, 0xe6, 0x61, 0x36, 0x6e, 0xac, 0xad, 0xb7, 0xda, 0x35, 0x7d, 0xab, 0x98, 0x40, 0x08, 0x0a, + 0x71, 0xc7, 0x56, 0xa3, 0x98, 0x44, 0x97, 0x40, 0x3d, 0x6a, 0x33, 0x77, 0xf4, 0xf6, 0x03, 0x73, + 0x5b, 0x6b, 0x37, 0x8a, 0xa9, 0x6b, 0x3f, 0x2b, 0x50, 0x38, 0xfa, 0x9e, 0x8a, 0x96, 0xe1, 0x62, + 0xd3, 0x68, 0x34, 0x1b, 0xad, 0xda, 0x43, 0xb3, 0xd5, 0xae, 0xb5, 0x1f, 0xb7, 0x46, 0x62, 0x2a, + 0x43, 0x69, 0x14, 0x50, 0xd7, 0x9a, 0x8d, 0x96, 0xde, 0x36, 0x9b, 0x9a, 0xa1, 0x37, 0xea, 0x45, + 0x05, 0x5d, 0x86, 0xa5, 0x51, 0xcc, 0x76, 0xa3, 0xad, 0x6f, 0x7d, 0x1a, 0x42, 0x12, 0x68, 0x11, + 0x2e, 0x8c, 0x42, 0x9a, 0xb5, 0x56, 0x4b, 0xab, 0x07, 0x41, 0x8f, 0xfa, 0x0c, 0x6d, 0x53, 0xdb, + 0x68, 0x6b, 0xf5, 0x62, 0x6a, 0x1c, 0xf3, 0x7e, 0x4d, 0x7f, 0xa8, 0xd5, 0x8b, 0x93, 0xeb, 0xda, + 0xab, 0x77, 0x25, 0xe5, 0xf5, 0xbb, 0x92, 0xf2, 0xc7, 0xbb, 0x92, 0xf2, 0xe2, 0x7d, 0x69, 0xe2, + 0xf5, 0xfb, 0xd2, 0xc4, 0xaf, 0xef, 0x4b, 0x13, 0x9f, 0x5f, 0xef, 0x10, 0xbe, 0xdf, 0xdf, 0xad, + 0xec, 0x51, 0x47, 0x7e, 0x3d, 0xc9, 0x7f, 0x37, 0x99, 0xfd, 0x45, 0xf5, 0x50, 0x7c, 0x11, 0xf2, + 0x41, 0x0f, 0x33, 0xff, 0x73, 0x2f, 0x2d, 0xa6, 0xe7, 0xf6, 0x5f, 0x01, 0x00, 0x00, 0xff, 0xff, + 0x08, 0xe1, 0xbb, 0x1f, 0x2f, 0x0e, 0x00, 0x00, } func (m *WeightedVoteOption) Marshal() (dAtA []byte, err error) { @@ -1537,6 +1551,15 @@ func (m *Params) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if len(m.MinDepositRatio) > 0 { + i -= len(m.MinDepositRatio) + copy(dAtA[i:], m.MinDepositRatio) + i = encodeVarintGov(dAtA, i, uint64(len(m.MinDepositRatio))) + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0x82 + } if m.BurnVoteVeto { i-- if m.BurnVoteVeto { @@ -1967,6 +1990,10 @@ func (m *Params) Size() (n int) { if m.BurnVoteVeto { n += 2 } + l = len(m.MinDepositRatio) + if l > 0 { + n += 2 + l + sovGov(uint64(l)) + } return n } @@ -3914,6 +3941,38 @@ func (m *Params) Unmarshal(dAtA []byte) error { } } m.BurnVoteVeto = bool(v != 0) + case 16: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MinDepositRatio", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGov + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGov + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGov + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.MinDepositRatio = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGov(dAtA[iNdEx:]) diff --git a/x/gov/types/v1/params.go b/x/gov/types/v1/params.go index 5633ebb4c5..658104a954 100644 --- a/x/gov/types/v1/params.go +++ b/x/gov/types/v1/params.go @@ -30,6 +30,7 @@ var ( DefaultBurnProposalPrevote = false // set to false to replicate behavior of when this change was made (0.47) DefaultBurnVoteQuorom = false // set to false to replicate behavior of when this change was made (0.47) DefaultBurnVoteVeto = true // set to true to replicate behavior of when this change was made (0.47) + DefaultMinDepositRatio = sdkmath.LegacyMustNewDecFromStr("0.01") ) // Deprecated: NewDepositParams creates a new DepositParams object @@ -59,7 +60,8 @@ func NewVotingParams(votingPeriod *time.Duration) VotingParams { // NewParams creates a new Params instance with given values. func NewParams( minDeposit, expeditedminDeposit sdk.Coins, maxDepositPeriod, votingPeriod, expeditedVotingPeriod time.Duration, - quorum, threshold, expeditedThreshold, vetoThreshold, minInitialDepositRatio, proposalCancelRatio, proposalCancelDest string, burnProposalDeposit, burnVoteQuorum, burnVoteVeto bool, + quorum, threshold, expeditedThreshold, vetoThreshold, minInitialDepositRatio, proposalCancelRatio, proposalCancelDest string, + burnProposalDeposit, burnVoteQuorum, burnVoteVeto bool, minDepositRatio string, ) Params { return Params{ MinDeposit: minDeposit, @@ -77,6 +79,7 @@ func NewParams( BurnProposalDepositPrevote: burnProposalDeposit, BurnVoteQuorum: burnVoteQuorum, BurnVoteVeto: burnVoteVeto, + MinDepositRatio: minDepositRatio, } } @@ -98,6 +101,7 @@ func DefaultParams() Params { DefaultBurnProposalPrevote, DefaultBurnVoteQuorom, DefaultBurnVoteVeto, + DefaultMinDepositRatio.String(), ) }