feat(x/mint)!: Replace InflationCalculationFn with MintFn + simple epoch minting (#20363)

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: Marko <marko@baricevic.me>
This commit is contained in:
Facundo Medica 2024-06-11 14:27:20 +02:00 committed by GitHub
parent fbd3b75c5a
commit 150ca963f2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
37 changed files with 949 additions and 269 deletions

View File

@ -10,6 +10,7 @@ import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoiface "google.golang.org/protobuf/runtime/protoiface"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
_ "google.golang.org/protobuf/types/known/anypb"
io "io"
reflect "reflect"
sync "sync"
@ -19,6 +20,7 @@ var (
md_Minter protoreflect.MessageDescriptor
fd_Minter_inflation protoreflect.FieldDescriptor
fd_Minter_annual_provisions protoreflect.FieldDescriptor
fd_Minter_data protoreflect.FieldDescriptor
)
func init() {
@ -26,6 +28,7 @@ func init() {
md_Minter = File_cosmos_mint_v1beta1_mint_proto.Messages().ByName("Minter")
fd_Minter_inflation = md_Minter.Fields().ByName("inflation")
fd_Minter_annual_provisions = md_Minter.Fields().ByName("annual_provisions")
fd_Minter_data = md_Minter.Fields().ByName("data")
}
var _ protoreflect.Message = (*fastReflection_Minter)(nil)
@ -105,6 +108,12 @@ func (x *fastReflection_Minter) Range(f func(protoreflect.FieldDescriptor, proto
return
}
}
if len(x.Data) != 0 {
value := protoreflect.ValueOfBytes(x.Data)
if !f(fd_Minter_data, value) {
return
}
}
}
// Has reports whether a field is populated.
@ -124,6 +133,8 @@ func (x *fastReflection_Minter) Has(fd protoreflect.FieldDescriptor) bool {
return x.Inflation != ""
case "cosmos.mint.v1beta1.Minter.annual_provisions":
return x.AnnualProvisions != ""
case "cosmos.mint.v1beta1.Minter.data":
return len(x.Data) != 0
default:
if fd.IsExtension() {
panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.mint.v1beta1.Minter"))
@ -144,6 +155,8 @@ func (x *fastReflection_Minter) Clear(fd protoreflect.FieldDescriptor) {
x.Inflation = ""
case "cosmos.mint.v1beta1.Minter.annual_provisions":
x.AnnualProvisions = ""
case "cosmos.mint.v1beta1.Minter.data":
x.Data = nil
default:
if fd.IsExtension() {
panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.mint.v1beta1.Minter"))
@ -166,6 +179,9 @@ func (x *fastReflection_Minter) Get(descriptor protoreflect.FieldDescriptor) pro
case "cosmos.mint.v1beta1.Minter.annual_provisions":
value := x.AnnualProvisions
return protoreflect.ValueOfString(value)
case "cosmos.mint.v1beta1.Minter.data":
value := x.Data
return protoreflect.ValueOfBytes(value)
default:
if descriptor.IsExtension() {
panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.mint.v1beta1.Minter"))
@ -190,6 +206,8 @@ func (x *fastReflection_Minter) Set(fd protoreflect.FieldDescriptor, value proto
x.Inflation = value.Interface().(string)
case "cosmos.mint.v1beta1.Minter.annual_provisions":
x.AnnualProvisions = value.Interface().(string)
case "cosmos.mint.v1beta1.Minter.data":
x.Data = value.Bytes()
default:
if fd.IsExtension() {
panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.mint.v1beta1.Minter"))
@ -214,6 +232,8 @@ func (x *fastReflection_Minter) Mutable(fd protoreflect.FieldDescriptor) protore
panic(fmt.Errorf("field inflation of message cosmos.mint.v1beta1.Minter is not mutable"))
case "cosmos.mint.v1beta1.Minter.annual_provisions":
panic(fmt.Errorf("field annual_provisions of message cosmos.mint.v1beta1.Minter is not mutable"))
case "cosmos.mint.v1beta1.Minter.data":
panic(fmt.Errorf("field data of message cosmos.mint.v1beta1.Minter is not mutable"))
default:
if fd.IsExtension() {
panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.mint.v1beta1.Minter"))
@ -231,6 +251,8 @@ func (x *fastReflection_Minter) NewField(fd protoreflect.FieldDescriptor) protor
return protoreflect.ValueOfString("")
case "cosmos.mint.v1beta1.Minter.annual_provisions":
return protoreflect.ValueOfString("")
case "cosmos.mint.v1beta1.Minter.data":
return protoreflect.ValueOfBytes(nil)
default:
if fd.IsExtension() {
panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.mint.v1beta1.Minter"))
@ -308,6 +330,10 @@ func (x *fastReflection_Minter) ProtoMethods() *protoiface.Methods {
if l > 0 {
n += 1 + l + runtime.Sov(uint64(l))
}
l = len(x.Data)
if l > 0 {
n += 1 + l + runtime.Sov(uint64(l))
}
if x.unknownFields != nil {
n += len(x.unknownFields)
}
@ -337,6 +363,13 @@ func (x *fastReflection_Minter) ProtoMethods() *protoiface.Methods {
i -= len(x.unknownFields)
copy(dAtA[i:], x.unknownFields)
}
if len(x.Data) > 0 {
i -= len(x.Data)
copy(dAtA[i:], x.Data)
i = runtime.EncodeVarint(dAtA, i, uint64(len(x.Data)))
i--
dAtA[i] = 0x1a
}
if len(x.AnnualProvisions) > 0 {
i -= len(x.AnnualProvisions)
copy(dAtA[i:], x.AnnualProvisions)
@ -464,6 +497,40 @@ func (x *fastReflection_Minter) ProtoMethods() *protoiface.Methods {
}
x.AnnualProvisions = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 3:
if wireType != 2 {
return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field Data", wireType)
}
var byteLen int
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++
byteLen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if byteLen < 0 {
return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength
}
postIndex := iNdEx + byteLen
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.Data = append(x.Data[:0], dAtA[iNdEx:postIndex]...)
if x.Data == nil {
x.Data = []byte{}
}
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := runtime.Skip(dAtA[iNdEx:])
@ -1310,6 +1377,9 @@ type Minter struct {
Inflation string `protobuf:"bytes,1,opt,name=inflation,proto3" json:"inflation,omitempty"`
// current annual expected provisions
AnnualProvisions string `protobuf:"bytes,2,opt,name=annual_provisions,json=annualProvisions,proto3" json:"annual_provisions,omitempty"`
// data is any custom data that the user might want to put in the minter, to
// be used in the minting process.
Data []byte `protobuf:"bytes,3,opt,name=data,proto3" json:"data,omitempty"`
}
func (x *Minter) Reset() {
@ -1346,6 +1416,13 @@ func (x *Minter) GetAnnualProvisions() string {
return ""
}
func (x *Minter) GetData() []byte {
if x != nil {
return x.Data
}
return nil
}
// Params defines the parameters for the x/mint module.
type Params struct {
state protoimpl.MessageState
@ -1447,67 +1524,70 @@ var file_cosmos_mint_v1beta1_mint_proto_rawDesc = []byte{
0x2f, 0x67, 0x6f, 0x67, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x19, 0x63, 0x6f, 0x73,
0x6d, 0x6f, 0x73, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x11, 0x61, 0x6d, 0x69, 0x6e, 0x6f, 0x2f, 0x61, 0x6d,
0x69, 0x6e, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xb9, 0x01, 0x0a, 0x06, 0x4d, 0x69,
0x6e, 0x74, 0x65, 0x72, 0x12, 0x4f, 0x0a, 0x09, 0x69, 0x6e, 0x66, 0x6c, 0x61, 0x74, 0x69, 0x6f,
0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x31, 0xc8, 0xde, 0x1f, 0x00, 0xda, 0xde, 0x1f,
0x1b, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 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, 0x09, 0x69, 0x6e, 0x66, 0x6c,
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x5e, 0x0a, 0x11, 0x61, 0x6e, 0x6e, 0x75, 0x61, 0x6c, 0x5f,
0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
0x42, 0x31, 0xc8, 0xde, 0x1f, 0x00, 0xda, 0xde, 0x1f, 0x1b, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73,
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, 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,
0x65, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x36,
0x69, 0x6e, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x19, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x61, 0x6e, 0x79, 0x2e, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x22, 0xcd, 0x01, 0x0a, 0x06, 0x4d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x12,
0x4f, 0x0a, 0x09, 0x69, 0x6e, 0x66, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01,
0x28, 0x09, 0x42, 0x31, 0xc8, 0xde, 0x1f, 0x00, 0xda, 0xde, 0x1f, 0x1b, 0x63, 0x6f, 0x73, 0x6d,
0x6f, 0x73, 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, 0x09, 0x69, 0x6e, 0x66, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e,
0x12, 0x5e, 0x0a, 0x11, 0x61, 0x6e, 0x6e, 0x75, 0x61, 0x6c, 0x5f, 0x70, 0x72, 0x6f, 0x76, 0x69,
0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x31, 0xc8, 0xde, 0x1f,
0x00, 0xda, 0xde, 0x1f, 0x1b, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 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,
0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04,
0x64, 0x61, 0x74, 0x61, 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, 0x65,
0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x36, 0xc8,
0xde, 0x1f, 0x00, 0xda, 0xde, 0x1f, 0x1b, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 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,
0xa8, 0xe7, 0xb0, 0x2a, 0x01, 0x52, 0x13, 0x69, 0x6e, 0x66, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e,
0x52, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x5b, 0x0a, 0x0d, 0x69, 0x6e,
0x66, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x61, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28,
0x09, 0x42, 0x36, 0xc8, 0xde, 0x1f, 0x00, 0xda, 0xde, 0x1f, 0x1b, 0x63, 0x6f, 0x73, 0x6d, 0x6f,
0x73, 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, 0xa8, 0xe7, 0xb0, 0x2a, 0x01, 0x52, 0x0c, 0x69, 0x6e, 0x66, 0x6c, 0x61,
0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x61, 0x78, 0x12, 0x5b, 0x0a, 0x0d, 0x69, 0x6e, 0x66, 0x6c, 0x61,
0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x42, 0x36,
0xc8, 0xde, 0x1f, 0x00, 0xda, 0xde, 0x1f, 0x1b, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 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, 0xa8, 0xe7, 0xb0, 0x2a, 0x01, 0x52, 0x13, 0x69, 0x6e, 0x66, 0x6c, 0x61, 0x74, 0x69, 0x6f,
0x6e, 0x52, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x5b, 0x0a, 0x0d, 0x69,
0x6e, 0x66, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x61, 0x78, 0x18, 0x03, 0x20, 0x01,
0x28, 0x09, 0x42, 0x36, 0xc8, 0xde, 0x1f, 0x00, 0xda, 0xde, 0x1f, 0x1b, 0x63, 0x6f, 0x73, 0x6d,
0x6f, 0x73, 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, 0xa8, 0xe7, 0xb0, 0x2a, 0x01, 0x52, 0x0c, 0x69, 0x6e, 0x66, 0x6c,
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x61, 0x78, 0x12, 0x5b, 0x0a, 0x0d, 0x69, 0x6e, 0x66, 0x6c,
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x42,
0x36, 0xc8, 0xde, 0x1f, 0x00, 0xda, 0xde, 0x1f, 0x1b, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 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, 0xa8, 0xe7, 0xb0, 0x2a, 0x01, 0x52, 0x0c, 0x69, 0x6e, 0x66, 0x6c, 0x61, 0x74, 0x69,
0x6f, 0x6e, 0x4d, 0x69, 0x6e, 0x12, 0x57, 0x0a, 0x0b, 0x67, 0x6f, 0x61, 0x6c, 0x5f, 0x62, 0x6f,
0x6e, 0x64, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x42, 0x36, 0xc8, 0xde, 0x1f, 0x00,
0xda, 0xde, 0x1f, 0x1b, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 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, 0xa8, 0xe7, 0xb0,
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, 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,
0x63, 0xa8, 0xe7, 0xb0, 0x2a, 0x01, 0x52, 0x0c, 0x69, 0x6e, 0x66, 0x6c, 0x61, 0x74, 0x69, 0x6f,
0x6e, 0x4d, 0x69, 0x6e, 0x12, 0x57, 0x0a, 0x0b, 0x67, 0x6f, 0x61, 0x6c, 0x5f, 0x62, 0x6f, 0x6e,
0x64, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x42, 0x36, 0xc8, 0xde, 0x1f, 0x00, 0xda,
0xde, 0x1f, 0x1b, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 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, 0xa8, 0xe7, 0xb0, 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, 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

@ -171,7 +171,7 @@ type SimApp struct {
ConsensusParamsKeeper consensusparamkeeper.Keeper
CircuitKeeper circuitkeeper.Keeper
PoolKeeper poolkeeper.Keeper
EpochsKeeper epochskeeper.Keeper
EpochsKeeper *epochskeeper.Keeper
// managers
ModuleManager *module.Manager

View File

@ -93,7 +93,7 @@ type SimApp struct {
ConsensusParamsKeeper consensuskeeper.Keeper
CircuitBreakerKeeper circuitkeeper.Keeper
PoolKeeper poolkeeper.Keeper
EpochsKeeper epochskeeper.Keeper
EpochsKeeper *epochskeeper.Keeper
// simulation manager
sm *module.SimulationManager
@ -111,7 +111,8 @@ func init() {
// AppConfig returns the default app config.
func AppConfig() depinject.Config {
return depinject.Configs(
appConfig, // Alternatively use appconfig.LoadYAML(AppConfigYAML)
appConfig, // Alternatively use appconfig.LoadYAML(AppConfigYAML)
depinject.Provide(ProvideExampleMintFn), // optional: override the mint module's mint function with epoched minting
)
}
@ -174,8 +175,7 @@ func NewSimApp(
//
// For providing a custom inflation function for x/mint add here your
// custom function that implements the minttypes.InflationCalculationFn
// interface.
// custom function that implements the minttypes.MintFn interface.
),
)
)

View File

@ -19,7 +19,7 @@ require (
cosmossdk.io/x/bank v0.0.0-20240226161501-23359a0b6d91
cosmossdk.io/x/circuit v0.0.0-20230613133644-0a778132a60f
cosmossdk.io/x/distribution v0.0.0-20240227221813-a248d05f70f4
cosmossdk.io/x/epochs v0.0.0-00010101000000-000000000000
cosmossdk.io/x/epochs v0.0.0-20240522060652-a1ae4c3e0337
cosmossdk.io/x/evidence v0.0.0-20230613133644-0a778132a60f
cosmossdk.io/x/feegrant v0.0.0-20230613133644-0a778132a60f
cosmossdk.io/x/gov v0.0.0-20231113122742-912390d5fc4a

125
simapp/mint_fn.go Normal file
View File

@ -0,0 +1,125 @@
package simapp
import (
"context"
"encoding/binary"
"cosmossdk.io/core/appmodule"
"cosmossdk.io/core/event"
"cosmossdk.io/math"
authtypes "cosmossdk.io/x/auth/types"
banktypes "cosmossdk.io/x/bank/types"
minttypes "cosmossdk.io/x/mint/types"
stakingtypes "cosmossdk.io/x/staking/types"
sdk "github.com/cosmos/cosmos-sdk/types"
)
type MintBankKeeper interface {
MintCoins(ctx context.Context, moduleName string, coins sdk.Coins) error
SendCoinsFromModuleToModule(ctx context.Context, senderModule string, recipientModule string, amt sdk.Coins) error
}
// ProvideExampleMintFn returns the function used in x/mint's endblocker to mint new tokens.
// Note that this function can not have the mint keeper as a parameter because it would create a cyclic dependency.
func ProvideExampleMintFn(bankKeeper MintBankKeeper) minttypes.MintFn {
return func(ctx context.Context, env appmodule.Environment, minter *minttypes.Minter, epochID string, epochNumber int64) error {
// in this example we ignore epochNumber as we don't care what epoch we are in, we just assume we are being called every minute.
if epochID != "minute" {
return nil
}
var stakingParams stakingtypes.QueryParamsResponse
err := env.QueryRouterService.InvokeTyped(ctx, &stakingtypes.QueryParamsRequest{}, &stakingParams)
if err != nil {
return err
}
var bankSupply banktypes.QuerySupplyOfResponse
err = env.QueryRouterService.InvokeTyped(ctx, &banktypes.QuerySupplyOfRequest{Denom: stakingParams.Params.BondDenom}, &bankSupply)
if err != nil {
return err
}
stakingTokenSupply := bankSupply.Amount
var mintParams minttypes.QueryParamsResponse
err = env.QueryRouterService.InvokeTyped(ctx, &minttypes.QueryParamsRequest{}, &mintParams)
if err != nil {
return err
}
var stakingPool stakingtypes.QueryPoolResponse
err = env.QueryRouterService.InvokeTyped(ctx, &stakingtypes.QueryPoolRequest{}, &stakingPool)
if err != nil {
return err
}
// bondedRatio
bondedRatio := math.LegacyNewDecFromInt(stakingPool.Pool.BondedTokens).QuoInt(stakingTokenSupply.Amount)
minter.Inflation = minter.NextInflationRate(mintParams.Params, bondedRatio)
minter.AnnualProvisions = minter.NextAnnualProvisions(mintParams.Params, stakingTokenSupply.Amount)
// to get a more accurate amount of tokens minted, we get, and later store, last minting time.
// if this is the first time minting, we initialize the minter.Data with the current time - 60s
// to mint tokens at the beginning. Note: this is a custom behavior to avoid breaking tests.
if minter.Data == nil {
minter.Data = make([]byte, 8)
binary.BigEndian.PutUint64(minter.Data, (uint64)(env.HeaderService.HeaderInfo(ctx).Time.Unix()-60))
}
lastMint := binary.BigEndian.Uint64(minter.Data)
binary.BigEndian.PutUint64(minter.Data, (uint64)(env.HeaderService.HeaderInfo(ctx).Time.Unix()))
// calculate the amount of tokens to mint, based on the time since the last mint
secsSinceLastMint := env.HeaderService.HeaderInfo(ctx).Time.Unix() - (int64)(lastMint)
provisionAmt := minter.AnnualProvisions.QuoInt64(31536000).MulInt64(secsSinceLastMint) // 31536000 = seconds in a year
mintedCoin := sdk.NewCoin(mintParams.Params.MintDenom, provisionAmt.TruncateInt())
maxSupply := mintParams.Params.MaxSupply
totalSupply := stakingTokenSupply.Amount
if !maxSupply.IsZero() {
// supply is not infinite, check the amount to mint
remainingSupply := maxSupply.Sub(totalSupply)
if remainingSupply.LTE(math.ZeroInt()) {
// max supply reached, no new tokens will be minted
// also handles the case where totalSupply > maxSupply
return nil
}
// if the amount to mint is greater than the remaining supply, mint the remaining supply
if mintedCoin.Amount.GT(remainingSupply) {
mintedCoin.Amount = remainingSupply
}
}
if mintedCoin.Amount.IsZero() {
// skip as no coins need to be minted
return nil
}
mintedCoins := sdk.NewCoins(mintedCoin)
if err := bankKeeper.MintCoins(ctx, minttypes.ModuleName, mintedCoins); err != nil {
return err
}
// Example of custom send while minting
// Send some tokens to a "team account"
// if err = bankKeeper.SendCoinsFromModuleToAccount(ctx, minttypes.ModuleName, ... ); err != nil {
// return err
// }
if err = bankKeeper.SendCoinsFromModuleToModule(ctx, minttypes.ModuleName, authtypes.FeeCollectorName, mintedCoins); err != nil {
return err
}
return env.EventService.EventManager(ctx).EmitKV(
minttypes.EventTypeMint,
event.NewAttribute(minttypes.AttributeKeyBondedRatio, bondedRatio.String()),
event.NewAttribute(minttypes.AttributeKeyInflation, minter.Inflation.String()),
event.NewAttribute(minttypes.AttributeKeyAnnualProvisions, minter.AnnualProvisions.String()),
event.NewAttribute(sdk.AttributeKeyAmount, mintedCoin.Amount.String()),
)
}
}

View File

@ -35,7 +35,7 @@ func (s *E2ETestSuite) TestTotalSupplyGRPCHandler() {
&types.QueryTotalSupplyResponse{
Supply: sdk.NewCoins(
sdk.NewCoin(fmt.Sprintf("%stoken", val.GetMoniker()), s.cfg.AccountTokens),
sdk.NewCoin(s.cfg.BondDenom, s.cfg.StakingTokens.Add(math.NewInt(3))),
sdk.NewCoin(s.cfg.BondDenom, s.cfg.StakingTokens.Add(math.NewInt(47))),
),
Pagination: &query.PageResponse{
Total: 2,
@ -50,7 +50,7 @@ func (s *E2ETestSuite) TestTotalSupplyGRPCHandler() {
},
&types.QuerySupplyOfResponse{},
&types.QuerySupplyOfResponse{
Amount: sdk.NewCoin(s.cfg.BondDenom, s.cfg.StakingTokens.Add(math.NewInt(3))),
Amount: sdk.NewCoin(s.cfg.BondDenom, s.cfg.StakingTokens.Add(math.NewInt(47))),
},
},
{
@ -61,7 +61,7 @@ func (s *E2ETestSuite) TestTotalSupplyGRPCHandler() {
},
&types.QuerySupplyOfResponse{},
&types.QuerySupplyOfResponse{
Amount: sdk.NewCoin(s.cfg.BondDenom, s.cfg.StakingTokens.Add(math.NewInt(6))),
Amount: sdk.NewCoin(s.cfg.BondDenom, s.cfg.StakingTokens.Add(math.NewInt(47))),
},
},
{
@ -72,7 +72,7 @@ func (s *E2ETestSuite) TestTotalSupplyGRPCHandler() {
},
&types.QuerySupplyOfResponse{},
&types.QuerySupplyOfResponse{
Amount: sdk.NewCoin(s.cfg.BondDenom, s.cfg.StakingTokens.Add(math.NewInt(3))),
Amount: sdk.NewCoin(s.cfg.BondDenom, s.cfg.StakingTokens.Add(math.NewInt(47))),
},
},
{

View File

@ -116,7 +116,7 @@ func (s *GRPCQueryTestSuite) TestQueryOutstandingRewardsGRPC() {
val := s.network.GetValidators()[0]
baseURL := val.GetAPIAddress()
rewards, err := sdk.ParseDecCoins("5.88stake")
rewards, err := sdk.ParseDecCoins("46.06stake")
s.Require().NoError(err)
testCases := []struct {
@ -170,7 +170,7 @@ func (s *GRPCQueryTestSuite) TestQueryValidatorCommissionGRPC() {
val := s.network.GetValidators()[0]
baseURL := val.GetAPIAddress()
commission, err := sdk.ParseDecCoins("2.94stake")
commission, err := sdk.ParseDecCoins("23.03stake")
s.Require().NoError(err)
testCases := []struct {
@ -283,7 +283,7 @@ func (s *GRPCQueryTestSuite) TestQueryDelegatorRewardsGRPC() {
val := s.network.GetValidators()[0]
baseURL := val.GetAPIAddress()
rewards, err := sdk.ParseDecCoins("2.94stake")
rewards, err := sdk.ParseDecCoins("23.03stake")
s.Require().NoError(err)
testCases := []struct {

View File

@ -65,7 +65,7 @@ require (
cosmossdk.io/client/v2 v2.0.0-20230630094428-02b760776860 // indirect
cosmossdk.io/core/testing v0.0.0-00010101000000-000000000000 // indirect
cosmossdk.io/x/circuit v0.0.0-20230613133644-0a778132a60f // indirect
cosmossdk.io/x/epochs v0.0.0-00010101000000-000000000000 // indirect
cosmossdk.io/x/epochs v0.0.0-20240522060652-a1ae4c3e0337 // indirect
filippo.io/edwards25519 v1.1.0 // indirect
github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect
github.com/99designs/keyring v1.2.2 // indirect

View File

@ -39,7 +39,7 @@ type ModuleInputs struct {
type ModuleOutputs struct {
depinject.Out
EpochKeeper keeper.Keeper
EpochKeeper *keeper.Keeper
Module appmodule.AppModule
}
@ -49,7 +49,7 @@ func ProvideModule(in ModuleInputs) ModuleOutputs {
return ModuleOutputs{EpochKeeper: k, Module: m}
}
func InvokeSetHooks(keeper keeper.Keeper, hooks map[string]types.EpochHooksWrapper) error {
func InvokeSetHooks(keeper *keeper.Keeper, hooks map[string]types.EpochHooksWrapper) error {
if hooks == nil {
return nil
}

View File

@ -93,9 +93,10 @@ func (s *KeeperTestSuite) TestEpochLifeCycle() {
allEpochs, err := s.EpochsKeeper.AllEpochInfos(s.Ctx)
s.Require().NoError(err)
s.Require().Len(allEpochs, 4)
s.Require().Len(allEpochs, 5)
s.Require().Equal(allEpochs[0].Identifier, "day") // alphabetical order
s.Require().Equal(allEpochs[1].Identifier, "hour")
s.Require().Equal(allEpochs[2].Identifier, "monthly")
s.Require().Equal(allEpochs[3].Identifier, "week")
s.Require().Equal(allEpochs[2].Identifier, "minute")
s.Require().Equal(allEpochs[3].Identifier, "monthly")
s.Require().Equal(allEpochs[4].Identifier, "week")
}

View File

@ -18,7 +18,7 @@ func TestEpochsExportGenesis(t *testing.T) {
genesis, err := epochsKeeper.ExportGenesis(ctx)
require.NoError(t, err)
require.Len(t, genesis.Epochs, 3)
require.Len(t, genesis.Epochs, 4)
expectedEpochs := types.DefaultGenesis().Epochs
for i := 0; i < len(expectedEpochs); i++ {

View File

@ -11,7 +11,7 @@ func (s *KeeperTestSuite) TestQueryEpochInfos() {
// Check that querying epoch infos on default genesis returns the default genesis epoch infos
epochInfosResponse, err := queryClient.EpochInfos(s.Ctx, &types.QueryEpochsInfoRequest{})
s.Require().NoError(err)
s.Require().Len(epochInfosResponse.Epochs, 3)
s.Require().Len(epochInfosResponse.Epochs, 4)
expectedEpochs := types.DefaultGenesis().Epochs
for id := range expectedEpochs {
expectedEpochs[id].StartTime = s.Ctx.BlockTime()

View File

@ -19,7 +19,7 @@ type Keeper struct {
}
// NewKeeper returns a new keeper by codec and storeKey inputs.
func NewKeeper(env appmodule.Environment, cdc codec.BinaryCodec) Keeper {
func NewKeeper(env appmodule.Environment, cdc codec.BinaryCodec) *Keeper {
sb := collections.NewSchemaBuilder(env.KVStoreService)
k := Keeper{
Environment: env,
@ -32,11 +32,11 @@ func NewKeeper(env appmodule.Environment, cdc codec.BinaryCodec) Keeper {
panic(err)
}
k.Schema = schema
return k
return &k
}
// Set the gamm hooks.
func (k Keeper) SetHooks(eh types.EpochHooks) Keeper {
func (k *Keeper) SetHooks(eh types.EpochHooks) *Keeper {
if k.hooks != nil {
panic("cannot set epochs hooks twice")
}

View File

@ -27,7 +27,7 @@ type KeeperTestSuite struct {
suite.Suite
Ctx sdk.Context
environment appmodule.Environment
EpochsKeeper epochskeeper.Keeper
EpochsKeeper *epochskeeper.Keeper
queryClient types.QueryClient
}
@ -39,7 +39,7 @@ func (s *KeeperTestSuite) SetupTest() {
s.environment = environment
queryRouter := baseapp.NewGRPCQueryRouter()
cfg := module.NewConfigurator(nil, nil, queryRouter)
types.RegisterQueryServer(cfg.QueryServer(), epochskeeper.NewQuerier(s.EpochsKeeper))
types.RegisterQueryServer(cfg.QueryServer(), epochskeeper.NewQuerier(*s.EpochsKeeper))
grpcQueryService := &baseapp.QueryServiceTestHelper{
GRPCQueryRouter: queryRouter,
Ctx: s.Ctx,
@ -49,7 +49,7 @@ func (s *KeeperTestSuite) SetupTest() {
s.queryClient = types.NewQueryClient(grpcQueryService)
}
func Setup(t *testing.T) (sdk.Context, epochskeeper.Keeper, appmodule.Environment) {
func Setup(t *testing.T) (sdk.Context, *epochskeeper.Keeper, appmodule.Environment) {
t.Helper()
key := storetypes.NewKVStoreKey(types.StoreKey)
@ -67,7 +67,7 @@ func Setup(t *testing.T) (sdk.Context, epochskeeper.Keeper, appmodule.Environmen
ctx.WithHeaderInfo(header.Info{Height: 1, Time: time.Now().UTC(), ChainID: "epochs"})
err := epochsKeeper.InitGenesis(ctx, *types.DefaultGenesis())
require.NoError(t, err)
SetEpochStartTime(ctx, epochsKeeper)
SetEpochStartTime(ctx, *epochsKeeper)
return ctx, epochsKeeper, environment
}

View File

@ -36,11 +36,11 @@ const ConsensusVersion = 1
// AppModule implements the AppModule interface for the epochs module.
type AppModule struct {
cdc codec.Codec
keeper keeper.Keeper
keeper *keeper.Keeper
}
// NewAppModule creates a new AppModule object.
func NewAppModule(cdc codec.Codec, keeper keeper.Keeper) AppModule {
func NewAppModule(cdc codec.Codec, keeper *keeper.Keeper) AppModule {
return AppModule{
cdc: cdc,
keeper: keeper,
@ -67,7 +67,7 @@ func (AppModule) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *gwrunt
// RegisterServices registers module services.
func (am AppModule) RegisterServices(registrar grpc.ServiceRegistrar) error {
types.RegisterQueryServer(registrar, keeper.NewQuerier(am.keeper))
types.RegisterQueryServer(registrar, keeper.NewQuerier(*am.keeper))
return nil
}

View File

@ -17,6 +17,7 @@ func DefaultGenesis() *GenesisState {
epochs := []EpochInfo{
NewGenesisEpochInfo("day", time.Hour*24), // alphabetical order
NewGenesisEpochInfo("hour", time.Hour),
NewGenesisEpochInfo("minute", time.Minute),
NewGenesisEpochInfo("week", time.Hour*24*7),
}
return NewGenesisState(epochs)

View File

@ -44,6 +44,7 @@ require (
cosmossdk.io/collections v0.4.0 // indirect
cosmossdk.io/core/testing v0.0.0-00010101000000-000000000000 // indirect
cosmossdk.io/x/accounts/defaults/lockup v0.0.0-20240417181816-5e7aae0db1f5 // indirect
cosmossdk.io/x/epochs v0.0.0-20240522060652-a1ae4c3e0337 // indirect
cosmossdk.io/x/tx v0.13.3 // indirect
filippo.io/edwards25519 v1.1.0 // indirect
github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect

View File

@ -12,6 +12,8 @@ cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc h1:R9O9d75e0qZYUsVV0zzi+
cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc/go.mod h1:amTTatOUV3u1PsKmNb87z6/galCxrRbz9kRdJkL0DyU=
cosmossdk.io/x/accounts/defaults/lockup v0.0.0-20240417181816-5e7aae0db1f5 h1:eb0kcGyaYHSS0do7+MIWg7UKlskSH01biRNENbm/zDA=
cosmossdk.io/x/accounts/defaults/lockup v0.0.0-20240417181816-5e7aae0db1f5/go.mod h1:drzY4oVisyWvSgpsM7ccQ7IX3efMuVIvd9Eij1Gm/6o=
cosmossdk.io/x/epochs v0.0.0-20240522060652-a1ae4c3e0337 h1:GuBrfHsK3RD5vlD4DuBz3DXslR6VlnzrYmHOC3L679Q=
cosmossdk.io/x/epochs v0.0.0-20240522060652-a1ae4c3e0337/go.mod h1:PhLn1pMBilyRC4GfRkoYhm+XVAYhF4adVrzut8AdpJI=
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs=

View File

@ -27,12 +27,14 @@ 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.
* [#20363](https://github.com/cosmos/cosmos-sdk/pull/20363) Implemented epoched minting, configurable through `MintFn`. Now `MintFn` doesn't do any assumptions on how tokens are minted, users can define their own minting logic.
* [#19896](https://github.com/cosmos/cosmos-sdk/pull/19896) Added a new max supply genesis param to existing params.
### Improvements
### API Breaking Changes
* [#20363](https://github.com/cosmos/cosmos-sdk/pull/20363) Deprecated InflationCalculationFn in favor of MintFn, `keeper.DefaultMintFn` wrapper must be used in order to continue using it in `NewAppModule`. This is not breaking for depinject users, as both `MintFn` and `InflationCalculationFn` are accepted.
* [#19367](https://github.com/cosmos/cosmos-sdk/pull/19398) `appmodule.Environment` is received on the Keeper to get access to different application services
### Bug Fixes

View File

@ -6,10 +6,15 @@ sidebar_position: 1
## Contents
* [Concepts](#concepts)
* [The Minting Mechanism](#the-minting-mechanism)
* [State](#state)
* [Minter](#minter)
* [Params](#params)
* [Begin-Block](#begin-block)
* [Epoch minting](#epoch-minting)
* [MintFn](#mintfn)
* [Block based minting](#block-based-minting)
* [Default configuration](#default-configuration)
* [NextInflationRate](#nextinflationrate)
* [NextAnnualProvisions](#nextannualprovisions)
* [BlockProvision](#blockprovision)
@ -51,12 +56,13 @@ It can be broken down in the following way:
### Minter
The minter is a space for holding current inflation information.
The minter is a space for holding current inflation information and any other data
related to minting (in the `data` field)
* Minter: `0x00 -> ProtocolBuffer(minter)`
```protobuf reference
https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/mint/v1beta1/mint.proto#L10-L24
https://github.com/cosmos/cosmos-sdk/blob/ace7bca105a8d5363782cfd19c6f169b286cd3b2/x/mint/proto/cosmos/mint/v1beta1/mint.proto#L11-L29
```
### Params
@ -72,11 +78,43 @@ A value of `0` indicates an unlimited supply.
https://github.com/cosmos/cosmos-sdk/blob/7068d0da52d954430054768b2c56aff44666933b/x/mint/proto/cosmos/mint/v1beta1/mint.proto#L26-L68
```
## Begin-Block
## Epoch minting
Minting parameters are recalculated and inflation paid at the beginning of each block.
In the latest release of x/mint, the minting logic has been refactored to allow for more flexibility in the minting process. The `InflationCalculationFn` has been deprecated in favor of `MintFn`. The `MintFn` function is passed to the `NewAppModule` function and is used to mint tokens on the configured epoch beginning. This change allows users to define their own minting logic and removes any assumptions on how tokens are minted.
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.
```mermaid
flowchart LR
A[BeforeEpochStart] --> B[MintFn]
subgraph B["MintFn (user defined)"]
direction LR
C[Get x/staking info] --> D[Calculate Inflation]
D --> E[Mint Tokens]
end
```
### MintFn
The `MintFn` function is called at the beginning of each epoch and is responsible for minting tokens. The function signature is as follows:
```go
type MintFn func(ctx context.Context, env appmodule.Environment, minter *Minter, epochId string, epochNumber int64) error
```
How this function mints tokens is defined by the app developers, meaning they can query state and perform any calculations they deem necessary. [This implementation](https://github.com/cosmos/cosmos-sdk/blob/ace7bca105a8d5363782cfd19c6f169b286cd3b2/simapp/mint_fn.go#L25) in SimApp contains examples of how to use `QueryRouterService` and the Minter's `data`.
:::warning
Note that BeginBlock will keep calling the MintFn for every block, so it is important to ensure that MintFn returns early if the epoch ID does not match the expected one.
:::
## Block based minting
In addition to minting based on epoch, minting based on block is also possible. This is achieved through calling the `MintFn` in `BeginBlock` with an epochID and epochNumber of `"block"` and `-1`, respectively.
### Default configuration
If no `MintFn` is passed to the `NewAppModule` function, the minting logic defaults to block-based minting, corresponding to `mintKeeper.DefaultMintFn(types.DefaultInflationCalculationFn)`.
### Inflation rate calculation

View File

@ -6,6 +6,7 @@ import (
"cosmossdk.io/depinject"
"cosmossdk.io/depinject/appconfig"
authtypes "cosmossdk.io/x/auth/types"
epochstypes "cosmossdk.io/x/epochs/types"
"cosmossdk.io/x/mint/keeper"
"cosmossdk.io/x/mint/types"
@ -30,7 +31,8 @@ type ModuleInputs struct {
Config *modulev1.Module
Environment appmodule.Environment
Cdc codec.Codec
InflationCalculationFn types.InflationCalculationFn `optional:"true"`
MintFn types.MintFn `optional:"true"`
InflationCalculationFn types.InflationCalculationFn `optional:"true"` // deprecated
AccountKeeper types.AccountKeeper
BankKeeper types.BankKeeper
@ -42,6 +44,7 @@ type ModuleOutputs struct {
MintKeeper keeper.Keeper
Module appmodule.AppModule
EpochHooks epochstypes.EpochHooksWrapper
}
func ProvideModule(in ModuleInputs) ModuleOutputs {
@ -71,8 +74,21 @@ func ProvideModule(in ModuleInputs) ModuleOutputs {
as,
)
// when no inflation calculation function is provided it will use the default types.DefaultInflationCalculationFn
m := NewAppModule(in.Cdc, k, in.AccountKeeper, in.InflationCalculationFn)
if in.MintFn != nil && in.InflationCalculationFn != nil {
panic("MintFn and InflationCalculationFn cannot both be set")
}
return ModuleOutputs{MintKeeper: k, Module: m}
// if no mintFn is provided, use the default minting function
if in.MintFn == nil {
// if no inflationCalculationFn is provided, use the default inflation calculation function
if in.InflationCalculationFn == nil {
in.InflationCalculationFn = types.DefaultInflationCalculationFn
}
in.MintFn = k.DefaultMintFn(in.InflationCalculationFn)
}
m := NewAppModule(in.Cdc, k, in.AccountKeeper, in.MintFn)
return ModuleOutputs{MintKeeper: k, Module: m, EpochHooks: epochstypes.EpochHooksWrapper{EpochHooks: m}}
}

34
x/mint/epoch_hooks.go Normal file
View File

@ -0,0 +1,34 @@
package mint
import (
"context"
epochstypes "cosmossdk.io/x/epochs/types"
)
var _ epochstypes.EpochHooks = AppModule{}
// GetModuleName implements types.EpochHooks.
func (am AppModule) GetModuleName() string {
return am.Name()
}
// BeforeEpochStart calls the mint function.
func (am AppModule) BeforeEpochStart(ctx context.Context, epochIdentifier string, epochNumber int64) error {
minter, err := am.keeper.Minter.Get(ctx)
if err != nil {
return err
}
err = am.mintFn(ctx, am.keeper.Environment, &minter, epochIdentifier, epochNumber)
if err != nil {
return err
}
return am.keeper.Minter.Set(ctx, minter)
}
// AfterEpochEnd is a noop
func (am AppModule) AfterEpochEnd(ctx context.Context, epochIdentifier string, epochNumber int64) error {
return nil
}

View File

@ -12,6 +12,7 @@ require (
cosmossdk.io/math v1.3.0
cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc
cosmossdk.io/x/accounts v0.0.0-20240226161501-23359a0b6d91 // indirect
cosmossdk.io/x/epochs v0.0.0-20240522060652-a1ae4c3e0337
github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect
github.com/cosmos/cosmos-proto v1.0.0-beta.5
github.com/cosmos/cosmos-sdk v0.51.0

View File

@ -14,6 +14,8 @@ cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc h1:R9O9d75e0qZYUsVV0zzi+
cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc/go.mod h1:amTTatOUV3u1PsKmNb87z6/galCxrRbz9kRdJkL0DyU=
cosmossdk.io/x/accounts/defaults/lockup v0.0.0-20240417181816-5e7aae0db1f5 h1:eb0kcGyaYHSS0do7+MIWg7UKlskSH01biRNENbm/zDA=
cosmossdk.io/x/accounts/defaults/lockup v0.0.0-20240417181816-5e7aae0db1f5/go.mod h1:drzY4oVisyWvSgpsM7ccQ7IX3efMuVIvd9Eij1Gm/6o=
cosmossdk.io/x/epochs v0.0.0-20240522060652-a1ae4c3e0337 h1:GuBrfHsK3RD5vlD4DuBz3DXslR6VlnzrYmHOC3L679Q=
cosmossdk.io/x/epochs v0.0.0-20240522060652-a1ae4c3e0337/go.mod h1:PhLn1pMBilyRC4GfRkoYhm+XVAYhF4adVrzut8AdpJI=
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs=

View File

@ -3,15 +3,13 @@ package keeper
import (
"context"
"cosmossdk.io/core/event"
"cosmossdk.io/x/mint/types"
"github.com/cosmos/cosmos-sdk/telemetry"
sdk "github.com/cosmos/cosmos-sdk/types"
)
// BeginBlocker mints new tokens for the previous block.
func (k Keeper) BeginBlocker(ctx context.Context, ic types.InflationCalculationFn) error {
func (k Keeper) BeginBlocker(ctx context.Context, mintFn types.MintFn) error {
defer telemetry.ModuleMeasureSince(types.ModuleName, telemetry.Now(), telemetry.MetricKeyBeginBlocker)
// fetch stored minter & params
@ -20,76 +18,12 @@ func (k Keeper) BeginBlocker(ctx context.Context, ic types.InflationCalculationF
return err
}
params, err := k.Params.Get(ctx)
// we pass -1 as epoch number to indicate that this is not an epoch minting,
// but a regular block minting. Same with epoch id "block".
err = mintFn(ctx, k.Environment, &minter, "block", -1)
if err != nil {
return err
}
// recalculate inflation rate
totalStakingSupply, err := k.StakingTokenSupply(ctx)
if err != nil {
return err
}
bondedRatio, err := k.BondedRatio(ctx)
if err != nil {
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
}
// calculate minted coins
mintedCoin := minter.BlockProvision(params)
mintedCoins := sdk.NewCoins(mintedCoin)
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
err = k.AddCollectedFees(ctx, mintedCoins)
if err != nil {
return err
}
if mintedCoin.Amount.IsInt64() {
defer telemetry.ModuleSetGauge(types.ModuleName, float32(mintedCoin.Amount.Int64()), "minted_tokens")
}
return k.EventService.EventManager(ctx).EmitKV(
types.EventTypeMint,
event.NewAttribute(types.AttributeKeyBondedRatio, bondedRatio.String()),
event.NewAttribute(types.AttributeKeyInflation, minter.Inflation.String()),
event.NewAttribute(types.AttributeKeyAnnualProvisions, minter.AnnualProvisions.String()),
event.NewAttribute(sdk.AttributeKeyAmount, mintedCoin.Amount.String()),
)
return k.Minter.Set(ctx, minter)
}

View File

@ -6,11 +6,13 @@ import (
"cosmossdk.io/collections"
"cosmossdk.io/core/appmodule"
"cosmossdk.io/core/event"
"cosmossdk.io/log"
"cosmossdk.io/math"
"cosmossdk.io/x/mint/types"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/telemetry"
sdk "github.com/cosmos/cosmos-sdk/types"
)
@ -101,3 +103,85 @@ func (k Keeper) MintCoins(ctx context.Context, newCoins sdk.Coins) error {
func (k Keeper) AddCollectedFees(ctx context.Context, fees sdk.Coins) error {
return k.bankKeeper.SendCoinsFromModuleToModule(ctx, types.ModuleName, k.feeCollectorName, fees)
}
func (k Keeper) DefaultMintFn(ic types.InflationCalculationFn) types.MintFn {
return func(ctx context.Context, env appmodule.Environment, minter *types.Minter, epochId string, epochNumber int64) error {
// the default mint function is called every block, so we only check if epochId is "block" which is
// a special value to indicate that this is not an epoch minting, but a regular block minting.
if epochId != "block" {
return nil
}
stakingTokenSupply, err := k.StakingTokenSupply(ctx)
if err != nil {
return err
}
bondedRatio, err := k.BondedRatio(ctx)
if err != nil {
return err
}
params, err := k.Params.Get(ctx)
if err != nil {
return err
}
minter.Inflation = ic(ctx, *minter, params, bondedRatio)
minter.AnnualProvisions = minter.NextAnnualProvisions(params, stakingTokenSupply)
mintedCoin := minter.BlockProvision(params)
mintedCoins := sdk.NewCoins(mintedCoin)
maxSupply := params.MaxSupply
totalSupply := stakingTokenSupply
// 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)
if diff.LTE(math.ZeroInt()) {
k.logger.Info("max supply reached, no new tokens will be minted")
return nil
}
// 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
// TODO: figure out a better way to do this
err = k.AddCollectedFees(ctx, mintedCoins)
if err != nil {
return err
}
if mintedCoin.Amount.IsInt64() {
defer telemetry.ModuleSetGauge(types.ModuleName, float32(mintedCoin.Amount.Int64()), "minted_tokens")
}
return env.EventService.EventManager(ctx).EmitKV(
types.EventTypeMint,
event.NewAttribute(types.AttributeKeyBondedRatio, bondedRatio.String()),
event.NewAttribute(types.AttributeKeyInflation, minter.Inflation.String()),
event.NewAttribute(types.AttributeKeyAnnualProvisions, minter.AnnualProvisions.String()),
event.NewAttribute(sdk.AttributeKeyAmount, mintedCoin.Amount.String()),
)
}
}

View File

@ -24,7 +24,7 @@ import (
const govModuleNameStr = "cosmos10d07y265gmmuvt4z0w9aw880jnsr700j6zn9kn"
type IntegrationTestSuite struct {
type KeeperTestSuite struct {
suite.Suite
mintKeeper keeper.Keeper
@ -35,10 +35,10 @@ type IntegrationTestSuite struct {
}
func TestKeeperTestSuite(t *testing.T) {
suite.Run(t, new(IntegrationTestSuite))
suite.Run(t, new(KeeperTestSuite))
}
func (s *IntegrationTestSuite) SetupTest() {
func (s *KeeperTestSuite) SetupTest() {
encCfg := moduletestutil.MakeTestEncodingConfig(codectestutil.CodecOptions{}, mint.AppModule{})
key := storetypes.NewKVStoreKey(types.StoreKey)
storeService := runtime.NewKVStoreService(key)
@ -67,31 +67,106 @@ func (s *IntegrationTestSuite) SetupTest() {
s.bankKeeper = bankKeeper
err := s.mintKeeper.Params.Set(s.ctx, types.DefaultParams())
s.Require().NoError(err)
s.NoError(err)
s.Require().NoError(s.mintKeeper.Minter.Set(s.ctx, types.DefaultInitialMinter()))
s.NoError(s.mintKeeper.Minter.Set(s.ctx, types.DefaultInitialMinter()))
s.msgServer = keeper.NewMsgServerImpl(s.mintKeeper)
}
func (s *IntegrationTestSuite) TestAliasFunctions() {
func (s *KeeperTestSuite) TestAliasFunctions() {
stakingTokenSupply := math.NewIntFromUint64(100000000000)
s.stakingKeeper.EXPECT().StakingTokenSupply(s.ctx).Return(stakingTokenSupply, nil)
tokenSupply, err := s.mintKeeper.StakingTokenSupply(s.ctx)
s.Require().NoError(err)
s.Require().Equal(tokenSupply, stakingTokenSupply)
s.NoError(err)
s.Equal(tokenSupply, stakingTokenSupply)
bondedRatio := math.LegacyNewDecWithPrec(15, 2)
s.stakingKeeper.EXPECT().BondedRatio(s.ctx).Return(bondedRatio, nil)
ratio, err := s.mintKeeper.BondedRatio(s.ctx)
s.Require().NoError(err)
s.Require().Equal(ratio, bondedRatio)
s.NoError(err)
s.Equal(ratio, bondedRatio)
coins := sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(1000000)))
s.bankKeeper.EXPECT().MintCoins(s.ctx, types.ModuleName, coins).Return(nil)
s.Require().Equal(s.mintKeeper.MintCoins(s.ctx, sdk.NewCoins()), nil)
s.Require().Nil(s.mintKeeper.MintCoins(s.ctx, coins))
s.Equal(s.mintKeeper.MintCoins(s.ctx, sdk.NewCoins()), nil)
s.Nil(s.mintKeeper.MintCoins(s.ctx, coins))
fees := sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(1000)))
s.bankKeeper.EXPECT().SendCoinsFromModuleToModule(s.ctx, types.ModuleName, authtypes.FeeCollectorName, fees).Return(nil)
s.Require().Nil(s.mintKeeper.AddCollectedFees(s.ctx, fees))
s.Nil(s.mintKeeper.AddCollectedFees(s.ctx, fees))
}
func (s *KeeperTestSuite) TestDefaultMintFn() {
s.stakingKeeper.EXPECT().StakingTokenSupply(s.ctx).Return(math.NewIntFromUint64(100000000000), nil).AnyTimes()
bondedRatio := math.LegacyNewDecWithPrec(15, 2)
s.stakingKeeper.EXPECT().BondedRatio(s.ctx).Return(bondedRatio, nil).AnyTimes()
s.bankKeeper.EXPECT().MintCoins(s.ctx, types.ModuleName, sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(792)))).Return(nil)
s.bankKeeper.EXPECT().SendCoinsFromModuleToModule(s.ctx, types.ModuleName, authtypes.FeeCollectorName, gomock.Any()).Return(nil)
minter, err := s.mintKeeper.Minter.Get(s.ctx)
s.NoError(err)
err = s.mintKeeper.DefaultMintFn(types.DefaultInflationCalculationFn)(s.ctx, s.mintKeeper.Environment, &minter, "block", 0)
s.NoError(err)
// set a maxsupply and call again
params, err := s.mintKeeper.Params.Get(s.ctx)
s.NoError(err)
params.MaxSupply = math.NewInt(10000000000)
err = s.mintKeeper.Params.Set(s.ctx, params)
s.NoError(err)
err = s.mintKeeper.DefaultMintFn(types.DefaultInflationCalculationFn)(s.ctx, s.mintKeeper.Environment, &minter, "block", 0)
s.NoError(err)
// modify max supply to be almost reached
// we tried to mint 2059stake but we only get to mint 2000stake
params, err = s.mintKeeper.Params.Get(s.ctx)
s.NoError(err)
params.MaxSupply = math.NewInt(100000000000 + 2000)
err = s.mintKeeper.Params.Set(s.ctx, params)
s.NoError(err)
s.bankKeeper.EXPECT().MintCoins(s.ctx, types.ModuleName, sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(792)))).Return(nil)
s.bankKeeper.EXPECT().SendCoinsFromModuleToModule(s.ctx, types.ModuleName, authtypes.FeeCollectorName, gomock.Any()).Return(nil)
err = s.mintKeeper.DefaultMintFn(types.DefaultInflationCalculationFn)(s.ctx, s.mintKeeper.Environment, &minter, "block", 0)
s.NoError(err)
}
func (s *KeeperTestSuite) TestBeginBlocker() {
s.stakingKeeper.EXPECT().StakingTokenSupply(s.ctx).Return(math.NewIntFromUint64(100000000000), nil).AnyTimes()
bondedRatio := math.LegacyNewDecWithPrec(15, 2)
s.stakingKeeper.EXPECT().BondedRatio(s.ctx).Return(bondedRatio, nil).AnyTimes()
s.bankKeeper.EXPECT().MintCoins(s.ctx, types.ModuleName, sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(792)))).Return(nil)
s.bankKeeper.EXPECT().SendCoinsFromModuleToModule(s.ctx, types.ModuleName, authtypes.FeeCollectorName, gomock.Any()).Return(nil)
// get minter (it should get modified aftwerwards)
minter, err := s.mintKeeper.Minter.Get(s.ctx)
s.NoError(err)
err = s.mintKeeper.BeginBlocker(s.ctx, s.mintKeeper.DefaultMintFn(types.DefaultInflationCalculationFn))
s.NoError(err)
// get minter again and compare
newMinter, err := s.mintKeeper.Minter.Get(s.ctx)
s.NoError(err)
s.NotEqual(minter, newMinter)
}
func (s *KeeperTestSuite) TestMigrator() {
m := keeper.NewMigrator(s.mintKeeper)
s.NoError(m.Migrate1to2(s.ctx)) // just to get the coverage up
// set max supply to one and migrate (should get it to zero)
params, err := s.mintKeeper.Params.Get(s.ctx)
s.NoError(err)
params.MaxSupply = math.OneInt()
s.NoError(s.mintKeeper.Params.Set(s.ctx, params))
s.NoError(m.Migrate2to3(s.ctx))
newParams, err := s.mintKeeper.Params.Get(s.ctx)
s.NoError(err)
s.Equal(math.ZeroInt(), newParams.MaxSupply)
}

View File

@ -7,7 +7,7 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
)
func (s *IntegrationTestSuite) TestUpdateParams() {
func (s *KeeperTestSuite) TestUpdateParams() {
testCases := []struct {
name string
request *types.MsgUpdateParams

View File

@ -44,28 +44,31 @@ type AppModule struct {
keeper keeper.Keeper
authKeeper types.AccountKeeper
// inflationCalculator is used to calculate the inflation rate during BeginBlock.
// If inflationCalculator is nil, the default inflation calculation logic is used.
inflationCalculator types.InflationCalculationFn
// mintFn is used to mint new coins during BeginBlock. This function is in charge of
// minting new coins based on arbitrary logic, previously done through InflationCalculationFn.
// If mintFn is nil, the default minting logic is used.
mintFn types.MintFn
}
// NewAppModule creates a new AppModule object.
// If the InflationCalculationFn argument is nil, then the SDK's default inflation function will be used.
// If the mintFn argument is nil, then the SDK's default minting function will be used.
func NewAppModule(
cdc codec.Codec,
keeper keeper.Keeper,
ak types.AccountKeeper,
ic types.InflationCalculationFn,
mintFn types.MintFn,
) AppModule {
if ic == nil {
ic = types.DefaultInflationCalculationFn
// If mintFn is nil, use the default minting function.
// This check also happens in ProvideModule when used with depinject.
if mintFn == nil {
mintFn = keeper.DefaultMintFn(types.DefaultInflationCalculationFn)
}
return AppModule{
cdc: cdc,
keeper: keeper,
authKeeper: ak,
inflationCalculator: ic,
cdc: cdc,
keeper: keeper,
authKeeper: ak,
mintFn: mintFn,
}
}
@ -157,7 +160,7 @@ func (AppModule) ConsensusVersion() uint64 { return ConsensusVersion }
// BeginBlock returns the begin blocker for the mint module.
func (am AppModule) BeginBlock(ctx context.Context) error {
return am.keeper.BeginBlocker(ctx, am.inflationCalculator)
return am.keeper.BeginBlocker(ctx, am.mintFn)
}
// AppModuleSimulation functions

92
x/mint/module_test.go Normal file
View File

@ -0,0 +1,92 @@
package mint_test
import (
"testing"
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/suite"
"cosmossdk.io/log"
"cosmossdk.io/math"
storetypes "cosmossdk.io/store/types"
authtypes "cosmossdk.io/x/auth/types"
"cosmossdk.io/x/mint"
"cosmossdk.io/x/mint/keeper"
minttestutil "cosmossdk.io/x/mint/testutil"
"cosmossdk.io/x/mint/types"
codectestutil "github.com/cosmos/cosmos-sdk/codec/testutil"
"github.com/cosmos/cosmos-sdk/runtime"
"github.com/cosmos/cosmos-sdk/testutil"
sdk "github.com/cosmos/cosmos-sdk/types"
moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil"
)
const govModuleNameStr = "cosmos10d07y265gmmuvt4z0w9aw880jnsr700j6zn9kn"
type ModuleTestSuite struct {
suite.Suite
mintKeeper keeper.Keeper
ctx sdk.Context
msgServer types.MsgServer
stakingKeeper *minttestutil.MockStakingKeeper
bankKeeper *minttestutil.MockBankKeeper
appmodule mint.AppModule
}
func TestKeeperTestSuite(t *testing.T) {
suite.Run(t, new(ModuleTestSuite))
}
func (s *ModuleTestSuite) SetupTest() {
encCfg := moduletestutil.MakeTestEncodingConfig(codectestutil.CodecOptions{}, mint.AppModule{})
key := storetypes.NewKVStoreKey(types.StoreKey)
storeService := runtime.NewKVStoreService(key)
env := runtime.NewEnvironment(storeService, log.NewNopLogger())
testCtx := testutil.DefaultContextWithDB(s.T(), key, storetypes.NewTransientStoreKey("transient_test"))
s.ctx = testCtx.Ctx
// gomock initializations
ctrl := gomock.NewController(s.T())
accountKeeper := minttestutil.NewMockAccountKeeper(ctrl)
bankKeeper := minttestutil.NewMockBankKeeper(ctrl)
stakingKeeper := minttestutil.NewMockStakingKeeper(ctrl)
accountKeeper.EXPECT().GetModuleAddress(types.ModuleName).Return(sdk.AccAddress{})
s.mintKeeper = keeper.NewKeeper(
encCfg.Codec,
env,
stakingKeeper,
accountKeeper,
bankKeeper,
authtypes.FeeCollectorName,
govModuleNameStr,
)
s.stakingKeeper = stakingKeeper
s.bankKeeper = bankKeeper
err := s.mintKeeper.Params.Set(s.ctx, types.DefaultParams())
s.NoError(err)
s.NoError(s.mintKeeper.Minter.Set(s.ctx, types.DefaultInitialMinter()))
s.msgServer = keeper.NewMsgServerImpl(s.mintKeeper)
s.appmodule = mint.NewAppModule(encCfg.Codec, s.mintKeeper, accountKeeper, s.mintKeeper.DefaultMintFn(types.DefaultInflationCalculationFn))
}
func (s *ModuleTestSuite) TestEpochHooks() {
s.stakingKeeper.EXPECT().StakingTokenSupply(s.ctx).Return(math.NewIntFromUint64(100000000000), nil).AnyTimes()
bondedRatio := math.LegacyNewDecWithPrec(15, 2)
s.stakingKeeper.EXPECT().BondedRatio(s.ctx).Return(bondedRatio, nil).AnyTimes()
s.bankKeeper.EXPECT().MintCoins(s.ctx, types.ModuleName, sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(792)))).Return(nil)
s.bankKeeper.EXPECT().SendCoinsFromModuleToModule(s.ctx, types.ModuleName, authtypes.FeeCollectorName, gomock.Any()).Return(nil)
err := s.appmodule.BeforeEpochStart(s.ctx, "block", -1)
s.NoError(err)
err = s.appmodule.AfterEpochEnd(s.ctx, "epochIdentifier", 1) // just to get coverage up
s.NoError(err)
}

View File

@ -6,6 +6,7 @@ option go_package = "cosmossdk.io/x/mint/types";
import "gogoproto/gogo.proto";
import "cosmos_proto/cosmos.proto";
import "amino/amino.proto";
import "google/protobuf/any.proto";
// Minter represents the minting state.
message Minter {
@ -21,6 +22,10 @@ message Minter {
(gogoproto.customtype) = "cosmossdk.io/math.LegacyDec",
(gogoproto.nullable) = false
];
// data is any custom data that the user might want to put in the minter, to
// be used in the minting process.
bytes data = 3;
}
// Params defines the parameters for the x/mint module.

View File

@ -3,6 +3,7 @@ package types
import (
"context"
"cosmossdk.io/core/appmodule"
"cosmossdk.io/math"
)
@ -11,9 +12,14 @@ import (
// bondedRatio and returns the newly calculated inflation rate.
// It can be used to specify a custom inflation calculation logic, instead of relying on the
// default logic provided by the sdk.
// Deprecated: use MintFn instead.
type InflationCalculationFn func(ctx context.Context, minter Minter, params Params, bondedRatio math.LegacyDec) math.LegacyDec
// MintFn defines the function that needs to be implemented in order to customize the minting process.
type MintFn func(ctx context.Context, env appmodule.Environment, minter *Minter, epochId string, epochNumber int64) error
// DefaultInflationCalculationFn is the default function used to calculate inflation.
// Deprecated: use DefaultMintFn instead.
func DefaultInflationCalculationFn(_ context.Context, minter Minter, params Params, bondedRatio math.LegacyDec) math.LegacyDec {
return minter.NextInflationRate(params, bondedRatio)
}

View File

@ -0,0 +1,21 @@
package types
import (
"testing"
"github.com/stretchr/testify/require"
)
func TestGenesis(t *testing.T) {
minter := DefaultInitialMinter()
params := DefaultParams()
gs := NewGenesisState(minter, params)
err := ValidateGenesis(*gs)
require.NoError(t, err)
defaultGs := DefaultGenesisState()
err = ValidateGenesis(*defaultGs)
require.NoError(t, err)
require.Equal(t, gs, defaultGs)
}

View File

@ -10,6 +10,7 @@ import (
_ "github.com/cosmos/cosmos-sdk/types/tx/amino"
_ "github.com/cosmos/gogoproto/gogoproto"
proto "github.com/cosmos/gogoproto/proto"
_ "github.com/cosmos/gogoproto/types/any"
io "io"
math "math"
math_bits "math/bits"
@ -32,6 +33,9 @@ type Minter struct {
Inflation cosmossdk_io_math.LegacyDec `protobuf:"bytes,1,opt,name=inflation,proto3,customtype=cosmossdk.io/math.LegacyDec" json:"inflation"`
// current annual expected provisions
AnnualProvisions cosmossdk_io_math.LegacyDec `protobuf:"bytes,2,opt,name=annual_provisions,json=annualProvisions,proto3,customtype=cosmossdk.io/math.LegacyDec" json:"annual_provisions"`
// data is any custom data that the user might want to put in the minter, to
// be used in the minting process.
Data []byte `protobuf:"bytes,3,opt,name=data,proto3" json:"data,omitempty"`
}
func (m *Minter) Reset() { *m = Minter{} }
@ -67,6 +71,13 @@ func (m *Minter) XXX_DiscardUnknown() {
var xxx_messageInfo_Minter proto.InternalMessageInfo
func (m *Minter) GetData() []byte {
if m != nil {
return m.Data
}
return nil
}
// Params defines the parameters for the x/mint module.
type Params struct {
// type of coin to mint
@ -140,36 +151,38 @@ func init() {
func init() { proto.RegisterFile("cosmos/mint/v1beta1/mint.proto", fileDescriptor_2df116d183c1e223) }
var fileDescriptor_2df116d183c1e223 = []byte{
// 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,
// 490 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x93, 0x3f, 0x6f, 0xd3, 0x40,
0x18, 0xc6, 0x73, 0x10, 0x82, 0x72, 0xb4, 0x82, 0x5e, 0xa9, 0xe4, 0x16, 0xd5, 0x8d, 0x3a, 0xa0,
0xa8, 0xa8, 0xb1, 0xa2, 0x4a, 0x0c, 0x8c, 0x21, 0x4b, 0x11, 0x15, 0x91, 0x19, 0x10, 0x20, 0x61,
0xbd, 0xb6, 0xaf, 0xee, 0x11, 0xdf, 0x9d, 0xe5, 0xbb, 0x54, 0xf6, 0x57, 0x60, 0xe2, 0x63, 0x30,
0x76, 0x60, 0xe1, 0x1b, 0x74, 0x41, 0xaa, 0x98, 0x10, 0x43, 0x85, 0x92, 0xa1, 0x5f, 0x03, 0xf9,
0xce, 0xa4, 0xfc, 0x99, 0x08, 0x5d, 0xac, 0xbb, 0xf7, 0x79, 0xdf, 0xdf, 0xf3, 0xd8, 0xf2, 0x8b,
0xdd, 0x48, 0x2a, 0x2e, 0x95, 0xc7, 0x99, 0xd0, 0xde, 0x71, 0x3f, 0xa4, 0x1a, 0xfa, 0xe6, 0xd2,
0xcb, 0x72, 0xa9, 0x25, 0x59, 0xb5, 0x7a, 0xcf, 0x94, 0x6a, 0x7d, 0xe3, 0x6e, 0x22, 0x13, 0x69,
0x74, 0xaf, 0x3a, 0xd9, 0xd6, 0x8d, 0x75, 0xdb, 0x1a, 0x58, 0xa1, 0x9e, 0xb3, 0xd2, 0x0a, 0x70,
0x26, 0xa4, 0x67, 0x9e, 0x3f, 0xbb, 0x13, 0x29, 0x93, 0x94, 0x7a, 0xe6, 0x16, 0x4e, 0x0e, 0x3d,
0x10, 0xa5, 0x95, 0xb6, 0x3f, 0x23, 0xdc, 0x3a, 0x60, 0x42, 0xd3, 0x9c, 0x3c, 0xc3, 0x6d, 0x26,
0x0e, 0x53, 0xd0, 0x4c, 0x0a, 0x07, 0x75, 0x50, 0xb7, 0x3d, 0xe8, 0x9f, 0x9e, 0x6f, 0x35, 0xbe,
0x9d, 0x6f, 0xdd, 0xb3, 0x0e, 0x2a, 0x1e, 0xf7, 0x98, 0xf4, 0x38, 0xe8, 0xa3, 0xde, 0x53, 0x9a,
0x40, 0x54, 0x0e, 0x69, 0xf4, 0xe5, 0xe3, 0x2e, 0xae, 0x03, 0x0c, 0x69, 0xe4, 0x5f, 0x32, 0xc8,
0x1b, 0xbc, 0x02, 0x42, 0x4c, 0x20, 0xad, 0x62, 0x1e, 0x33, 0xc5, 0xa4, 0x50, 0xce, 0xb5, 0x45,
0xc1, 0x77, 0x2c, 0x6b, 0x34, 0x47, 0x11, 0x82, 0x9b, 0x31, 0x68, 0x70, 0xae, 0x77, 0x50, 0x77,
0xc9, 0x37, 0xe7, 0xed, 0x4f, 0x4d, 0xdc, 0x1a, 0x41, 0x0e, 0x5c, 0x91, 0x4d, 0x8c, 0xab, 0x2f,
0x19, 0xc4, 0x54, 0x48, 0x6e, 0x5f, 0xc8, 0x6f, 0x57, 0x95, 0x61, 0x55, 0x20, 0x6f, 0xf1, 0xda,
0x3c, 0x6a, 0x90, 0x83, 0xa6, 0x41, 0x74, 0x04, 0x22, 0xa1, 0x75, 0xc2, 0x87, 0xff, 0x9c, 0xf0,
0xc3, 0xc5, 0xc9, 0x0e, 0xf2, 0x57, 0xe7, 0x50, 0x1f, 0x34, 0x7d, 0x6c, 0x90, 0xe4, 0x35, 0x5e,
0xbe, 0xf4, 0xe2, 0x50, 0x98, 0xc8, 0x8b, 0x7b, 0x2c, 0xcd, 0x61, 0x07, 0x50, 0xfc, 0x01, 0x67,
0xc2, 0x69, 0x5e, 0x15, 0x9c, 0x09, 0xf2, 0x02, 0xdf, 0x4a, 0x24, 0xa4, 0x41, 0x28, 0x45, 0x4c,
0x63, 0xe7, 0xc6, 0x7f, 0xa1, 0x71, 0x85, 0x1a, 0x18, 0x12, 0xb9, 0x8f, 0x6f, 0x87, 0xa9, 0x8c,
0xc6, 0x2a, 0xc8, 0x68, 0x1e, 0x94, 0x14, 0x72, 0xa7, 0xd5, 0x41, 0xdd, 0xa6, 0xbf, 0x6c, 0xcb,
0x23, 0x9a, 0xbf, 0xa4, 0x90, 0x93, 0x27, 0x18, 0x73, 0x28, 0x02, 0x35, 0xc9, 0xb2, 0xb4, 0x74,
0x6e, 0x1a, 0xff, 0x07, 0xb5, 0xff, 0xda, 0xdf, 0xfe, 0xfb, 0x42, 0xff, 0xe2, 0xbc, 0x2f, 0xb4,
0xdf, 0xe6, 0x50, 0x3c, 0x37, 0xd3, 0x8f, 0x36, 0xdf, 0x5d, 0x9c, 0xec, 0x38, 0x56, 0xdb, 0x55,
0xf1, 0xd8, 0x2b, 0xec, 0x2e, 0xda, 0x1f, 0x66, 0xb0, 0x77, 0x3a, 0x75, 0xd1, 0xd9, 0xd4, 0x45,
0xdf, 0xa7, 0x2e, 0x7a, 0x3f, 0x73, 0x1b, 0x67, 0x33, 0xb7, 0xf1, 0x75, 0xe6, 0x36, 0x5e, 0xad,
0xff, 0x66, 0x54, 0x4f, 0xe9, 0x32, 0xa3, 0x2a, 0x6c, 0x99, 0x3d, 0xda, 0xfb, 0x11, 0x00, 0x00,
0xff, 0xff, 0x53, 0x44, 0x4d, 0x1a, 0xdd, 0x03, 0x00, 0x00,
}
func (m *Minter) Marshal() (dAtA []byte, err error) {
@ -192,6 +205,13 @@ func (m *Minter) MarshalToSizedBuffer(dAtA []byte) (int, error) {
_ = i
var l int
_ = l
if len(m.Data) > 0 {
i -= len(m.Data)
copy(dAtA[i:], m.Data)
i = encodeVarintMint(dAtA, i, uint64(len(m.Data)))
i--
dAtA[i] = 0x1a
}
{
size := m.AnnualProvisions.Size()
i -= size
@ -321,6 +341,10 @@ func (m *Minter) Size() (n int) {
n += 1 + l + sovMint(uint64(l))
l = m.AnnualProvisions.Size()
n += 1 + l + sovMint(uint64(l))
l = len(m.Data)
if l > 0 {
n += 1 + l + sovMint(uint64(l))
}
return n
}
@ -453,6 +477,40 @@ func (m *Minter) Unmarshal(dAtA []byte) error {
return err
}
iNdEx = postIndex
case 3:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Data", wireType)
}
var byteLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowMint
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
byteLen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if byteLen < 0 {
return ErrInvalidLengthMint
}
postIndex := iNdEx + byteLen
if postIndex < 0 {
return ErrInvalidLengthMint
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Data = append(m.Data[:0], dAtA[iNdEx:postIndex]...)
if m.Data == nil {
m.Data = []byte{}
}
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipMint(dAtA[iNdEx:])

View File

@ -55,6 +55,9 @@ func TestNextInflation(t *testing.T) {
inflation := minter.NextInflationRate(params, tc.bondedRatio)
diffInflation := inflation.Sub(tc.setInflation)
annualProvisions := minter.NextAnnualProvisions(params, math.NewInt(100000000000000))
require.Equal(t, minter.Inflation.MulInt(math.NewInt(100000000000000)), annualProvisions)
require.True(t, diffInflation.Equal(tc.expChange),
"Test Index: %v\nDiff: %v\nExpected: %v\n", i, diffInflation, tc.expChange)
}
@ -88,6 +91,25 @@ func TestBlockProvision(t *testing.T) {
}
}
func TestValidateMinter(t *testing.T) {
tests := []struct {
minter Minter
expErr bool
}{
{InitialMinter(math.LegacyNewDecWithPrec(1, 1)), false},
{InitialMinter(math.LegacyNewDecWithPrec(-1, 1)), true},
{InitialMinter(math.LegacyZeroDec()), false},
}
for i, tc := range tests {
err := ValidateMinter(tc.minter)
if tc.expErr {
require.Error(t, err, "test: %v", i)
} else {
require.NoError(t, err, "test: %v", i)
}
}
}
// Benchmarking :)
// previously using math.Int operations:
// BenchmarkBlockProvision-4 5000000 220 ns/op

View File

@ -69,12 +69,7 @@ func (p Params) Validate() error {
return nil
}
func validateMintDenom(i interface{}) error {
v, ok := i.(string)
if !ok {
return fmt.Errorf("invalid parameter type: %T", i)
}
func validateMintDenom(v string) error {
if strings.TrimSpace(v) == "" {
return errors.New("mint denom cannot be blank")
}
@ -85,12 +80,7 @@ func validateMintDenom(i interface{}) error {
return nil
}
func validateInflationRateChange(i interface{}) error {
v, ok := i.(math.LegacyDec)
if !ok {
return fmt.Errorf("invalid parameter type: %T", i)
}
func validateInflationRateChange(v math.LegacyDec) error {
if v.IsNil() {
return fmt.Errorf("inflation rate change cannot be nil: %s", v)
}
@ -104,12 +94,7 @@ func validateInflationRateChange(i interface{}) error {
return nil
}
func validateInflationMax(i interface{}) error {
v, ok := i.(math.LegacyDec)
if !ok {
return fmt.Errorf("invalid parameter type: %T", i)
}
func validateInflationMax(v math.LegacyDec) error {
if v.IsNil() {
return fmt.Errorf("max inflation cannot be nil: %s", v)
}
@ -123,12 +108,7 @@ func validateInflationMax(i interface{}) error {
return nil
}
func validateInflationMin(i interface{}) error {
v, ok := i.(math.LegacyDec)
if !ok {
return fmt.Errorf("invalid parameter type: %T", i)
}
func validateInflationMin(v math.LegacyDec) error {
if v.IsNil() {
return fmt.Errorf("min inflation cannot be nil: %s", v)
}
@ -142,12 +122,7 @@ func validateInflationMin(i interface{}) error {
return nil
}
func validateGoalBonded(i interface{}) error {
v, ok := i.(math.LegacyDec)
if !ok {
return fmt.Errorf("invalid parameter type: %T", i)
}
func validateGoalBonded(v math.LegacyDec) error {
if v.IsNil() {
return fmt.Errorf("goal bonded cannot be nil: %s", v)
}
@ -161,12 +136,7 @@ func validateGoalBonded(i interface{}) error {
return nil
}
func validateBlocksPerYear(i interface{}) error {
v, ok := i.(uint64)
if !ok {
return fmt.Errorf("invalid parameter type: %T", i)
}
func validateBlocksPerYear(v uint64) error {
if v == 0 {
return fmt.Errorf("blocks per year must be positive: %d", v)
}
@ -174,12 +144,7 @@ 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)
}
func validateMaxSupply(v math.Int) error {
if v.IsNegative() {
return fmt.Errorf("max supply must be positive: %d", v)
}

112
x/mint/types/params_test.go Normal file
View File

@ -0,0 +1,112 @@
package types
import (
"testing"
"github.com/stretchr/testify/require"
"cosmossdk.io/math"
)
func TestValidate(t *testing.T) {
params := DefaultParams()
err := params.Validate()
require.NoError(t, err)
params2 := NewParams(
params.MintDenom,
params.InflationRateChange,
params.InflationMax,
params.InflationMin,
params.GoalBonded,
params.BlocksPerYear,
params.MaxSupply,
)
err = params2.Validate()
require.NoError(t, err)
require.Equal(t, params, params2)
params.MintDenom = ""
err = params.Validate()
require.Error(t, err)
params.MintDenom = "asd/$%!@#"
err = params.Validate()
require.Error(t, err)
params = DefaultParams()
params.InflationRateChange = math.LegacyNewDec(123)
err = params.Validate()
require.Error(t, err)
params = DefaultParams()
params.InflationRateChange = math.LegacyNewDec(-123)
err = params.Validate()
require.Error(t, err)
params = DefaultParams()
params.InflationRateChange = math.LegacyDec{}
err = params.Validate()
require.Error(t, err)
params = DefaultParams()
params.InflationMax = math.LegacyNewDec(123)
err = params.Validate()
require.Error(t, err)
params = DefaultParams()
params.InflationMax = math.LegacyNewDec(-123)
err = params.Validate()
require.Error(t, err)
params = DefaultParams()
params.InflationMax = math.LegacyDec{}
err = params.Validate()
require.Error(t, err)
params = DefaultParams()
params.InflationMin = math.LegacyNewDec(123)
err = params.Validate()
require.Error(t, err)
params = DefaultParams()
params.InflationMin = math.LegacyNewDec(-123)
err = params.Validate()
require.Error(t, err)
params = DefaultParams()
params.InflationMin = math.LegacyDec{}
err = params.Validate()
require.Error(t, err)
params = DefaultParams()
params.GoalBonded = math.LegacyNewDec(123)
err = params.Validate()
require.Error(t, err)
params = DefaultParams()
params.GoalBonded = math.LegacyNewDec(-123)
err = params.Validate()
require.Error(t, err)
params = DefaultParams()
params.GoalBonded = math.LegacyDec{}
err = params.Validate()
require.Error(t, err)
params = DefaultParams()
params.BlocksPerYear = 0
err = params.Validate()
require.Error(t, err)
params = DefaultParams()
params.MaxSupply = math.NewInt(-1)
err = params.Validate()
require.Error(t, err)
params = DefaultParams()
params.InflationMax = math.LegacyNewDecWithPrec(1, 2)
params.InflationMin = math.LegacyNewDecWithPrec(2, 2)
err = params.Validate()
require.Error(t, err)
}