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:
parent
fbd3b75c5a
commit
150ca963f2
@ -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 (
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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.
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
@ -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
125
simapp/mint_fn.go
Normal 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()),
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -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))),
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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")
|
||||
}
|
||||
|
||||
@ -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++ {
|
||||
|
||||
@ -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()
|
||||
|
||||
@ -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")
|
||||
}
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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=
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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
34
x/mint/epoch_hooks.go
Normal 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
|
||||
}
|
||||
@ -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
|
||||
|
||||
@ -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=
|
||||
|
||||
@ -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)
|
||||
}
|
||||
|
||||
@ -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()),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -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)
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
92
x/mint/module_test.go
Normal 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)
|
||||
}
|
||||
@ -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.
|
||||
|
||||
@ -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)
|
||||
}
|
||||
|
||||
21
x/mint/types/genesis_test.go
Normal file
21
x/mint/types/genesis_test.go
Normal 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)
|
||||
}
|
||||
@ -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:])
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
112
x/mint/types/params_test.go
Normal 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)
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user