feat(x/mint): Add max supply param (#19896)

Co-authored-by: Marko <marko@baricevic.me>
This commit is contained in:
Likhita Polavarapu 2024-05-03 15:56:18 +05:30 committed by GitHub
parent 74966c9c94
commit 52dbcc171c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 297 additions and 65 deletions

View File

@ -507,6 +507,7 @@ var (
fd_Params_inflation_min protoreflect.FieldDescriptor
fd_Params_goal_bonded protoreflect.FieldDescriptor
fd_Params_blocks_per_year protoreflect.FieldDescriptor
fd_Params_max_supply protoreflect.FieldDescriptor
)
func init() {
@ -518,6 +519,7 @@ func init() {
fd_Params_inflation_min = md_Params.Fields().ByName("inflation_min")
fd_Params_goal_bonded = md_Params.Fields().ByName("goal_bonded")
fd_Params_blocks_per_year = md_Params.Fields().ByName("blocks_per_year")
fd_Params_max_supply = md_Params.Fields().ByName("max_supply")
}
var _ protoreflect.Message = (*fastReflection_Params)(nil)
@ -621,6 +623,12 @@ func (x *fastReflection_Params) Range(f func(protoreflect.FieldDescriptor, proto
return
}
}
if x.MaxSupply != "" {
value := protoreflect.ValueOfString(x.MaxSupply)
if !f(fd_Params_max_supply, value) {
return
}
}
}
// Has reports whether a field is populated.
@ -648,6 +656,8 @@ func (x *fastReflection_Params) Has(fd protoreflect.FieldDescriptor) bool {
return x.GoalBonded != ""
case "cosmos.mint.v1beta1.Params.blocks_per_year":
return x.BlocksPerYear != uint64(0)
case "cosmos.mint.v1beta1.Params.max_supply":
return x.MaxSupply != ""
default:
if fd.IsExtension() {
panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.mint.v1beta1.Params"))
@ -676,6 +686,8 @@ func (x *fastReflection_Params) Clear(fd protoreflect.FieldDescriptor) {
x.GoalBonded = ""
case "cosmos.mint.v1beta1.Params.blocks_per_year":
x.BlocksPerYear = uint64(0)
case "cosmos.mint.v1beta1.Params.max_supply":
x.MaxSupply = ""
default:
if fd.IsExtension() {
panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.mint.v1beta1.Params"))
@ -710,6 +722,9 @@ func (x *fastReflection_Params) Get(descriptor protoreflect.FieldDescriptor) pro
case "cosmos.mint.v1beta1.Params.blocks_per_year":
value := x.BlocksPerYear
return protoreflect.ValueOfUint64(value)
case "cosmos.mint.v1beta1.Params.max_supply":
value := x.MaxSupply
return protoreflect.ValueOfString(value)
default:
if descriptor.IsExtension() {
panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.mint.v1beta1.Params"))
@ -742,6 +757,8 @@ func (x *fastReflection_Params) Set(fd protoreflect.FieldDescriptor, value proto
x.GoalBonded = value.Interface().(string)
case "cosmos.mint.v1beta1.Params.blocks_per_year":
x.BlocksPerYear = value.Uint()
case "cosmos.mint.v1beta1.Params.max_supply":
x.MaxSupply = value.Interface().(string)
default:
if fd.IsExtension() {
panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.mint.v1beta1.Params"))
@ -774,6 +791,8 @@ func (x *fastReflection_Params) Mutable(fd protoreflect.FieldDescriptor) protore
panic(fmt.Errorf("field goal_bonded of message cosmos.mint.v1beta1.Params is not mutable"))
case "cosmos.mint.v1beta1.Params.blocks_per_year":
panic(fmt.Errorf("field blocks_per_year of message cosmos.mint.v1beta1.Params is not mutable"))
case "cosmos.mint.v1beta1.Params.max_supply":
panic(fmt.Errorf("field max_supply of message cosmos.mint.v1beta1.Params is not mutable"))
default:
if fd.IsExtension() {
panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.mint.v1beta1.Params"))
@ -799,6 +818,8 @@ func (x *fastReflection_Params) NewField(fd protoreflect.FieldDescriptor) protor
return protoreflect.ValueOfString("")
case "cosmos.mint.v1beta1.Params.blocks_per_year":
return protoreflect.ValueOfUint64(uint64(0))
case "cosmos.mint.v1beta1.Params.max_supply":
return protoreflect.ValueOfString("")
default:
if fd.IsExtension() {
panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.mint.v1beta1.Params"))
@ -891,6 +912,10 @@ func (x *fastReflection_Params) ProtoMethods() *protoiface.Methods {
if x.BlocksPerYear != 0 {
n += 1 + runtime.Sov(uint64(x.BlocksPerYear))
}
l = len(x.MaxSupply)
if l > 0 {
n += 1 + l + runtime.Sov(uint64(l))
}
if x.unknownFields != nil {
n += len(x.unknownFields)
}
@ -920,6 +945,13 @@ func (x *fastReflection_Params) ProtoMethods() *protoiface.Methods {
i -= len(x.unknownFields)
copy(dAtA[i:], x.unknownFields)
}
if len(x.MaxSupply) > 0 {
i -= len(x.MaxSupply)
copy(dAtA[i:], x.MaxSupply)
i = runtime.EncodeVarint(dAtA, i, uint64(len(x.MaxSupply)))
i--
dAtA[i] = 0x3a
}
if x.BlocksPerYear != 0 {
i = runtime.EncodeVarint(dAtA, i, uint64(x.BlocksPerYear))
i--
@ -1188,6 +1220,38 @@ func (x *fastReflection_Params) ProtoMethods() *protoiface.Methods {
break
}
}
case 7:
if wireType != 2 {
return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field MaxSupply", 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.MaxSupply = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := runtime.Skip(dAtA[iNdEx:])
@ -1300,6 +1364,8 @@ type Params struct {
GoalBonded string `protobuf:"bytes,5,opt,name=goal_bonded,json=goalBonded,proto3" json:"goal_bonded,omitempty"`
// expected blocks per year
BlocksPerYear uint64 `protobuf:"varint,6,opt,name=blocks_per_year,json=blocksPerYear,proto3" json:"blocks_per_year,omitempty"`
// maximum supply for the token
MaxSupply string `protobuf:"bytes,7,opt,name=max_supply,json=maxSupply,proto3" json:"max_supply,omitempty"`
}
func (x *Params) Reset() {
@ -1364,6 +1430,13 @@ func (x *Params) GetBlocksPerYear() uint64 {
return 0
}
func (x *Params) GetMaxSupply() string {
if x != nil {
return x.MaxSupply
}
return ""
}
var File_cosmos_mint_v1beta1_mint_proto protoreflect.FileDescriptor
var file_cosmos_mint_v1beta1_mint_proto_rawDesc = []byte{
@ -1386,7 +1459,7 @@ var file_cosmos_mint_v1beta1_mint_proto_rawDesc = []byte{
0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x4c, 0x65, 0x67, 0x61,
0x63, 0x79, 0x44, 0x65, 0x63, 0xd2, 0xb4, 0x2d, 0x0a, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e,
0x44, 0x65, 0x63, 0x52, 0x10, 0x61, 0x6e, 0x6e, 0x75, 0x61, 0x6c, 0x50, 0x72, 0x6f, 0x76, 0x69,
0x73, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xed, 0x03, 0x0a, 0x06, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73,
0x73, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xb9, 0x04, 0x0a, 0x06, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73,
0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x69, 0x6e, 0x74, 0x5f, 0x64, 0x65, 0x6e, 0x6f, 0x6d, 0x18, 0x01,
0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6d, 0x69, 0x6e, 0x74, 0x44, 0x65, 0x6e, 0x6f, 0x6d, 0x12,
0x6a, 0x0a, 0x15, 0x69, 0x6e, 0x66, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x72, 0x61, 0x74,
@ -1415,22 +1488,26 @@ var file_cosmos_mint_v1beta1_mint_proto_rawDesc = []byte{
0x2a, 0x01, 0x52, 0x0a, 0x67, 0x6f, 0x61, 0x6c, 0x42, 0x6f, 0x6e, 0x64, 0x65, 0x64, 0x12, 0x26,
0x0a, 0x0f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x5f, 0x70, 0x65, 0x72, 0x5f, 0x79, 0x65, 0x61,
0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0d, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x50,
0x65, 0x72, 0x59, 0x65, 0x61, 0x72, 0x3a, 0x1d, 0x8a, 0xe7, 0xb0, 0x2a, 0x18, 0x63, 0x6f, 0x73,
0x6d, 0x6f, 0x73, 0x2d, 0x73, 0x64, 0x6b, 0x2f, 0x78, 0x2f, 0x6d, 0x69, 0x6e, 0x74, 0x2f, 0x50,
0x61, 0x72, 0x61, 0x6d, 0x73, 0x42, 0xc4, 0x01, 0x0a, 0x17, 0x63, 0x6f, 0x6d, 0x2e, 0x63, 0x6f,
0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61,
0x31, 0x42, 0x09, 0x4d, 0x69, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x30,
0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x61, 0x70, 0x69,
0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x6d, 0x69, 0x6e, 0x74, 0x2f, 0x76, 0x31, 0x62,
0x65, 0x74, 0x61, 0x31, 0x3b, 0x6d, 0x69, 0x6e, 0x74, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31,
0xa2, 0x02, 0x03, 0x43, 0x4d, 0x58, 0xaa, 0x02, 0x13, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e,
0x4d, 0x69, 0x6e, 0x74, 0x2e, 0x56, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0xca, 0x02, 0x13, 0x43,
0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x5c, 0x4d, 0x69, 0x6e, 0x74, 0x5c, 0x56, 0x31, 0x62, 0x65, 0x74,
0x61, 0x31, 0xe2, 0x02, 0x1f, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x5c, 0x4d, 0x69, 0x6e, 0x74,
0x5c, 0x56, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61,
0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x15, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x3a, 0x3a, 0x4d,
0x69, 0x6e, 0x74, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x33,
0x65, 0x72, 0x59, 0x65, 0x61, 0x72, 0x12, 0x4a, 0x0a, 0x0a, 0x6d, 0x61, 0x78, 0x5f, 0x73, 0x75,
0x70, 0x70, 0x6c, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x42, 0x2b, 0xc8, 0xde, 0x1f, 0x00,
0xda, 0xde, 0x1f, 0x15, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f,
0x2f, 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x49, 0x6e, 0x74, 0xd2, 0xb4, 0x2d, 0x0a, 0x63, 0x6f, 0x73,
0x6d, 0x6f, 0x73, 0x2e, 0x49, 0x6e, 0x74, 0x52, 0x09, 0x6d, 0x61, 0x78, 0x53, 0x75, 0x70, 0x70,
0x6c, 0x79, 0x3a, 0x1d, 0x8a, 0xe7, 0xb0, 0x2a, 0x18, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2d,
0x73, 0x64, 0x6b, 0x2f, 0x78, 0x2f, 0x6d, 0x69, 0x6e, 0x74, 0x2f, 0x50, 0x61, 0x72, 0x61, 0x6d,
0x73, 0x42, 0xc4, 0x01, 0x0a, 0x17, 0x63, 0x6f, 0x6d, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73,
0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x42, 0x09, 0x4d,
0x69, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x30, 0x63, 0x6f, 0x73, 0x6d,
0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x63, 0x6f, 0x73,
0x6d, 0x6f, 0x73, 0x2f, 0x6d, 0x69, 0x6e, 0x74, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31,
0x3b, 0x6d, 0x69, 0x6e, 0x74, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0xa2, 0x02, 0x03, 0x43,
0x4d, 0x58, 0xaa, 0x02, 0x13, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x4d, 0x69, 0x6e, 0x74,
0x2e, 0x56, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0xca, 0x02, 0x13, 0x43, 0x6f, 0x73, 0x6d, 0x6f,
0x73, 0x5c, 0x4d, 0x69, 0x6e, 0x74, 0x5c, 0x56, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0xe2, 0x02,
0x1f, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x5c, 0x4d, 0x69, 0x6e, 0x74, 0x5c, 0x56, 0x31, 0x62,
0x65, 0x74, 0x61, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61,
0xea, 0x02, 0x15, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x3a, 0x3a, 0x4d, 0x69, 0x6e, 0x74, 0x3a,
0x3a, 0x56, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (

View File

@ -29,7 +29,7 @@ func (s *E2ETestSuite) TestQueryGRPC() {
&minttypes.QueryParamsResponse{},
&minttypes.QueryParamsResponse{
Params: minttypes.NewParams("stake", math.LegacyNewDecWithPrec(13, 2), math.LegacyNewDecWithPrec(100, 2),
math.LegacyNewDec(1), math.LegacyNewDecWithPrec(67, 2), (60 * 60 * 8766 / 5)),
math.LegacyNewDec(1), math.LegacyNewDecWithPrec(67, 2), (60 * 60 * 8766 / 5), math.ZeroInt()),
},
},
{

View File

@ -27,6 +27,8 @@ Ref: https://keepachangelog.com/en/1.0.0/
### Features
* [19896](https://github.com/cosmos/cosmos-sdk/pull/19896) Added a new max supply genesis param to existing params.
### Improvements
### API Breaking Changes

View File

@ -63,17 +63,21 @@ https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/mint/v1beta1/
The mint module stores its params in state with the prefix of `0x01`,
it can be updated with governance or the address with authority.
**Note:** With the latest update, the addition of the `MaxSupply` parameter allows controlling the maximum supply of tokens minted by the module.
A value of `0` indicates an unlimited supply.
* Params: `mint/params -> legacy_amino(params)`
```protobuf reference
https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/mint/v1beta1/mint.proto#L26-L59
https://github.com/cosmos/cosmos-sdk/blob/7068d0da52d954430054768b2c56aff44666933b/x/mint/proto/cosmos/mint/v1beta1/mint.proto#L26-L68
```
## Begin-Block
Minting parameters are recalculated and inflation paid at the beginning of each block.
The minting logic in the `BeginBlocker` function provides an optional feature for controlling token minting based on the maximum allowable supply (MaxSupply). This feature allows users to adjust the minting process according to their specific requirements and use cases. However, it's important to note that the MaxSupply parameter is independent of the minting process and assumes that any adjustments to the total supply, including burning tokens, are handled by external modules.
### Inflation rate calculation
Inflation rate is calculated using an "inflation calculation function" that's
@ -136,15 +140,17 @@ BlockProvision(params Params) sdk.Coin {
## Parameters
The minting module contains the following parameters:
Note: `0` indicates unlimited supply for MaxSupply param
| Key | Type | Example |
|---------------------|-----------------|------------------------|
| MintDenom | string | "uatom" |
| InflationRateChange | string (dec) | "0.130000000000000000" |
| InflationMax | string (dec) | "0.200000000000000000" |
| InflationMin | string (dec) | "0.070000000000000000" |
| GoalBonded | string (dec) | "0.670000000000000000" |
| BlocksPerYear | string (uint64) | "6311520" |
| Key | Type | Example |
|---------------------|------------------|------------------------|
| MintDenom | string | "uatom" |
| InflationRateChange | string (dec) | "0.130000000000000000" |
| InflationMax | string (dec) | "0.200000000000000000" |
| InflationMin | string (dec) | "0.070000000000000000" |
| GoalBonded | string (dec) | "0.670000000000000000" |
| BlocksPerYear | string (uint64) | "6311520" |
| MaxSupply | string (math.Int)| "0" |
## Events
@ -232,6 +238,7 @@ inflation_max: "0.200000000000000000"
inflation_min: "0.070000000000000000"
inflation_rate_change: "0.130000000000000000"
mint_denom: stake
max_supply: "0"
```
### gRPC
@ -306,7 +313,8 @@ Example Output:
"inflationMax": "200000000000000000",
"inflationMin": "70000000000000000",
"goalBonded": "670000000000000000",
"blocksPerYear": "6311520"
"blocksPerYear": "6311520",
"maxSupply": "0",
}
}
```
@ -377,7 +385,8 @@ Example Output:
"inflationMax": "200000000000000000",
"inflationMin": "70000000000000000",
"goalBonded": "670000000000000000",
"blocksPerYear": "6311520"
"blocksPerYear": "6311520",
"maxSupply": "0",
}
}
```

View File

@ -36,19 +36,43 @@ func (k Keeper) BeginBlocker(ctx context.Context, ic types.InflationCalculationF
return err
}
// update minter's inflation and annual provisions
minter.Inflation = ic(ctx, minter, params, bondedRatio)
minter.AnnualProvisions = minter.NextAnnualProvisions(params, totalStakingSupply)
if err = k.Minter.Set(ctx, minter); err != nil {
return err
}
// mint coins, update supply
// calculate minted coins
mintedCoin := minter.BlockProvision(params)
mintedCoins := sdk.NewCoins(mintedCoin)
err = k.MintCoins(ctx, mintedCoins)
if err != nil {
return err
maxSupply := params.MaxSupply
totalSupply := k.bankKeeper.GetSupply(ctx, params.MintDenom).Amount // fetch total supply from the bank module
// if maxSupply is not infinite, check against max_supply parameter
if !maxSupply.IsZero() {
if totalSupply.Add(mintedCoins.AmountOf(params.MintDenom)).GT(maxSupply) {
// calculate the difference between maxSupply and totalSupply
diff := maxSupply.Sub(totalSupply)
// mint the difference
diffCoin := sdk.NewCoin(params.MintDenom, diff)
diffCoins := sdk.NewCoins(diffCoin)
// mint coins
if err := k.MintCoins(ctx, diffCoins); err != nil {
return err
}
mintedCoins = diffCoins
}
}
// mint coins if maxSupply is infinite or total staking supply is less than maxSupply
if maxSupply.IsZero() || totalSupply.Add(mintedCoins.AmountOf(params.MintDenom)).LT(maxSupply) {
// mint coins
if err := k.MintCoins(ctx, mintedCoins); err != nil {
return err
}
}
// send the minted coins to the fee collector account

View File

@ -71,6 +71,7 @@ func (s *GenesisTestSuite) TestImportExportGenesis() {
math.LegacyNewDecWithPrec(9, 2),
math.LegacyNewDecWithPrec(69, 2),
uint64(60*60*8766/5),
math.ZeroInt(),
)
err := s.keeper.InitGenesis(s.sdkCtx, s.accountKeeper, genesisState)

View File

@ -1,6 +1,10 @@
package keeper
import "context"
import (
"context"
"cosmossdk.io/x/mint/types"
)
// Migrator is a struct for handling in-place state migrations.
type Migrator struct {
@ -21,3 +25,24 @@ func NewMigrator(k Keeper) Migrator {
func (m Migrator) Migrate1to2(ctx context.Context) error {
return nil
}
// Migrate2to3 migrates the x/mint module state from the consensus version 2 to
// version 3.
func (m Migrator) Migrate2to3(ctx context.Context) error {
params, err := m.keeper.Params.Get(ctx)
if err != nil {
return err
}
// Initialize the new MaxSupply parameter with the default value
defaultParams := types.DefaultParams()
params.MaxSupply = defaultParams.MaxSupply
// Set the updated params
err = m.keeper.Params.Set(ctx, params)
if err != nil {
return err
}
return nil
}

View File

@ -53,6 +53,7 @@ func (s *IntegrationTestSuite) TestUpdateParams() {
InflationMin: sdkmath.LegacyNewDecWithPrec(2, 2),
GoalBonded: sdkmath.LegacyNewDecWithPrec(37, 2),
BlocksPerYear: uint64(60 * 60 * 8766 / 5),
MaxSupply: sdkmath.ZeroInt(), // infinite supply
},
},
expectErr: false,

View File

@ -21,7 +21,7 @@ import (
)
// ConsensusVersion defines the current x/mint module consensus version.
const ConsensusVersion = 2
const ConsensusVersion = 3
var (
_ module.HasName = AppModule{}
@ -109,6 +109,10 @@ func (am AppModule) RegisterMigrations(mr appmodule.MigrationRegistrar) error {
return fmt.Errorf("failed to migrate x/%s from version 1 to 2: %w", types.ModuleName, err)
}
if err := mr.Register(types.ModuleName, 2, m.Migrate2to3); err != nil {
return fmt.Errorf("failed to migrate x/%s from version 2 to 3: %w", types.ModuleName, err)
}
return nil
}

View File

@ -59,4 +59,10 @@ message Params {
];
// expected blocks per year
uint64 blocks_per_year = 6;
// maximum supply for the token
string max_supply = 7 [
(cosmos_proto.scalar) = "cosmos.Int",
(gogoproto.customtype) = "cosmossdk.io/math.Int",
(gogoproto.nullable) = false
];
}

View File

@ -66,7 +66,7 @@ func RandomizedGenState(simState *module.SimulationState) {
mintDenom := simState.BondDenom
blocksPerYear := uint64(60 * 60 * 8766 / 5)
params := types.NewParams(mintDenom, inflationRateChange, inflationMax, inflationMin, goalBonded, blocksPerYear)
params := types.NewParams(mintDenom, inflationRateChange, inflationMax, inflationMin, goalBonded, blocksPerYear, math.ZeroInt())
mintGenesis := types.NewGenesisState(types.InitialMinter(inflation), params)

View File

@ -167,6 +167,20 @@ func (m *MockBankKeeper) EXPECT() *MockBankKeeperMockRecorder {
return m.recorder
}
// GetSupply mocks base method.
func (m *MockBankKeeper) GetSupply(ctx context.Context, denom string) types.Coin {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetSupply", ctx, denom)
ret0, _ := ret[0].(types.Coin)
return ret0
}
// GetSupply indicates an expected call of GetSupply.
func (mr *MockBankKeeperMockRecorder) GetSupply(ctx, denom interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSupply", reflect.TypeOf((*MockBankKeeper)(nil).GetSupply), ctx, denom)
}
// MintCoins mocks base method.
func (m *MockBankKeeper) MintCoins(ctx context.Context, name string, amt types.Coins) error {
m.ctrl.T.Helper()

View File

@ -31,4 +31,5 @@ type BankKeeper interface {
SendCoinsFromModuleToAccount(ctx context.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins) error
SendCoinsFromModuleToModule(ctx context.Context, senderModule, recipientModule string, amt sdk.Coins) error
MintCoins(ctx context.Context, name string, amt sdk.Coins) error
GetSupply(ctx context.Context, denom string) sdk.Coin
}

View File

@ -81,6 +81,8 @@ type Params struct {
GoalBonded cosmossdk_io_math.LegacyDec `protobuf:"bytes,5,opt,name=goal_bonded,json=goalBonded,proto3,customtype=cosmossdk.io/math.LegacyDec" json:"goal_bonded"`
// expected blocks per year
BlocksPerYear uint64 `protobuf:"varint,6,opt,name=blocks_per_year,json=blocksPerYear,proto3" json:"blocks_per_year,omitempty"`
// maximum supply for the token
MaxSupply cosmossdk_io_math.Int `protobuf:"bytes,7,opt,name=max_supply,json=maxSupply,proto3,customtype=cosmossdk.io/math.Int" json:"max_supply"`
}
func (m *Params) Reset() { *m = Params{} }
@ -138,34 +140,36 @@ func init() {
func init() { proto.RegisterFile("cosmos/mint/v1beta1/mint.proto", fileDescriptor_2df116d183c1e223) }
var fileDescriptor_2df116d183c1e223 = []byte{
// 426 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x93, 0x4f, 0x8b, 0xd3, 0x40,
0x18, 0xc6, 0x33, 0xee, 0x1a, 0xe8, 0xe8, 0xa2, 0x3b, 0xab, 0x90, 0x5d, 0xd9, 0xec, 0xb2, 0x07,
0x59, 0x0a, 0x4d, 0x28, 0x05, 0x0f, 0x1e, 0x6b, 0x8f, 0x16, 0x4b, 0x2e, 0xa2, 0x82, 0xe1, 0x4d,
0x32, 0xa6, 0x63, 0x93, 0x99, 0x32, 0x33, 0x96, 0xf6, 0x2b, 0x78, 0xf2, 0x63, 0x78, 0xec, 0xc1,
0x8b, 0xdf, 0xa0, 0xc7, 0xe2, 0x49, 0x3c, 0x14, 0x69, 0x0f, 0x3d, 0xf9, 0x1d, 0x24, 0x99, 0x90,
0xa2, 0x37, 0xed, 0x5e, 0x42, 0xe6, 0x79, 0xde, 0xf7, 0xf7, 0x3e, 0xcc, 0x1f, 0xec, 0xc6, 0x42,
0xe5, 0x42, 0xf9, 0x39, 0xe3, 0xda, 0x9f, 0xb4, 0x23, 0xaa, 0xa1, 0x5d, 0x2e, 0xbc, 0xb1, 0x14,
0x5a, 0x90, 0x13, 0xe3, 0x7b, 0xa5, 0x54, 0xf9, 0x67, 0x0f, 0x52, 0x91, 0x8a, 0xd2, 0xf7, 0x8b,
0x3f, 0x53, 0x7a, 0x76, 0x6a, 0x4a, 0x43, 0x63, 0x54, 0x7d, 0xc6, 0x3a, 0x86, 0x9c, 0x71, 0xe1,
0x97, 0x5f, 0x23, 0x5d, 0x7d, 0x45, 0xd8, 0xee, 0x33, 0xae, 0xa9, 0x24, 0x2f, 0x70, 0x83, 0xf1,
0x77, 0x19, 0x68, 0x26, 0xb8, 0x83, 0x2e, 0xd1, 0x75, 0xa3, 0xdb, 0x5e, 0xac, 0x2e, 0xac, 0x1f,
0xab, 0x8b, 0x47, 0x06, 0xa3, 0x92, 0x91, 0xc7, 0x84, 0x9f, 0x83, 0x1e, 0x7a, 0xcf, 0x69, 0x0a,
0xf1, 0xac, 0x47, 0xe3, 0x6f, 0x5f, 0x5a, 0xb8, 0x9a, 0xd2, 0xa3, 0x71, 0xb0, 0x63, 0x90, 0xb7,
0xf8, 0x18, 0x38, 0xff, 0x00, 0x59, 0x91, 0x65, 0xc2, 0x14, 0x13, 0x5c, 0x39, 0xb7, 0xfe, 0x17,
0x7c, 0xdf, 0xb0, 0x06, 0x35, 0xea, 0xea, 0xd7, 0x01, 0xb6, 0x07, 0x20, 0x21, 0x57, 0xe4, 0x1c,
0xe3, 0x62, 0x6b, 0xc2, 0x84, 0x72, 0x91, 0x9b, 0xf0, 0x41, 0xa3, 0x50, 0x7a, 0x85, 0x40, 0xde,
0xe3, 0x87, 0x75, 0xac, 0x50, 0x82, 0xa6, 0x61, 0x3c, 0x04, 0x9e, 0xd2, 0x2a, 0xcd, 0x93, 0x7f,
0x4e, 0xf3, 0x79, 0x3b, 0x6f, 0xa2, 0xe0, 0xa4, 0x86, 0x06, 0xa0, 0xe9, 0xb3, 0x12, 0x49, 0xde,
0xe0, 0xa3, 0xdd, 0xac, 0x1c, 0xa6, 0xce, 0xc1, 0x5e, 0x33, 0xee, 0xd6, 0xb0, 0x3e, 0x4c, 0xff,
0x82, 0x33, 0xee, 0x1c, 0xde, 0x14, 0x9c, 0x71, 0xf2, 0x12, 0xdf, 0x49, 0x05, 0x64, 0x61, 0x24,
0x78, 0x42, 0x13, 0xe7, 0xf6, 0x5e, 0x68, 0x5c, 0xa0, 0xba, 0x25, 0x89, 0x3c, 0xc6, 0xf7, 0xa2,
0x4c, 0xc4, 0x23, 0x15, 0x8e, 0xa9, 0x0c, 0x67, 0x14, 0xa4, 0x63, 0x5f, 0xa2, 0xeb, 0xc3, 0xe0,
0xc8, 0xc8, 0x03, 0x2a, 0x5f, 0x51, 0x90, 0x4f, 0xcf, 0x3f, 0x6e, 0xe7, 0x4d, 0xc7, 0x90, 0x5a,
0x2a, 0x19, 0xf9, 0x53, 0xf3, 0x20, 0xcc, 0x21, 0x77, 0x3b, 0x8b, 0xb5, 0x8b, 0x96, 0x6b, 0x17,
0xfd, 0x5c, 0xbb, 0xe8, 0xd3, 0xc6, 0xb5, 0x96, 0x1b, 0xd7, 0xfa, 0xbe, 0x71, 0xad, 0xd7, 0xa7,
0x7f, 0x84, 0xab, 0xba, 0xf4, 0x6c, 0x4c, 0x55, 0x64, 0x97, 0xf7, 0xbc, 0xf3, 0x3b, 0x00, 0x00,
0xff, 0xff, 0xcd, 0x30, 0x64, 0xe0, 0x62, 0x03, 0x00, 0x00,
// 461 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x93, 0x4f, 0x6b, 0xd4, 0x40,
0x18, 0xc6, 0x37, 0xba, 0xae, 0xec, 0x68, 0xd1, 0x4e, 0x2d, 0x4c, 0x2b, 0x4d, 0x4b, 0x0f, 0x52,
0x2a, 0xdd, 0xb0, 0x14, 0x3c, 0x78, 0x5c, 0xf7, 0x52, 0xb1, 0xb8, 0xc4, 0x83, 0xa8, 0xe0, 0xf0,
0x6e, 0x32, 0xa6, 0xe3, 0x66, 0x66, 0xc2, 0xcc, 0xb4, 0x64, 0xbf, 0x82, 0x27, 0x3f, 0x86, 0xc7,
0x1e, 0xbc, 0xf4, 0x1b, 0xf4, 0x58, 0x3c, 0x89, 0x87, 0x22, 0xbb, 0x87, 0x7e, 0x0d, 0xc9, 0x4c,
0x48, 0xfd, 0x73, 0xd2, 0x7a, 0x09, 0xc9, 0xf3, 0xcc, 0xfb, 0x7b, 0x1e, 0xc2, 0xbc, 0x28, 0x4c,
0x94, 0x11, 0xca, 0x44, 0x82, 0x4b, 0x1b, 0x1d, 0xf5, 0xc7, 0xcc, 0x42, 0xdf, 0x7d, 0xf4, 0x0a,
0xad, 0xac, 0xc2, 0x4b, 0xde, 0xef, 0x39, 0xa9, 0xf6, 0x57, 0xef, 0x65, 0x2a, 0x53, 0xce, 0x8f,
0xaa, 0x37, 0x7f, 0x74, 0x75, 0xc5, 0x1f, 0xa5, 0xde, 0xa8, 0xe7, 0xbc, 0xb5, 0x08, 0x82, 0x4b,
0x15, 0xb9, 0xa7, 0x97, 0x36, 0x4f, 0x02, 0xd4, 0xd9, 0xe7, 0xd2, 0x32, 0x8d, 0x9f, 0xa3, 0x2e,
0x97, 0xef, 0x72, 0xb0, 0x5c, 0x49, 0x12, 0x6c, 0x04, 0x5b, 0xdd, 0x41, 0xff, 0xf4, 0x7c, 0xbd,
0xf5, 0xed, 0x7c, 0xfd, 0xbe, 0xc7, 0x98, 0x74, 0xd2, 0xe3, 0x2a, 0x12, 0x60, 0x0f, 0x7a, 0xcf,
0x58, 0x06, 0xc9, 0x74, 0xc8, 0x92, 0x2f, 0x9f, 0x77, 0x50, 0x9d, 0x32, 0x64, 0x49, 0x7c, 0xc9,
0xc0, 0x6f, 0xd1, 0x22, 0x48, 0x79, 0x08, 0x79, 0xd5, 0xe5, 0x88, 0x1b, 0xae, 0xa4, 0x21, 0xd7,
0xfe, 0x15, 0x7c, 0xd7, 0xb3, 0x46, 0x0d, 0x6a, 0xf3, 0xa4, 0x8d, 0x3a, 0x23, 0xd0, 0x20, 0x0c,
0x5e, 0x43, 0xa8, 0xfa, 0x35, 0x34, 0x65, 0x52, 0x09, 0x5f, 0x3e, 0xee, 0x56, 0xca, 0xb0, 0x12,
0xf0, 0x7b, 0xb4, 0xdc, 0xd4, 0xa2, 0x1a, 0x2c, 0xa3, 0xc9, 0x01, 0xc8, 0x8c, 0xd5, 0x6d, 0x1e,
0xfd, 0x75, 0x9b, 0x4f, 0x17, 0xc7, 0xdb, 0x41, 0xbc, 0xd4, 0x40, 0x63, 0xb0, 0xec, 0x89, 0x43,
0xe2, 0x37, 0x68, 0xe1, 0x32, 0x4b, 0x40, 0x49, 0xae, 0x5f, 0x29, 0xe3, 0x76, 0x03, 0xdb, 0x87,
0xf2, 0x37, 0x38, 0x97, 0xa4, 0xfd, 0xbf, 0xe0, 0x5c, 0xe2, 0x97, 0xe8, 0x56, 0xa6, 0x20, 0xa7,
0x63, 0x25, 0x53, 0x96, 0x92, 0x1b, 0x57, 0x42, 0xa3, 0x0a, 0x35, 0x70, 0x24, 0xfc, 0x00, 0xdd,
0x19, 0xe7, 0x2a, 0x99, 0x18, 0x5a, 0x30, 0x4d, 0xa7, 0x0c, 0x34, 0xe9, 0x6c, 0x04, 0x5b, 0xed,
0x78, 0xc1, 0xcb, 0x23, 0xa6, 0x5f, 0x31, 0xd0, 0xf8, 0x29, 0x42, 0x02, 0x4a, 0x6a, 0x0e, 0x8b,
0x22, 0x9f, 0x92, 0x9b, 0x2e, 0xff, 0x61, 0x9d, 0xbf, 0xfc, 0x67, 0xfe, 0x9e, 0xb4, 0x3f, 0x25,
0xef, 0x49, 0x1b, 0x77, 0x05, 0x94, 0x2f, 0xdc, 0xf4, 0xe3, 0xb5, 0x0f, 0x17, 0xc7, 0xdb, 0xc4,
0x7b, 0x3b, 0x26, 0x9d, 0x44, 0xa5, 0x5f, 0x2e, 0x7f, 0x61, 0x06, 0xbb, 0xa7, 0xb3, 0x30, 0x38,
0x9b, 0x85, 0xc1, 0xf7, 0x59, 0x18, 0x7c, 0x9c, 0x87, 0xad, 0xb3, 0x79, 0xd8, 0xfa, 0x3a, 0x0f,
0x5b, 0xaf, 0x57, 0x7e, 0x09, 0xaa, 0xa7, 0xec, 0xb4, 0x60, 0x66, 0xdc, 0x71, 0x3b, 0xb3, 0xfb,
0x23, 0x00, 0x00, 0xff, 0xff, 0x5e, 0xda, 0x10, 0x60, 0xae, 0x03, 0x00, 0x00,
}
func (m *Minter) Marshal() (dAtA []byte, err error) {
@ -231,6 +235,16 @@ func (m *Params) MarshalToSizedBuffer(dAtA []byte) (int, error) {
_ = i
var l int
_ = l
{
size := m.MaxSupply.Size()
i -= size
if _, err := m.MaxSupply.MarshalTo(dAtA[i:]); err != nil {
return 0, err
}
i = encodeVarintMint(dAtA, i, uint64(size))
}
i--
dAtA[i] = 0x3a
if m.BlocksPerYear != 0 {
i = encodeVarintMint(dAtA, i, uint64(m.BlocksPerYear))
i--
@ -331,6 +345,8 @@ func (m *Params) Size() (n int) {
if m.BlocksPerYear != 0 {
n += 1 + sovMint(uint64(m.BlocksPerYear))
}
l = m.MaxSupply.Size()
n += 1 + l + sovMint(uint64(l))
return n
}
@ -674,6 +690,40 @@ func (m *Params) Unmarshal(dAtA []byte) error {
break
}
}
case 7:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field MaxSupply", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowMint
}
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 ErrInvalidLengthMint
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthMint
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
if err := m.MaxSupply.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipMint(dAtA[iNdEx:])

View File

@ -11,7 +11,7 @@ import (
)
// NewParams returns Params instance with the given values.
func NewParams(mintDenom string, inflationRateChange, inflationMax, inflationMin, goalBonded math.LegacyDec, blocksPerYear uint64) Params {
func NewParams(mintDenom string, inflationRateChange, inflationMax, inflationMin, goalBonded math.LegacyDec, blocksPerYear uint64, maxSupply math.Int) Params {
return Params{
MintDenom: mintDenom,
InflationRateChange: inflationRateChange,
@ -19,6 +19,7 @@ func NewParams(mintDenom string, inflationRateChange, inflationMax, inflationMin
InflationMin: inflationMin,
GoalBonded: goalBonded,
BlocksPerYear: blocksPerYear,
MaxSupply: maxSupply,
}
}
@ -31,6 +32,7 @@ func DefaultParams() Params {
InflationMin: math.LegacyNewDecWithPrec(7, 2),
GoalBonded: math.LegacyNewDecWithPrec(67, 2),
BlocksPerYear: uint64(60 * 60 * 8766 / 5), // assuming 5 second block times
MaxSupply: math.ZeroInt(), // assuming zero is infinite
}
}
@ -54,6 +56,9 @@ func (p Params) Validate() error {
if err := validateBlocksPerYear(p.BlocksPerYear); err != nil {
return err
}
if err := validateMaxSupply(p.MaxSupply); err != nil {
return err
}
if p.InflationMax.LT(p.InflationMin) {
return fmt.Errorf(
"max inflation (%s) must be greater than or equal to min inflation (%s)",
@ -168,3 +173,16 @@ func validateBlocksPerYear(i interface{}) error {
return nil
}
func validateMaxSupply(i interface{}) error {
v, ok := i.(math.Int)
if !ok {
return fmt.Errorf("invalid parameter type: %T", i)
}
if v.IsNegative() {
return fmt.Errorf("max supply must be positive: %d", v)
}
return nil
}