diff --git a/api/desmos/tokenfactory/module/v1/module.pulsar.go b/api/desmos/tokenfactory/module/v1/module.pulsar.go new file mode 100755 index 0000000000..bb88f13c10 --- /dev/null +++ b/api/desmos/tokenfactory/module/v1/module.pulsar.go @@ -0,0 +1,583 @@ +// Code generated by protoc-gen-go-pulsar. DO NOT EDIT. +package modulev1 + +import ( + _ "cosmossdk.io/api/cosmos/app/v1alpha1" + fmt "fmt" + runtime "github.com/cosmos/cosmos-proto/runtime" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoiface "google.golang.org/protobuf/runtime/protoiface" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + io "io" + reflect "reflect" + sync "sync" +) + +var ( + md_Module protoreflect.MessageDescriptor + fd_Module_authority protoreflect.FieldDescriptor +) + +func init() { + file_desmos_tokenfactory_module_v1_module_proto_init() + md_Module = File_desmos_tokenfactory_module_v1_module_proto.Messages().ByName("Module") + fd_Module_authority = md_Module.Fields().ByName("authority") +} + +var _ protoreflect.Message = (*fastReflection_Module)(nil) + +type fastReflection_Module Module + +func (x *Module) ProtoReflect() protoreflect.Message { + return (*fastReflection_Module)(x) +} + +func (x *Module) slowProtoReflect() protoreflect.Message { + mi := &file_desmos_tokenfactory_module_v1_module_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +var _fastReflection_Module_messageType fastReflection_Module_messageType +var _ protoreflect.MessageType = fastReflection_Module_messageType{} + +type fastReflection_Module_messageType struct{} + +func (x fastReflection_Module_messageType) Zero() protoreflect.Message { + return (*fastReflection_Module)(nil) +} +func (x fastReflection_Module_messageType) New() protoreflect.Message { + return new(fastReflection_Module) +} +func (x fastReflection_Module_messageType) Descriptor() protoreflect.MessageDescriptor { + return md_Module +} + +// Descriptor returns message descriptor, which contains only the protobuf +// type information for the message. +func (x *fastReflection_Module) Descriptor() protoreflect.MessageDescriptor { + return md_Module +} + +// Type returns the message type, which encapsulates both Go and protobuf +// type information. If the Go type information is not needed, +// it is recommended that the message descriptor be used instead. +func (x *fastReflection_Module) Type() protoreflect.MessageType { + return _fastReflection_Module_messageType +} + +// New returns a newly allocated and mutable empty message. +func (x *fastReflection_Module) New() protoreflect.Message { + return new(fastReflection_Module) +} + +// Interface unwraps the message reflection interface and +// returns the underlying ProtoMessage interface. +func (x *fastReflection_Module) Interface() protoreflect.ProtoMessage { + return (*Module)(x) +} + +// Range iterates over every populated field in an undefined order, +// calling f for each field descriptor and value encountered. +// Range returns immediately if f returns false. +// While iterating, mutating operations may only be performed +// on the current field descriptor. +func (x *fastReflection_Module) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) { + if x.Authority != "" { + value := protoreflect.ValueOfString(x.Authority) + if !f(fd_Module_authority, value) { + return + } + } +} + +// Has reports whether a field is populated. +// +// Some fields have the property of nullability where it is possible to +// distinguish between the default value of a field and whether the field +// was explicitly populated with the default value. Singular message fields, +// member fields of a oneof, and proto2 scalar fields are nullable. Such +// fields are populated only if explicitly set. +// +// In other cases (aside from the nullable cases above), +// a proto3 scalar field is populated if it contains a non-zero value, and +// a repeated field is populated if it is non-empty. +func (x *fastReflection_Module) Has(fd protoreflect.FieldDescriptor) bool { + switch fd.FullName() { + case "desmos.tokenfactory.module.v1.Module.authority": + return x.Authority != "" + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: desmos.tokenfactory.module.v1.Module")) + } + panic(fmt.Errorf("message desmos.tokenfactory.module.v1.Module does not contain field %s", fd.FullName())) + } +} + +// Clear clears the field such that a subsequent Has call reports false. +// +// Clearing an extension field clears both the extension type and value +// associated with the given field number. +// +// Clear is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_Module) Clear(fd protoreflect.FieldDescriptor) { + switch fd.FullName() { + case "desmos.tokenfactory.module.v1.Module.authority": + x.Authority = "" + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: desmos.tokenfactory.module.v1.Module")) + } + panic(fmt.Errorf("message desmos.tokenfactory.module.v1.Module does not contain field %s", fd.FullName())) + } +} + +// Get retrieves the value for a field. +// +// For unpopulated scalars, it returns the default value, where +// the default value of a bytes scalar is guaranteed to be a copy. +// For unpopulated composite types, it returns an empty, read-only view +// of the value; to obtain a mutable reference, use Mutable. +func (x *fastReflection_Module) Get(descriptor protoreflect.FieldDescriptor) protoreflect.Value { + switch descriptor.FullName() { + case "desmos.tokenfactory.module.v1.Module.authority": + value := x.Authority + return protoreflect.ValueOfString(value) + default: + if descriptor.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: desmos.tokenfactory.module.v1.Module")) + } + panic(fmt.Errorf("message desmos.tokenfactory.module.v1.Module does not contain field %s", descriptor.FullName())) + } +} + +// Set stores the value for a field. +// +// For a field belonging to a oneof, it implicitly clears any other field +// that may be currently set within the same oneof. +// For extension fields, it implicitly stores the provided ExtensionType. +// When setting a composite type, it is unspecified whether the stored value +// aliases the source's memory in any way. If the composite value is an +// empty, read-only value, then it panics. +// +// Set is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_Module) Set(fd protoreflect.FieldDescriptor, value protoreflect.Value) { + switch fd.FullName() { + case "desmos.tokenfactory.module.v1.Module.authority": + x.Authority = value.Interface().(string) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: desmos.tokenfactory.module.v1.Module")) + } + panic(fmt.Errorf("message desmos.tokenfactory.module.v1.Module does not contain field %s", fd.FullName())) + } +} + +// Mutable returns a mutable reference to a composite type. +// +// If the field is unpopulated, it may allocate a composite value. +// For a field belonging to a oneof, it implicitly clears any other field +// that may be currently set within the same oneof. +// For extension fields, it implicitly stores the provided ExtensionType +// if not already stored. +// It panics if the field does not contain a composite type. +// +// Mutable is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_Module) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + case "desmos.tokenfactory.module.v1.Module.authority": + panic(fmt.Errorf("field authority of message desmos.tokenfactory.module.v1.Module is not mutable")) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: desmos.tokenfactory.module.v1.Module")) + } + panic(fmt.Errorf("message desmos.tokenfactory.module.v1.Module does not contain field %s", fd.FullName())) + } +} + +// NewField returns a new value that is assignable to the field +// for the given descriptor. For scalars, this returns the default value. +// For lists, maps, and messages, this returns a new, empty, mutable value. +func (x *fastReflection_Module) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + case "desmos.tokenfactory.module.v1.Module.authority": + return protoreflect.ValueOfString("") + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: desmos.tokenfactory.module.v1.Module")) + } + panic(fmt.Errorf("message desmos.tokenfactory.module.v1.Module does not contain field %s", fd.FullName())) + } +} + +// WhichOneof reports which field within the oneof is populated, +// returning nil if none are populated. +// It panics if the oneof descriptor does not belong to this message. +func (x *fastReflection_Module) WhichOneof(d protoreflect.OneofDescriptor) protoreflect.FieldDescriptor { + switch d.FullName() { + default: + panic(fmt.Errorf("%s is not a oneof field in desmos.tokenfactory.module.v1.Module", d.FullName())) + } + panic("unreachable") +} + +// GetUnknown retrieves the entire list of unknown fields. +// The caller may only mutate the contents of the RawFields +// if the mutated bytes are stored back into the message with SetUnknown. +func (x *fastReflection_Module) GetUnknown() protoreflect.RawFields { + return x.unknownFields +} + +// SetUnknown stores an entire list of unknown fields. +// The raw fields must be syntactically valid according to the wire format. +// An implementation may panic if this is not the case. +// Once stored, the caller must not mutate the content of the RawFields. +// An empty RawFields may be passed to clear the fields. +// +// SetUnknown is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_Module) SetUnknown(fields protoreflect.RawFields) { + x.unknownFields = fields +} + +// IsValid reports whether the message is valid. +// +// An invalid message is an empty, read-only value. +// +// An invalid message often corresponds to a nil pointer of the concrete +// message type, but the details are implementation dependent. +// Validity is not part of the protobuf data model, and may not +// be preserved in marshaling or other operations. +func (x *fastReflection_Module) IsValid() bool { + return x != nil +} + +// ProtoMethods returns optional fastReflectionFeature-path implementations of various operations. +// This method may return nil. +// +// The returned methods type is identical to +// "google.golang.org/protobuf/runtime/protoiface".Methods. +// Consult the protoiface package documentation for details. +func (x *fastReflection_Module) ProtoMethods() *protoiface.Methods { + size := func(input protoiface.SizeInput) protoiface.SizeOutput { + x := input.Message.Interface().(*Module) + if x == nil { + return protoiface.SizeOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Size: 0, + } + } + options := runtime.SizeInputToOptions(input) + _ = options + var n int + var l int + _ = l + l = len(x.Authority) + if l > 0 { + n += 1 + l + runtime.Sov(uint64(l)) + } + if x.unknownFields != nil { + n += len(x.unknownFields) + } + return protoiface.SizeOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Size: n, + } + } + + marshal := func(input protoiface.MarshalInput) (protoiface.MarshalOutput, error) { + x := input.Message.Interface().(*Module) + if x == nil { + return protoiface.MarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Buf: input.Buf, + }, nil + } + options := runtime.MarshalInputToOptions(input) + _ = options + size := options.Size(x) + dAtA := make([]byte, size) + i := len(dAtA) + _ = i + var l int + _ = l + if x.unknownFields != nil { + i -= len(x.unknownFields) + copy(dAtA[i:], x.unknownFields) + } + if len(x.Authority) > 0 { + i -= len(x.Authority) + copy(dAtA[i:], x.Authority) + i = runtime.EncodeVarint(dAtA, i, uint64(len(x.Authority))) + i-- + dAtA[i] = 0xa + } + if input.Buf != nil { + input.Buf = append(input.Buf, dAtA...) + } else { + input.Buf = dAtA + } + return protoiface.MarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Buf: input.Buf, + }, nil + } + unmarshal := func(input protoiface.UnmarshalInput) (protoiface.UnmarshalOutput, error) { + x := input.Message.Interface().(*Module) + if x == nil { + return protoiface.UnmarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Flags: input.Flags, + }, nil + } + options := runtime.UnmarshalInputToOptions(input) + _ = options + dAtA := input.Buf + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: Module: wiretype end group for non-group") + } + if fieldNum <= 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: Module: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field Authority", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if postIndex > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + x.Authority = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := runtime.Skip(dAtA[iNdEx:]) + if err != nil { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + if !options.DiscardUnknown { + x.unknownFields = append(x.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + } + iNdEx += skippy + } + } + + if iNdEx > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, nil + } + return &protoiface.Methods{ + NoUnkeyedLiterals: struct{}{}, + Flags: protoiface.SupportMarshalDeterministic | protoiface.SupportUnmarshalDiscardUnknown, + Size: size, + Marshal: marshal, + Unmarshal: unmarshal, + Merge: nil, + CheckInitialized: nil, + } +} + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.27.0 +// protoc (unknown) +// source: desmos/tokenfactory/module/v1/module.proto + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// Module is the config object of the tokenfactory module. +type Module struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // authority defines the custom module authority. If not set, defaults to the + // governance module. + Authority string `protobuf:"bytes,1,opt,name=authority,proto3" json:"authority,omitempty"` +} + +func (x *Module) Reset() { + *x = Module{} + if protoimpl.UnsafeEnabled { + mi := &file_desmos_tokenfactory_module_v1_module_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Module) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Module) ProtoMessage() {} + +// Deprecated: Use Module.ProtoReflect.Descriptor instead. +func (*Module) Descriptor() ([]byte, []int) { + return file_desmos_tokenfactory_module_v1_module_proto_rawDescGZIP(), []int{0} +} + +func (x *Module) GetAuthority() string { + if x != nil { + return x.Authority + } + return "" +} + +var File_desmos_tokenfactory_module_v1_module_proto protoreflect.FileDescriptor + +var file_desmos_tokenfactory_module_v1_module_proto_rawDesc = []byte{ + 0x0a, 0x2a, 0x64, 0x65, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x66, 0x61, + 0x63, 0x74, 0x6f, 0x72, 0x79, 0x2f, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x2f, 0x76, 0x31, 0x2f, + 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1d, 0x64, 0x65, + 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x66, 0x61, 0x63, 0x74, 0x6f, 0x72, + 0x79, 0x2e, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x1a, 0x20, 0x63, 0x6f, 0x73, + 0x6d, 0x6f, 0x73, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, + 0x2f, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x5c, 0x0a, + 0x06, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, + 0x72, 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x75, 0x74, 0x68, + 0x6f, 0x72, 0x69, 0x74, 0x79, 0x3a, 0x34, 0xba, 0xc0, 0x96, 0xda, 0x01, 0x2e, 0x0a, 0x2c, 0x67, + 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x64, 0x65, 0x73, 0x6d, 0x6f, 0x73, + 0x2d, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x64, 0x65, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x78, 0x2f, 0x74, + 0x6f, 0x6b, 0x65, 0x6e, 0x66, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x42, 0x80, 0x02, 0x0a, 0x21, + 0x63, 0x6f, 0x6d, 0x2e, 0x64, 0x65, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x74, 0x6f, 0x6b, 0x65, 0x6e, + 0x66, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x2e, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x2e, 0x76, + 0x31, 0x42, 0x0b, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, + 0x5a, 0x37, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x61, + 0x70, 0x69, 0x2f, 0x64, 0x65, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x66, + 0x61, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x2f, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x2f, 0x76, 0x31, + 0x3b, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x44, 0x54, 0x4d, 0xaa, + 0x02, 0x1d, 0x44, 0x65, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x66, 0x61, + 0x63, 0x74, 0x6f, 0x72, 0x79, 0x2e, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x2e, 0x56, 0x31, 0xca, + 0x02, 0x1d, 0x44, 0x65, 0x73, 0x6d, 0x6f, 0x73, 0x5c, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x66, 0x61, + 0x63, 0x74, 0x6f, 0x72, 0x79, 0x5c, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x5c, 0x56, 0x31, 0xe2, + 0x02, 0x29, 0x44, 0x65, 0x73, 0x6d, 0x6f, 0x73, 0x5c, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x66, 0x61, + 0x63, 0x74, 0x6f, 0x72, 0x79, 0x5c, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x5c, 0x56, 0x31, 0x5c, + 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x20, 0x44, 0x65, + 0x73, 0x6d, 0x6f, 0x73, 0x3a, 0x3a, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x66, 0x61, 0x63, 0x74, 0x6f, + 0x72, 0x79, 0x3a, 0x3a, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_desmos_tokenfactory_module_v1_module_proto_rawDescOnce sync.Once + file_desmos_tokenfactory_module_v1_module_proto_rawDescData = file_desmos_tokenfactory_module_v1_module_proto_rawDesc +) + +func file_desmos_tokenfactory_module_v1_module_proto_rawDescGZIP() []byte { + file_desmos_tokenfactory_module_v1_module_proto_rawDescOnce.Do(func() { + file_desmos_tokenfactory_module_v1_module_proto_rawDescData = protoimpl.X.CompressGZIP(file_desmos_tokenfactory_module_v1_module_proto_rawDescData) + }) + return file_desmos_tokenfactory_module_v1_module_proto_rawDescData +} + +var file_desmos_tokenfactory_module_v1_module_proto_msgTypes = make([]protoimpl.MessageInfo, 1) +var file_desmos_tokenfactory_module_v1_module_proto_goTypes = []interface{}{ + (*Module)(nil), // 0: desmos.tokenfactory.module.v1.Module +} +var file_desmos_tokenfactory_module_v1_module_proto_depIdxs = []int32{ + 0, // [0:0] is the sub-list for method output_type + 0, // [0:0] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_desmos_tokenfactory_module_v1_module_proto_init() } +func file_desmos_tokenfactory_module_v1_module_proto_init() { + if File_desmos_tokenfactory_module_v1_module_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_desmos_tokenfactory_module_v1_module_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Module); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_desmos_tokenfactory_module_v1_module_proto_rawDesc, + NumEnums: 0, + NumMessages: 1, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_desmos_tokenfactory_module_v1_module_proto_goTypes, + DependencyIndexes: file_desmos_tokenfactory_module_v1_module_proto_depIdxs, + MessageInfos: file_desmos_tokenfactory_module_v1_module_proto_msgTypes, + }.Build() + File_desmos_tokenfactory_module_v1_module_proto = out.File + file_desmos_tokenfactory_module_v1_module_proto_rawDesc = nil + file_desmos_tokenfactory_module_v1_module_proto_goTypes = nil + file_desmos_tokenfactory_module_v1_module_proto_depIdxs = nil +} diff --git a/app/app.go b/app/app.go index e9466ea5ea..37b6ff1072 100644 --- a/app/app.go +++ b/app/app.go @@ -81,8 +81,8 @@ import ( relationshipskeeper "github.com/desmos-labs/desmos/v5/x/relationships/keeper" reportskeeper "github.com/desmos-labs/desmos/v5/x/reports/keeper" subspaceskeeper "github.com/desmos-labs/desmos/v5/x/subspaces/keeper" - supplykeeper "github.com/desmos-labs/desmos/v5/x/supply/keeper" + tokenfactorykeeper "github.com/desmos-labs/desmos/v5/x/tokenfactory/keeper" authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" @@ -171,6 +171,7 @@ type DesmosApp struct { ReportsKeeper reportskeeper.Keeper ReactionsKeeper reactionskeeper.Keeper SupplyKeeper supplykeeper.Keeper + TokenFactoryKeeper tokenfactorykeeper.Keeper // Simulation manager sm *module.SimulationManager @@ -248,6 +249,7 @@ func NewDesmosApp( &app.ReportsKeeper, &app.ReactionsKeeper, &app.SupplyKeeper, + &app.TokenFactoryKeeper, ); err != nil { panic(err) } diff --git a/app/app_config.go b/app/app_config.go index 3e7c022036..032caa0fec 100644 --- a/app/app_config.go +++ b/app/app_config.go @@ -4,15 +4,6 @@ import ( "os" "path/filepath" - "github.com/desmos-labs/desmos/v5/x/reactions" - supplytypes "github.com/desmos-labs/desmos/v5/x/supply/types" - - postskeeper "github.com/desmos-labs/desmos/v5/x/posts/keeper" - poststypes "github.com/desmos-labs/desmos/v5/x/posts/types" - - "github.com/desmos-labs/desmos/v5/x/posts" - "github.com/desmos-labs/desmos/v5/x/relationships" - sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/auth/vesting" vestingtypes "github.com/cosmos/cosmos-sdk/x/auth/vesting/types" @@ -75,11 +66,16 @@ import ( upgradeclient "github.com/cosmos/cosmos-sdk/x/upgrade/client" upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" + "github.com/desmos-labs/desmos/v5/x/posts" + postskeeper "github.com/desmos-labs/desmos/v5/x/posts/keeper" + poststypes "github.com/desmos-labs/desmos/v5/x/posts/types" "github.com/desmos-labs/desmos/v5/x/profiles" profileskeeper "github.com/desmos-labs/desmos/v5/x/profiles/keeper" profilestypes "github.com/desmos-labs/desmos/v5/x/profiles/types" + "github.com/desmos-labs/desmos/v5/x/reactions" reactionskeeper "github.com/desmos-labs/desmos/v5/x/reactions/keeper" reactionstypes "github.com/desmos-labs/desmos/v5/x/reactions/types" + "github.com/desmos-labs/desmos/v5/x/relationships" relationshipskeeper "github.com/desmos-labs/desmos/v5/x/relationships/keeper" relationshipstypes "github.com/desmos-labs/desmos/v5/x/relationships/types" "github.com/desmos-labs/desmos/v5/x/reports" @@ -88,6 +84,9 @@ import ( "github.com/desmos-labs/desmos/v5/x/subspaces" subspaceskeeper "github.com/desmos-labs/desmos/v5/x/subspaces/keeper" subspacestypes "github.com/desmos-labs/desmos/v5/x/subspaces/types" + supplytypes "github.com/desmos-labs/desmos/v5/x/supply/types" + "github.com/desmos-labs/desmos/v5/x/tokenfactory" + tokenfactorytypes "github.com/desmos-labs/desmos/v5/x/tokenfactory/types" "github.com/desmos-labs/desmos/v5/x/supply" @@ -198,6 +197,7 @@ var ( reports.AppModuleBasic{}, reactions.AppModuleBasic{}, supply.AppModuleBasic{}, + tokenfactory.AppModuleBasic{}, ) // Module account permissions @@ -212,6 +212,7 @@ var ( {Account: wasm.ModuleName, Permissions: []string{authtypes.Burner}}, {Account: ibcfeetypes.ModuleName}, {Account: icatypes.ModuleName}, + {Account: tokenfactorytypes.ModuleName, Permissions: []string{authtypes.Minter, authtypes.Burner}}, } // During begin block slashing happens after distr.BeginBlocker so that @@ -252,6 +253,7 @@ var ( reportstypes.ModuleName, reactionstypes.ModuleName, supplytypes.ModuleName, + tokenfactorytypes.ModuleName, wasm.ModuleName, } @@ -289,6 +291,7 @@ var ( reportstypes.ModuleName, reactionstypes.ModuleName, supplytypes.ModuleName, + tokenfactorytypes.ModuleName, wasm.ModuleName, } @@ -333,6 +336,7 @@ var ( reportstypes.ModuleName, reactionstypes.ModuleName, supplytypes.ModuleName, + tokenfactorytypes.ModuleName, // wasm module should be at the end of app modules wasm.ModuleName, @@ -374,6 +378,7 @@ var ( reportstypes.ModuleName, reactionstypes.ModuleName, supplytypes.ModuleName, + tokenfactorytypes.ModuleName, wasm.ModuleName, crisistypes.ModuleName, diff --git a/app/app_module_config.go b/app/app_module_config.go index 5d51bb5f89..c2b175dc3a 100644 --- a/app/app_module_config.go +++ b/app/app_module_config.go @@ -55,6 +55,7 @@ import ( reportsmodulev1 "github.com/desmos-labs/desmos/v5/api/desmos/reports/module/v1" subspacesmodulev1 "github.com/desmos-labs/desmos/v5/api/desmos/subspaces/module/v1" supplymodulev1 "github.com/desmos-labs/desmos/v5/api/desmos/supply/module/v1" + tokenfactorymodulev1 "github.com/desmos-labs/desmos/v5/api/desmos/tokenfactory/module/v1" poststypes "github.com/desmos-labs/desmos/v5/x/posts/types" profilestypes "github.com/desmos-labs/desmos/v5/x/profiles/types" @@ -63,6 +64,7 @@ import ( reportstypes "github.com/desmos-labs/desmos/v5/x/reports/types" subspacestypes "github.com/desmos-labs/desmos/v5/x/subspaces/types" supplytypes "github.com/desmos-labs/desmos/v5/x/supply/types" + tokenfactorytypes "github.com/desmos-labs/desmos/v5/x/tokenfactory/types" ) var ( @@ -77,6 +79,7 @@ var ( ibcfeetypes.ModuleName, icatypes.ModuleName, wasmtypes.ModuleName, + tokenfactorytypes.ModuleName, // We allow the following module accounts to receive funds: // govtypes.ModuleName @@ -224,6 +227,10 @@ var ( Name: supplytypes.ModuleName, Config: appconfig.WrapAny(&supplymodulev1.Module{}), }, + { + Name: tokenfactorytypes.ModuleName, + Config: appconfig.WrapAny(&tokenfactorymodulev1.Module{}), + }, }, }) ) diff --git a/app/sim_test.go b/app/sim_test.go index 9e2d2320b1..dfb5a87763 100644 --- a/app/sim_test.go +++ b/app/sim_test.go @@ -20,6 +20,7 @@ import ( relationshipstypes "github.com/desmos-labs/desmos/v5/x/relationships/types" reportstypes "github.com/desmos-labs/desmos/v5/x/reports/types" subspacestypes "github.com/desmos-labs/desmos/v5/x/subspaces/types" + tokenfactorytypes "github.com/desmos-labs/desmos/v5/x/tokenfactory/types" authzkeeper "github.com/cosmos/cosmos-sdk/x/authz/keeper" minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" @@ -258,6 +259,7 @@ func TestAppImportExport(t *testing.T) { {app.GetKey(poststypes.StoreKey), newApp.GetKey(poststypes.StoreKey), [][]byte{}}, {app.GetKey(reportstypes.StoreKey), newApp.GetKey(reportstypes.StoreKey), [][]byte{}}, {app.GetKey(reactionstypes.StoreKey), newApp.GetKey(reactionstypes.StoreKey), [][]byte{}}, + {app.GetKey(tokenfactorytypes.StoreKey), newApp.GetKey(tokenfactorytypes.StoreKey), [][]byte{}}, {app.GetKey(wasmtypes.StoreKey), newApp.GetKey(wasmtypes.StoreKey), [][]byte{wasmtypes.TXCounterPrefix}}, } diff --git a/client/docs/config.json b/client/docs/config.json index c83d871d30..9a76b016b3 100644 --- a/client/docs/config.json +++ b/client/docs/config.json @@ -41,6 +41,9 @@ }, { "url": "./tmp-swagger-gen/desmos/supply/v1/query.swagger.json" + }, + { + "url": "./tmp-swagger-gen/desmos/tokenfactory/v1beta1/query.swagger.json" } ] } \ No newline at end of file diff --git a/client/docs/statik/statik.go b/client/docs/statik/statik.go index 6f9533a035..78fb42ebba 100644 --- a/client/docs/statik/statik.go +++ b/client/docs/statik/statik.go @@ -8,6 +8,6 @@ import ( ) func init() { - data := "PK\x03\x04\x14\x00\x08\x00\x08\x00\x00\x00!(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0c\x00 \x00swagger.yamlUT\x05\x00\x01\x80Cm8\xec\xfd]w\xdc8\xb2\xe7\x0b\xdf\xfbS\xc4S\x17S\xae\x19[\xae\xee\xea\xf5\\\xf8\x9c=\xeb\xb8mU\xb7f\xdc\xb6\xb6,\xf7\xac>\xb3\xf6RS\x99\xc8\x14\xc7\x99d6\x89\xb4\xad]\xbb\xbf\xfbYx#A&^\x02H\xa4\xa5]\x15qS.%\x19\x04\x82 \x08\xe2\xffC\xa0\xffR\xad\xd7\xac{ \xdf\xff\xfe\xec\xc7\xef\x9f\xd4\xcd\xaa}\xf9\x04\x80\xd7|\xc3^\xc2\x1b\xd6o\xdb\x1e\x9e\xc3\xd5\xf9\x87k\xa8\x9a%\xac\xaf._\xc3\x9f*\xce\xbeT\xf7\xb0l\x17\xfd\x13\x80%\xeb\x17]\xbd\xe3u\xdb\xbc\x84W\xea\xd8\xba\xe1\xac[U\x0b\x06\xab\xb6\x83\x9eW\x9c\xc1?\xf6\xac\xab\x998\xe33\xebzy\xf4Og?\x9e\xfd\xf8dW\xf1\xbb^\\\xf6\xc5R^\xf0\xc5\xaekW\xf5\x86\xf5/>\xff\xf4\xa2\xda\xed\x9eo\xea\xe6\x93<\x00`\xcd\xb8\xfa\x07@\xbf\xdfn\xab\xee\xfe%\xfc\xf7\xe7\xfa/\x00\xafv\xbbM\xbd\xa8DY\xde\x8a\x93\xccE\x81\xdf1\xa8\xc6\x1f{\x90>\xa1\xea\xfbvQW\x9c-\x81\xb7\xf2\xa0u\xfd\x995O\x06\x87\xfb\x9eu\xcf\xa0^\xc1\xaek?\xd7K\xb6<\x83\xf7\xfc\x8eu_\xea\x9e=\x83\x9a\x0f\x17\xa86\x9b\xf9E\xd45\x06W=o;\xb6<\xd3\xff\xdf\xeeX'\x8f\xbaX\xbe<(\xb6>\xa6c\xfd\xaemz\xd6\xbf\x1c\x9c|\xff\xfb\x1f\x7f\xfc~\xfc\xdf\x83\xe8\xf7\xfb\xc5\x82\xf5\xfdj\xbf\x19\xce>\xb3\x8e\xee\x17wl[\xd9\xe7\x03\xf0\xfb\x1d{ \xed\xed\xffa\x0b>\xf9a\xd7\x89B\xf2\xda\xbe\xbe2\xeb\x86\xd8\xa6\x83\xeb/5\xe7\xe2 \xfaS\xcd\xff\xbc\xbf}\x06\x8c/~\xf0:\x14\xf7R\x9c[\xaedV\xd7\xe0\xb2\x8f\xfa\x82\xd06\x07\x0f\xaf]~\xe0\xd5\xda\xd4!\xe8P\xf7\\\x81z\xca\xbe0\xd2b>\xc8\xfeR\xb6\x0e\x16o\x13\xc1X\xb0f\xbf\xf5\x87\xf39\xbc\xba\xbc|{\xf1\xfa\xd5\xf5\xc5\xfbw7o/\xde\xfd\xcf\x9b\x0f\xd7\xaf\xae\xcfo.\xde]\\_\xbcz{\xf1\xff\x9e\xbf\xb9\xf9\xf8\xee\xc3\xe5\xf9\xeb\x8b\x9f/\xce\xdf\xa4;\xfa\xeb\xf9\xd5\xc5\xcf\xe6\xef\x1f\xae_]]\x1f\xed\xe5\xfc\xea\xea\xfd\xd5\x91>>||\xfd\xfa\xfc\xc3\x87t/\xd7\x17\x7f9\x7fs\xf3\xfe\xe3\xb5\xe7\xd4%[U\xfb\x0d\x7fY&\xb0\x93\xce=\xd0\x96S\xef\xa3xS\x04\xda\x15\xc0]\xd5\xc3\xff\xd9\xf7\x1cn\x19k\xa0nj^W\x9b\xfa\xdf=\x9d\xa04d\xe0U\x130\x05\x18/\xd4\xf3\xaa\x13\xaf\xe1[V7k1B\xa8W\xf5\xf1\x97\x93mer1\xd6u\xe25\x0c\xcb\xbdxj\xe4\x13\xa6.\xa6\x1f\xfb]\xd7\x8a\x17\xe8\xb1\x17\xd6\x0dlr\xe9i\xd5\xacW\xf5\xe6\xf0u\x19\xbf\xdc\xd0\x12'\xd7\xe0\xf5\x96-\xa1\xdds\xf1*\xdb0\xf8R\xd5\\\\U\x0c\xc3\xe6uu^\xb4\xed\xaa\xc5\x86\xddt\xec\x1f{\xd6\xf3HG\x15h\x92\xef\xa5\x9f+\xe5\x06:\xb6\xebX\xcf\x1a\xae^\x80\xda;\xf0\xbb\x8a\xeb\xd0\xb0\x06\xb6\xd5\x92y\xfd\xe9\xe1\x99*\xdei\xdf\x91\xf5\xb2\xc0\x0bh\xd5v\xdb\x8a\xbf\x84}\xdd\xf0\xff\xff\x1f\xe2o\xaa\x8b7b\xb4!\xaax\xf1\xc6t\xfd:L\xde\x93\xf5\xbdR}\xc4\xcd\x83\x14[\xdd\xe6\x0f\xb2\x04\xaa\n\xaa\xf8U\xa3K\x07\xaat^O\x8bj\xb3\xb9 \x8d\xa2\x00\xd5\xdc\x84\xbd\xae6\x1b\xc7`K\xfce\xdf\xab\x11\xfe\x8eu\xa2\x86\xe2\x87\xa0+]\xf6\xd8\x0d@59@6;\xc0\x0f\xcf\x00\x7fC\x01\x1d>a\xf3\x91\x9c\xe86\xc61q\xfb\xa5a]\x7fW\xef\xa0\xbfk\xf7\x9b@\xef\xac\xed\x96!zrl#\x80SV\xfa\x8e}\x05\xd6,\xda%[\xca\xd2\xa8f#\xfb'UWQ\x17\xdd\x8a\xa2\x0ee\x9d\xef\xe7#\xca'\xd1\xf3\xaa\xc5\xa2\xdd7|\x8c\xb3\xff\xa9\xd9\xd4\xac)\xf4\xc8\xe3\x02\xf5Z^\xf1\xe2\xcd\xbc+\x1f{+U\xa6\xa1O\x8f\xdep\x11\xcb\xa1G\x0fu\x13\x1d\xeb\xc5\x90\xca\xe3P\x17\xff?\xfc\xc5\xd7}\xc2V\xbe\x07\xbbv\xab\xfbV\xe1\xd4\x94\xdd~-\x9ey\x1d\xbdo6\xf7P}\xae\xeaMu+\xde\xadwL}6\xa8\xf9\x8d\xba\x07\xf5f\x0e\x0f.\x11=\x06\xa6\xb7\xd0\xa3\x07D\xaf\xf9A\x1di\xdf\xb8\xca\x9e'\x88\x0e \xb4\xb7x\xb9\x01Yva\x9f\xab\xcd>\xf8\xa1\x07\xf8\x16\x0c\xe8V,\xec\xcf\xec\xebs\xf3\xa8\xcbR\xd8\xc3\x10\xe8\xebu#\x86\xa1\xf7\xd1w\x04\x8c\xdf{\xc1\xe3\x84\xc7\x8a\xef\xbb\x87\xaf\xedP\x92\xd9\xc0k\xd7\xb5\xcb\xfdB\xd6:\xeaO\xf8\x18\x06\xce\"z\xde3VU\xbda\xe1\x0eJ\xd5\xe2gy\xe0\xb4}\xaa\x93\x1f\xa8m\xcao\x84\xf2w\xeb\\\xb8U\xa1\x9fL,\xc1\x97\x9a\xab\x17\xac\xa8\xf5\xbes\x87t\xd11\x19\x86\x1b1\xc4?b\xc6\xcb\x8c\xf0\x96\x15g\xcf\x85\xafp\xbf\x1ahb\xafu\x89\xae\xeb-\x9b\xbf\x16\x84c\xa8\x9b\xf9\x84\xda\x97\xc0{AV\xd03P`_wu\xf7\xc8\xaa\x7f>\x94 \x1f\x00\xaf\xb3/\xf5f\xa3j\xe9*P\xb80\xb3\xd9c\xc7\xf0W\x0c\xc8\xd5\x0d\xe0-T\xb0`\x0d\xef\x02\xdf\xf3\xf6\xa0e\xfa\xcb\xaeZ\xd7\x8dgx\xaa\x0by9\x1c\x02K\xb6\xaa\x1b=\xf9>\x9e9LL\x1fz\x08=\xc6\xe1\x87\xb7a_\xf9\xcd'v\xefn\x19\xd1vaZ\xc5\xed=w7\x88\xc9L\x8cw\xacaJa>\xe5\xc4?y+^+\xbb\xaa\xd7\x9f \x97\xd5\xda|\x16\x9f\xa9\xdf=\xce\xfe\xb1g\x9d\x1aD\n\xb7\"\x80\x0c\xb6m\xcf\x81\xadV\xf5B\x8c\xb56\xf7gp\xc1U\xdb\xb9e\xc0\xb6;~\x0f\xf5\xca\xd7\xa2\xefX\xc7\xa0\xea\x184-l\xdb\xce\x8c\x81z\xd7\x80\x87\xb7\xbc\xda\x1c\x19\xcc\xc07d\xec\xe9\x92\x97\x97Q\x94\xffh\xf6\xdb[\xd6\x89f\xac\x8bl\x8d\xc2\xbc\xf5\xb5\x03-\xc7\xd57\xd2\x99o\x18\xfe\xa5\xea\xa1g\xfc\x19\xd4\xbc\xd7\xe3\x82\xba\x87}\xa3\x1a\xf1\x12Z#\xfb\x1c\x9c\x1f\x9f\xa5SEQ\xad^\xd5J\xdd\xaf[\xb6\x14\xef\xe5\xbaQ\xc2\x9ay0`\xcb\xfa\xbeZ\xb3^\x0c1\xdd\x1d\xc2\x1ds\xd5c\xd1v\xca\xc7R\xbc\xa2\xcd,\x8b\xf6&\xdf\xf7\xf2\x13\xc6\x8e\x8c3\x1c\xe6\x8c\x0f\xedv,\xf7/\xde\xceK\x8e\xd1w\xb2\xf7\x86?V\xddp\x93\xfe\x05~\xf7\x7f\x85N\x9a\x84E\xb6\xef\x7f\x81\xdf;\xcf\xf8\xe7\xe4\x8f\xbe\xd6\xf3\xaf\xe2\x89\x99ki\xc3\x05\x0e\xe6\xa0\xf4\xdf\xf5\xcc\x92|\xdcf\x0eE\xb4\xe6\x01\xe2-\xac\x19\x9f\x7f\xdci=Q|/W\xa3\x9e\xb3\xefY7\x9cn\xa6\x86-\x7fS\xf1\xae\x81}\xc3\xbe\xee\xd8B\xc4Q\x8eAN\xa9\xe1y\x069\x81\xa7[\x0c\"}'\xd4\x0dgk\xab\xb2\xc6L_P7\xfc\xa7\xdf\xcf~\xd5\xad,\xa9\x0cZ:\xf3\x9d\xf3m\xb5Gq\xfa\xcd\xbe\xf3\xf4\x93\x88\x9e\x12\xd3w({\x05\x1f\xaf\xde\xbe\xe8X\xdf\xee\xbb\x05S\n\x9b\x1cI\xee\x9b\xfa\x1f{\xb6\xb9\x87z\xc9\x1a^\xaf\x8c\xd8-\xae\x0d\xad\xafo\x04\xf5\xdd\xca:3\xad\xef=n\xd7\xb5\xbc]\xb4\x1b\xb8\xdd\xafV\xac37\xed\x0c\xae\xa5r)\xeb\x06\xdb}\xcf\xcd\xb0\x03*\xff\x10|\xc3\xaa\x9e\xfb\xaf\xd56\x0c\xbe{\xf1\x1d,\xee\xaa\xaeZp\xd6\x9d\xc9\xb9\x99M\xd5s\xe8\xd9z\xcb\x9a\xe1\x83\xfd\xe3\xd5\xdb\xef{\xd8U\xfc\xce\xebM\x16jx\xe8\xfdW\x95\x03\xef\xfdfs\x0f\xff\xd8W\x1b57\xafD\xc1\xd5\x18\xc9\xa7U\x0fu`\n\xe7\xef\xa2(/\xd6m\xbb\xde\xb03\x19\xb3\xdb\xfd\xea\xec\xcd^\x0d\x10\xff\xfe\x83\xaa\x89t;\xce'\xd5\xfeo\x9a\n\x16U\xd36\xf5\xa2\xda\xc8g\xc8\x7f\xe5\xa7\xecl}\xf6L\x84Vv\xfa\xdf\x9d}'\xde0M\xcb\xa1Z,\xd8\x8e\xb3\xe5\x0fgO\xfc\xa7_\x88\xcf\xbfj\xc1\xeb\x05{\x06\x9cU[\xf1\x8e\xd8W\"\x1c\xbb\x8e-\xda\xed\xae\x16/\xd9F\xf7\x92\xb7uS\x1dt\x93\xa3I\n\xe2~'\xdb`%;\xc9{\xff\xa5U_\x075\x17}\xea\xbe\x97\xc3e9\x91\xd46\\\x8cx\xda\x15\xbcj\xee\xcf\xe0\xcf\xed\x17\xf6\x99u\xcfD \xbc\xce>^\xbd\xed\xf5`[\xb8\xf2\xbc \x95\xc9\x1e\x94\xc1\xdf\xef8\xdf\xfd\xfd\x99\xfao\xff\xf7g\xd0vbh\xa4~}&[\xe3\xa2j\xa0\x95Og\x15Riz\xc6a\xbf\x83J\xd6=p]\xd6}f\xfa\x0bp[\xedz\xd5\xb4d\xc9y;\xbct\xe5\x80\xa3\xe6\x92R |.\xad\xda\xcd\xa6\xfd\xd2\xbf\x0c\xdc\xdb\xff\n\x17\xab\xb1F\xa2Y\x18\x8ae\xa8\xb4\xfe\x12\xddo\xd9\xd2=\x14\xd0\x8e^5\xf0\xe7\xeb\xebK\xf8\xd3\xf9\xb5\x11\xcb?^\xbdU\xcf\xd8}\xcd6K\xa8\xbcg\xff\xef\xf9cq}\xbfc\xff\xf6\xbf\xff\xcd{\x02\x98\xf1W\xa3\xdb\x9b~\x8d\xc8;\xa4'+\xa0j\xd4+\xcc?]\xf7_\xed/\xa3^\x8e|+\x1135\x0e_T\x0b\xd1\xb7\xb4\xed\xa7\xfdn\x18\xb1\xdcV}`\xaaZU6DG\xd1\xcc{)x\xaa\x95\\\xf5\xb5\xa7\x1em?R\xb3\xad\xd7w\x1cn\x03\x9d\x92\xac\xb4\x9c\x81\xaa\xb7\xbb\x0d\x13/Y5\xa2\x1dF\xb1=\xdbV\x0d\xaf\x17\xce\x0f\xc5\xc8L.b\x08\x14\xfd\xf6\xc6\x8f\x92\xfe\xa2\x90\x05\xa8D\xa1\xea\xa55\xc09\x18\xc7\xe8\x97{u\xdb~\xf6\xb7i\x1d\x02\xfd(\xb8\xaa\x8f)\xd9\xdf_5\xf7\x7f\x1fge\xaa\x06\xaa\xee\xb6\xe6\x9dx\x88\xfd%t\xba2\xef\x88j\xd3\xea\xa6\x07\x95\xfb\xd6\x8a\xdeY\xbehT o\xa7\xc3\xc2\xd9\xf0o\x18\xd5y\x9a\xe6\xa5yp6\xf5\xad,\xb6~\x8f\xf4\xd0\xefw\xbb\xb6\x93o\xf0]\xb5\xf8\xf4b\xdf\x88\xff\x88\xf7\xb6j\x17\xee'H\xbf\xe8\xfd\x03\x9bv\x05{\xae:6\xd3=\xf4\xa2c\xad\x96\xcbZ\xf5\x15\xb0f\x0d\xeb\xe4'\xe7\x96\xf1\xbbv\xa9q:\xf7\xcd\x14\xe5Q\xb7\xd0}\xbd\xf3\xaf\x95h\xfc\xf0\xbb\x97p)\xca/\xfa\x05]\x95j\x08z\xdd\xc0\xeb\xff\xf6\xdf\x02\xaf\xc9\x9f\xdb\x16Vm\x0b\xff\x02ggg\xfe/_Q\x98\xaa\xb9\xf7\x1fP5\xf7g\xa2\x18?w\xed\xf6\xe9\xaam\x7f\xf0\x1fzv\xe6\x7f\xff\xd5+x*\\}\x94\x15\xb9n\x9f\xfe\x17\xe1\xeb\x87\xe0\x87|\xc8\xdf?\xc3\xb1\xfb}$v\xff\xa3\xfa\\\x15\x0b\x1e\xfc\x8b\x1c\x1b\x8a\xab\x14\x88P\xdd?\xfd\xb9m\xcf\x16\x9b\xaa\xef#\x01RE\x14'\xa9:Z'\xfa\xcb\x10\x89\xdcO\x91\xc8]\xde\xf3\xbb\xb6 \xc4N\x15\xea\xe7\xb6}zvv\xe6\x7f\x19\x0cq{\x1a\\\xe0\xf6~\x1c\xc6\x99\xb7\x91\x9a\x00w\x8f\xa2\xf5\xac\x9b\x18\xe6\xb8/\xf5\xbdc\x88\xf6b\xb5\xdfl\xce\xe4\x0fb\xf8\xfb=T\xd6\xdbS\xbcYE\xdb\xf2\xbdkT\x9bs_lxU5\x9b{\xf3\x9dz0\xf90\x0c\xbb\xa1ZI\xf8\xd8s!9/\xf2\xfd\x8b\xef\xdd\x97\xd2\xefXSd\xf9\xf5\x0cL?#\xdf\xad\xda\xf6\xec\xb6\xeade\xbf\xbe\xb8?\xfb\xf7\xefT\x14\xe5\xb7\x9c\xd3\x9f\xff\xd3V\x16\xf5;\xe1C\xbc^\x9d\x87\xfc\x8f\x0f\xef\xdfy~\x12\xb7Z\xfc\x9dz\x02oUw=\xbf\x91722i\xafO\x10m\xcf\x1c\xef\x9e\xb2\x97\xe6y\xbc\x85\x85J\xf5\x9d\x8c\xe5w/\xe1;\xd7\xc39\x0d\xc3\x99\xaa\xe5w\xcfB\xfed\xfd\xdeU[\xe1\xf3\xffVU\xf8\xef\xc1\x13D\xfdf\xc7\xa7V\xf2b\xa5\xbf\xd3\xa6mM\xb5\x86\xba\x87/l\xb3y\xfe\xa9i\xbf4\xb2;\xb9\xabz\xa8`\xb1\xefy\xbb\x0d\xfd\xf8\x88\x1b\xd5\xb1~\xc2\xa3\xcc\xe7Y\xe5\xad\x9eF\xd5\x00\x0d\xd6lv\xcf\xaanq\xa7N\xb7{\xba\xbayy \xaeu\xec\x1f\xfb\xbac\xcb\x97\xb0\xaa6\x13I\xd59a`B\xe0\x06\x13\x90\x91\xb0&\x03\xe7Z\xe0\xc1\xe2%\xcf\xaa/\x03\xeaLc!\xe2p&\x02\xbdT\xef\xf5z%\xef\x95\x9cZ\xdd\xf4-\xf4\x8c\x9f(\x1ef\xc1\x142\x18\xc3r\xa7Y\xf5\x8d\x1b\xa8\x9b\xbe^\xb2\x83\x90\x1c\x1b\x0d\xdb\xd7\xe9\x832\x92&g\x9f\xd8\xbd/43\x86CC\x1b\x95\x1ejt\x8c\xef\xbbFI\xf3\xb6J}6\x10\x1er\xa6u=\x9b\x92\x9450t\\\x88\xda\x90$i\xdb\xc8\xa9\x98v\xb5\xea\x19\x87\xb6\x83iqa\xf2l\x95\x8e\x96g\xde\xcd\x11DU>d\x13\xd3\x95\x91\xa1l\xf6[\xd6\xd5\x0b\xf37\xf9VZT\xcd@RK~V\x07~\xdf\x0c\xf3\xbc\xb3\xcf\xbb\x0b\xe9m#\xba\xa8!\x84jft\xdf\x8bP\x7fb\x89\xf1\x9c\xba?qpg\x0c\x8c#\xbc\x9bz[c\xa3+\x8f5p\x91\x0f\x8dQ\x1a\x80\xdd\x82\xf9\xc0;O\xbc\xed\xd4\x8c\x9f\xfd\xa7\x8b\x15l\xd8\x8a\x1b\x94H\xb3E\xe6\x1bJ\xca\x17\x1a\x99mu\xe4\xc4\x07\x19\xab\x16w\xe2!\x7f\xc0(\xda\x80\xcfx~(\x96\xd6\x19\"\xa2\xb2\x85\xb6\xc0\xbb=\x93\x8cG\xdd,E\x97\xc5\x06!\xd3\x10\xe3\xe2@\xc7\xf2\x87\xbaYl\xf6\xcbY_X\x81\x06\xfaW\xce;&\xb9\x04K\xe0\x10C\x1c\x8b\x93\x9bu.\x1f/\xfa\xd9\xdd\x9aUAv\xb7\x1d\xeb5A\"\x1f\xaf\xf1y\x14\x8f\xdc\x99~\x9a\xeau\xd3v\xf3\xde\\?\x8d\xd3K\xa8\xc8\x1c{co\xdbv\xc3\xaa&t\x03;\xf6\x99u=\xf6M\xa6\x8f\x9e\xdf\xb8\xda\x02\xc4:\xe6~\x12&~\xc45\x98\xa2\xa5\xdan\xc9\xba\xf9\xfc\xf0\x87\xbaY\xb0\x97\xb0h\xc5\x90\xe9y\xbf\xfc\x04?\x9e\xfd\xe1\xa7\xa2\xd1\xe0\xd5z2\xd8\xfbW\xed-\x98\x0c\xe1\x85Zl\xd1\xbf\xf8eX \xf2O\xe5\xc4\x95 \xe1?\xbc \x12\xfex?\xac\xeb\x18\x12\x19\x80\xe8V7\x87t\x93\x86\x9bT\x82\x04\xe3O/\xfa\xa8Qy\x0d\xc6\xab\xe9\x83\x1fu\x82\x03\x1fc\x94\xc5\xa7\xfa\xd3\x14D\x15\xb2\xe3R\x14\xf8WU\x15LO\x10\x0c\x0cD\x83\x03\xd8\x95o\xd1X\x01\x14NJ\x10OI\x90R\xa6\xe0z\x8d\xc2\xc9\x08b\xa9\x08\x02\x89\x08\x92\xd2\x10D\xeb\x1fJA\x90\xbap=\xd5MB\xfa\x01\x9c\x8fP\xf2\x01\x9c\x87\xf0\xea\xb0\xf8ro\xe7\x89%\xd3\x0e`$\xed\xf4;\x17I9\x90\x9cp\x00\x19\xec2\xe9\x06p\x17+\x9el\x00w\xd9B\xa9\x06\xe2-\xafd\xa2\x01L\x9a\x81X\xa7\x99\x99b\xc0\xbf\xe2\x82\x87\x13\x0c\x14x\xcb\x85\x16\xecF;R\xc0\xad\xad\x008\"\xa9\x00>\xa5\xc0 \x8a{d2\x01\xc4*\xf2X\x93\x82\xe44\x02\xe1\x8c\x14\xa0?\x07BI\x04\xa2\xcd\nPM\x0b\xb0\x83(\xc0\xde<@\x06\x0c\x92\x13\x07\xc0mx\xc9,D{d\xdc\xed\x86SU\xb5`\xba\x80\xbcd\x01\xd8T\x01\x88D\x01\xa8\x00a\x82S2E@B\x82\x80Pz\x80Xr\x80B\xa9\x01\n$\x06\x88\xf6\x02\xf1\x1e \x9a\x12\xa0dB\x80hy\x01Uf\x88\x01\xa4\xcaPm\x14\x90\xed\x14\x8a&\x01\x88\xa7\x00@&\x008i\x1d\x8f_\xfa\x8f]\xf8\x1f[\xf6_h\xd1\x7f\xc1\xf6\x87X\xee\x9fzo\x8eY\xea\x8fX\xe8\x1f-\x0en\x95{\xac!\x15]\xe0\xef_\xde\x8fZ\xdc\xff\x8d\xaa\x9c\xb3\xa8_\x8a$\x1e\x7f\x9e%\xfd\xa1b\x14^\xce\xef[\xcc\x9f\xb2\x88v\x9c\xb8\x1dV\xd3\x1e\x96\xca\xcc\xb3\xcf\xfc\xe9Nt\xf6W\xf3y&\x17\xe4\xc8nE-\xab\xad\x9a\xc3yg\xa5\xf3U\xe3\\\xf3\xe0\x8b\x96\xd4\xce~\xa5%\xb5\xd8\xf9+ZRKKj}G\xd2\x92Zi\xb4\xa4\xf6\xd0hI--\xa9\xf5\x19-\xa9\xa5%\xb5\xd2hI--\xa9\xa5%\xb5\xb4\xa4V\x19-\xa9\xa5%\xb5\xb4\xa4\x96\x96\xd4\xd2\x92ZZR;5\xff\xa7--\xa9\xa5%\xb5\x1e\xa3%\xb5\xb4\xa4\x96\x96\xd4\x96YR;\xd01\x96\x97\xd0\xe7'\x9ep1\x9c\xbeZ\x14\x0b\xdcEPO\xe7^\xeb\xe6\xe5|\xf2}\\H\xc2\xbb}d\xb9T\xde2\x12\x85\x0f\xa9\xf3\xd2V\x8e\xbc\x97g\x0e\xabF\x0c\xf6\xa9\x1c\xca7\x8d=Q(\xaf6\xde\xd7q\xfeW\x07\xc8\x90\xa3V\xee\xdc\xc9\x02T1\xee\xd4x\xf0\xd1.2\xb1\x83o\x1b\x7f\x00\xdd\xed\xa8m4\x11\xd8a\xd4Gl\xa1E\xc4AR\x86|\xd9<\xde\xe8U.\xbe\xa5/f\x1dT\xac\xc6\xee\xaeQ\n\xd7\xf2\x06\x1f\xde^U\xd4Wj\xdd=\xeb\x87y\xb3\x83l\xd2\xad\xdd\x8c\x8dQ\n~J\xc1\x8f\x0e&\xa5\xe07F)\xf8\x9d\x96\x9b\x82?\x1cp\x17C\xa4\xde\xc9\x08~\xe8p\xda\x81[\xcb\x16f?\x1d\xf0CsxH\xf5\xa1\xe3\xf3E\xc8\xd0\xecWB\x86b\xady4B\x86\x08\x19r\x1b!C\xd2\x08\x19:4B\x86\x08\x19\xf2\x19!C\x84\x0cI#d\x88\x90!B\x86\x08\x19RF\xc8\x10!C\x84\x0c\x112D\xc8\x10!CS\xf3\x7f\xda\x122D\xc8\x90\xc7\x08\x19\"d\x88\x90\xa12\xc8P\xb1\x14\xf4J\x1e\xc7\x82\x82H\x16`\x8a\x16x\xca\xca\xe1Y\x80A\xb4\xe0\x08L\xcb\xebP\x1c\x18B\xb5\xa04\xae\x05Qd\x0br\xb1-\xaf7\xf5\xfd\x1b\x9e\n@\xe0[\x10F\xb8 \x0b\xe3\xf2\xba\n\xe2]\x90\x8bxy\xbd\xa9ad`\xd2\xad\x1c\xea\x05(\xdc\x0b2\x90/H\xc3\xbe \x07\xfd\x82d\xfc\x0b\xc2\xdd\x08D\x90\x1cH\xc0r\xb0(\x18\xe4\xe0`\x90\x8a\x84A\xb8\xe29h\x98\xd7\x99\x05^a\x1f\x19\x1c\"\x16| \xe4\xbe\x18\x01L\x0c\xca\xa2b\x10\xc3\xc5 \x8c\x8cy\xcf\xc9E\xc9\xa0`\xdbM@\xca +\x83\xc0\x08%\x96\x85\x03L\x9e\x18\xf760\xb2\xfd~\xe5\xac\x13\xdd\xa2\x92E\xb5b\xe6\xf5\xa7f\xfa\x16m\xd3H \xdf\x1f\xdba\xab\xa27R$\x86\xd0FW\xbb\xaemW^\x91.Z\xc7Kq\xfa\xb4\x86\xe3\x96\x81\xd2\xb7\xbb\xb2\xa1g#\x10\x84B\xaa\xe1n\x7f\xeb\xcfw\xa3\x0cq%@^\x0d\x90:%\xe0'\xc3 a\x0e\xc9XQ\xcd\x122uKH\xd1.\xa3\x9eFm\x13\xa3_Bi\x0d\x13rtL(\xa9eB\x92\x9e\x19ue\xa7VH\xd44\xa1\x8c\xae e\xb5M8B\xdf\x84\x0c\x8d3\xeaP\xbcRSuN(\xaauB\xb6\xde X\xcd3\xeae\xaa\x89buO(\xad}B\x11\xfd\x13\xf25P(\xa9\x83B\x92\x16\x1au5I\xe9\x80\xd3C\xe1t\x9a(\x9cX\x17\x85\xd3i\xa3\x90\xa1\x8fB\x8aF\x1a\xf5d\xa7\x80\x00\xbcN\n\xa9Zi\xd4\x9b\xec'R\xf4R\xc8\xd3L\xa1\xb4n\n\xc9\xda)\x94\xd2O\x01\xa3\xa1B\xda\xd0\x11\xa9\xa5B\xc6(3IS\x8dz\xe3&\xc5\x04RW\x85\xc4\x12'\xea\xabA_\xd3\xd1,Rc\x85T\x9d5\xe8 \xa1\xc1Bi\x1d\x16\x12\xb5X\xc8\xd4cc\x0e\xb1\x9a,\x14\xd5e!M>\x04\xac>\x0b\xe9\x1a-`D\x89#\xb4Z@\xfa\x8fLX\x16\xd4m!;\xf8i\xfa- k\x9e\xa9\xe3\xc21Z.\xe0#^D\xd3\x854]\x17\x12\xb4]H\xd2w\x01\x7fS\xf2t^H\xd6z!\xa6\xf7BI\xcd\x17rt_8B\xfb\x85t\xfd\x17\x907)\xa6\x03\x03\xd6O\x9a\x1e\x0c\x855a\xc0\x163\xf2\xc4\xa6\xeb\xc3Aw\xb7\xf78\x8d\x182u\xe2\xa0C\x9d\xea#\xaa\x15C\xa6^\x1ct\xc8\xcd\xdc^P3\x86\x0c\xdd8\xe8lL\x05\x82\x98VA\xea\xc7\x10\xd7\x90\xa1\xac\x8e\x0c\x18-\x19\x12\xf5\xe4\xc8\xfd\xb7\xd2\x89\x045e\xc8\xd0\x95\x83\xce>^\xbd=Cj\xcb\x90\xa9/C\xba\xc6\x0c\xb9:3di\xcd\x10\xef\x9a\x00\xa1\xdbA\x82v\x97\xa2;C\xae\xf6\x0c9\xfa3\xc4\x83QT\x87\x06\xac\x16\x0d\xa5\xf5hH\xd0\xa4!K\x97\x8ev\xd2Qm\x1a2\xf5i8R\xa3\x86\xc2\xed=Q\xab\x86d\xbd\x1a\"\xa3\xa9\xb8\xa6+\xecr\x7f\xfb?\xd9\xfd|\xb7\xa4\xdd\xfevS/dV\x06ke\xb0\x91\x9bc\xedK\x8a\xe1\xe2\x9e\xa9v\xc3#\x03\\1\xe6Q#\x80AQ\xf6\x1e\xdf\xd7\xeb\xa6\xe2\xfb\x0e\xb1\xd0\x80$\xdd\x80\x91\xa4K\x92\xee\xc4H\xd2\x8d:$I\x17H\xd2\x9d\x18I\xba$\xe9:\x8d$]e$\xe9\x92\xa4K\x92.I\xba\x11\x87$\xe9\"\xf5\x04\x92tI\xd2%I\x97$]\x92t\xa5\x91\xa4;1\x92tI\xd2\xb5\x8c$]\xb7\x91\xa4\x1b1\xac\xc4E\x92\xaem$\xe9\x86\x0e$I\xf7\x9bI\xba\x1f\x8cF:Wu\xef\xd8\xd7\xe7\xacY\xb4\xa2\xb9\x0fBjl*G\x9cx\xb9\xa9\xea\xe6\x9a}\xe5\xea\xf5\xe3=~'\x8e\xbb\xe1\xec+\x8f\xcb\xb3\xd1\xc9.\\e\xc7\xa2\x05*\xab^\x9a\xa2\xcar\x1e;\xe8P&\x00\x97\x93(z\x06?\xaa\xf1\x0c\xf1v\x1e%WA\xdf,\xdafU\xaf\xf3\x97_\xcbD\xd9\xaf\xa5\x93\xe9\xcbQ9\xd6Mr\xbe\x04\xdb\xeb.\xb44\x1b\xa1\x9ec\x94s\x99\xda\xfd\xb8V\x80\x9d\x0d\xf4\x06\xc7^\x83\xaf\x96\xde\xcb\xc1\x89\xec\xfb\xbc\xde\xe4\xb8\xb3n>\x89\x97\xc0\xb6Zz\xe6+\x17\x1d\x93!\xbf\xe1\xb5\xbf\x9e\x88:\x9a\xe9\xdce\xc5\xd9s\xe1+\xbf\x89\xe8\x12]\xd7\xdb\x83'_8\x16\xdd\xba\x062L\x0d\xef\x02yjo\x19kT-\x9do\x9fpy\x86\xbc\xee\x8e\xfb1\x14M\xbc\xb3X-\xa7\xf8\xab\x06\xea\x86\xb3\xee9xR\x07/\xba\xb6\xef\x9f\xebv\xeb<\xc2\x91\x9f|\xdcW\xc0\x91\xb8]\x95\xffr\xdcg\xc1\xce\x85nm\xbf`r\xca\x1fz\x08='\xe1'\xc4l\x1f\xe3n7\xd1V\x13\x95\x00B[\xdc\x8c6lb\xa3w\x12\x19\xf6\xb3\x81]\xd5\xf7JvT\xbb\xde\xfcc\xcfz~\xa6~\xf78\x93\xbb\x1fH7\xa1\x0do.\xb85\xb2\x91{\x8b\xf8^>\xa2Y0)\x826-l\xdb\xcel\xbc\xe1T[\xe4\xde\x17G\x06s\xb6\xb9\x88m\xb1go\xd8z\xc3\xb7\x17\x8b%\xe2\xf9\xeak\x07\xda\xde\xc5\xc4s\xf8\x97Jny\xf1\x0cj\xde\x1b\x19\xba\x87}\xa3\x1a\xf1R)g_jG\xb3\x8dw\xaa\xf6NG\xaaV\x93\xfd\xd0\xea\x06\xd6W\x97\xaf\x87\x07\xc3\x0c\xe3z\xf8\"\xee\x99\xeb\xf6\xb8\xdf\xa0\x8b\xb6S>\xe4\xe8\xb5S\x95\x1f\xc6\xe1b\xc0-E8;2\xcep\x983>\xb4\xdb\xb1\xdc\xc1q_\xc7v\xb2_\x83?V\xddp\x93b_f\x93\xb0\xc8\xf6\xed\xfb&\x9b\x0e\xe1\xc2\x0f\xa3\xdc\xe7c\xdc\x06c\x12w\xb5\xdb\x8c\xfa\x7f\xf9Y\xb2j]Y\xd3\xa4\x8b\x17\xd6&\x1f\xe2\xee\xa8\xe9\x98\xf1a\xd1\x93H\xf6C2\xddG\xa3\x81}\xa3\x90\x19\xb6T\xc8\xc2)\xb7\xd3\x90\x17p\xf4\xca\xfe\xa7U\x8c\xe4|'\x88w\xc7\xda1\x9dd\x9e\xed\xba\xe1?\xfd~\xf6\xabn5IeX2^\xd5\x9bG\xb2\x0d\x08\x8f`\x89\xd1\x9e\x0f\xd3\x17(K\xc5\x0f\x8d\xfe\xe9u\xc8\x91\xd8!\x1a7\xc4\xec~\x11\xc1\x0cS\xf1B\x89\x0fz\xbda\xb1B\xd7,i2N\x88\xc7\x08'\x98\xa0\xd7\x1f\x1e\x1f<\x12\x1bL\xc3\x0552\xe4/v\n&\x98\x8a\x07\x06w\xb5H\xc1\x02\x93p@\x0b\xf7\xf3;\xc4a\x80(\xfc\x0f\xbb\x8b\x05\x02\xfb+\x86\xfb\x1d\x87\xf9e\xe0}E\xb0><\xce7\xc5\xf5\x02\xfd\x93\xe3\xddo\xdb \xf0\xbdSa{'\xc0\xf5R0=4\x9e7\xc1\xef\x82}x\x1c\xcbK\xc2\xf1 \xb8\x1b\x05\x16\xc3sLg\x86z\xe3T\xec\xce`u\xfe\x97`\x14\xb7;\x1a\xb3\x0b\xe2u\x88!P\xf4[\x1a?JJ\xc2\xe7d\x14%\x1e\xe7\xef\xb0\xa3\xd8\x1c\xa6d\x89\x98\\hg <\x1e\x97\x84\xc5\xc5\xd0\xb7\x1c\xe4McmN\x7fQ\xd4-\x07q\x83\xc0\xc6!1\xb4\xad\x0c\xd2\x86\xa4\xa9\xa2\x08[\x02\xba\x16\xe2%rP\xb5\x90?\x8f\x9cW\x08IK\x0b\x1e\x1eA\xc3D(\x019\xcbB\xcd\"\x91;\x1a-C\"e\x18\x94\x0c\x87\x90E\x82\x9a\x8e\x8c\xe1Q1/\"V\x04\x0dKB\xc2rP\xb0\x04\x04,\xc8B\x05\x8a\x15<\x0f\x8fx\x95B\xbb\"\xd5p\xfe\x96\x8ep\xf9vm\x88\xa2[9\xc8\x96\xc1\xb2\x9c\x0eC\xa8V\x0e\xa2\xe5\xbdP\x18\xcdJE\xb2,\xec\xca\xe9\xcf\xffi\x8b@\xb0\x02\xe8U:r\x15\xc6\xaaRp\xaa)2\xe5t\xe7\xc3\xa8R\xf1)\xf0\xee\xb4\x10\xc7\xa6Rq\xa9\x04L*\x19\x8fJ\xc3\xa2\x02\x04P\xa8TX\x1c\x04\x8b?%cOI\xb8\x93\xa7\x929x\x93\x86\x80\x02\xcf\x90\xeb\x97\x1c\x9cI#K\xee\xb6\x1d\xc2\x98\xd2\xf1%o\x07\x16\xc4\x96\x02\xb8R6\x92T\xa2\xcd% Hx\xf4\xc8\xbc\x86wUWm\x19g\xddd'z r\xc8M\xc7-\x07\xa1/\xcf\xa7f\xce\xf2\x07\xb5\xc9\xf8\x8cE\xd0{\x15\x98<\x11\xba\x8b\x14\xfe\xc5\xdd:d3zVu\x8b\xd9$\xc7@0\xac\xa6Sp9\xfb\xf0\xcf\xa6\x07L\x85\x15\xb73[z\x8f\xac\xb6\xd4\xe2\xc4\x03<\xed\x89\xedy}\x85\xa3\x98\n\x9bJ\xda\xfe\x0e&\x91\x87\n\x8b\xb0.\xd5[\xbc^\xa9\xc8\xd5=T\x9b\xbe\x85\x9e\xf1\x13\xc5\x83W\xdd\x9a\xf1\xf4X\\\xcb\xf3\xa6\"\x0d\xb7\xb7\x89\xb0\xf6\x98W\xb1\x98\x17x\xbc\xdd\xd3x\x1c\x86B\x05U\x86\xf9\xf4\x01\x19\x19\x91\xb3O\xec\xde\x17\x98\x99\xe0\xabq\x8bJ\x0f*:\xc6\xf7\x9d\x82\xd2&\xfa\xf2\xd9\xc0f\xc89\xd5\xf5l\xf2Q\xd6@\xbc\x08c\xbc\xc5{\x11\x98\xb6\x91\xad\xae]\xadz\xc6\xa1\xed`Z\\;uD\xf9hyf\xd8\x1cAT\xe5C60]\x19\x19\xcaf\xbfe]\xbd0\x7f\x93\xef\x9fE\xd5\x88\xfa\xa8\xe9\xc5;\xd6\x98\xc0\xef\x9baFw\xf6!w!\xbdmDK\x1cB\xa8\xe6@\xf7\xbd\x08\xf5'\x96\x18\xcf\xa9\xfb\x13\x07wF\xaf8\xc2\xbb\xa9\xb756\xba\xf2X\x83 \xf8\xa0\x165\xdbo\xb7`\x0d,\xec73\n@\xcd\xed\xd9\x7f\xbaX\xc1\x86\xad\xb8\x81\x804\x15d\xbe\x96\xa4P\xa1\x1e\x10u\x11\x11\xe7\xdb{`\xd5\xe2\x0e\xaa\xdd\xee\x01\xa3h\xa39\xe3\xf9\xa1XZg\x88\x88\xca\x16\xda\x02\xef\xf6Ln\xf4S7\xcbzQq6H\x96:\x82\xf2@\xdd\x90lwu\xb3\xd8\xec\x97\xb37C\xa5\xae2h\xc6\xb3;& \x04K\xca\x10\x83\x19\x8bp\x9bu.\x1f/\xfa\xd9\xdd\x9aUA\xf6\xb6\x1d\xeb5+\"\x1f\xaf\xf1y\x14\x8f\xdc\x99~\x9a\xeau\xd3v3!\xc8<\x8d\xd3K\xa8\xc8\x1c{co\xdbv\xc3\xac\x1c*\x8e\x1b\xd8\xb1\xcf\xac\xeb\xb1\xeft}\xf4\xfc\xc6\xd5\x16\xda\xd51\xf7\x930\xf1#\xae\xc1\x14\xe7$\xf9\xe2\xf9L\xf0\x87\xbaY\x881G+\x86F\xcf\xfb\xe5'\xf8\xf1\xec\x0f?\x15\x8d\x06\xaf\xd6\x93a\xdd\xbfjo/\x96r<\xf6B\x7f\xd0\xf4/>\xff\xf4B\xbeG\x9f\x8b7n\xffB\xe5\xe4Rg\xae\xd9\x00\x10\xf5\xfb\xed\xb6\xea\xee'\x11\x1b\x10\xa4\xf7\xf2\x1cY\xe0\x9a\xf5\x06[\xd2\xe9\xbdD\x8bT/jy\x81g.\x89[\x0d\x87\xc4C:\xfcI8\xa9FY\xc8z\xd5\x8b\xef\x97\xf9hB\x9f\xd6\xee\x98\x1a)_,_\xce\x8b\xa7\x0f1\x90\x93\x15\x9c\xef\x7f\xff\xe3\x8f\xdf\xfbI)\xe8\xf7\x8b\x05\xeb\xfb\xd5~sJD\xca\x0e\xbcm\xfc\x01X#1\xc6\xcc\x16\xd9\xc6\x91t\xb6\x0b5\xf8\xcc<\x1d\x89*\xcbV\xf1F\x11^3lY\xff\xb1]\x89\x16X7\xeb\x0d\x0b\x10\xf4r\x98.o\xde\xe1\xadS%\xd1\xfb\xc5\xb1~\xfa1 \x1f\x07}\xdbg\xa7\x12\xc9L$3:\x98D2\x1b#\x92\xd9iEH\xe6\x83\x80OIf\xf5\x8e\x1d\xae\xe2Z\x06\xa2\x87K\xb7\xf7\x8e):\x1d\xc3y\x94$A%?|[1\x18\xb1:N\xddo\x12\xf0L\xc03\x01\xcf\xda\x08x&\xe0y4\x02\x9e9\x01\xcfn#\xe0\xd9\x18\x01\xcf\x04<\x13\xf0\x8c\x1c%\x11\xf0<\x18\x01\xcf\xb6\x11\xf0L\xc0\xb3\xc3\x08xv\x1dC\xc03\x01\xcf\x04<\x13\xf0<5\xff\xa7-\x01\xcf\x04<{\x8c\x80g\x02\x9e x.\x03<\xa7\xf3\xbf\xef\xa7\xfc\xafV\x0dZ\x0d\xb3\xd8*\x15\xb4\xab35Y\xc8\xc7\x8f\xdei\xd5\xaa\xcdlfE\xd1\x01=o;9\x81\xa0\x9a\x97r-'\xbbz\xce\xaa\xe5\xb1\x00U\x11\xf6w\x8c\xc3\xb9\x83\xf1\xd5\xd1\x90\xf0\xae\x145d]\xe4\x1b\xda\x00\x9b3i\xf9`ry\x8a\xf9\x8e\xb3\x06\x95z\xcaO\x14\x04\xe2}1\xd1\"\xdeW\xd9\x89\x83\x1b'U\x89\xf7-\x11E\xe2}\x89\xf7\xfd\xf5\xf3\xbe\xfaA|n(\xda\xe7\x95!\x14\xfd\xdc\xaf\xf5\xa2{\xa3N7o\xfb\x11o4\x00\xb0\xfa$T\x0f\xfb\xe0\xda\xdeYx6j]\xd7\x9fY\xa3\x166\x89\xb1\xfa\xd3Q\x13\xfe\xc1z\xf9\xeb\xc3'\x8c\xaf\xaf(\xfa\xd8G\x0b\xfb\xca\xd1\xdd\xe3\xc0l\x8eb}\x07\xc4P\xae\xfc\xb3A\xd4%\xeb\xb9\xe9\x81t\xdb\xb3\x87\x85\x8e\xf4\xbd\xca\xf41\xe1\x12\x1d\x9d\xad\x9a#\xf6xFT\x1e\x90\x1a\x95\xb1T\xce(\xe8\xcc-6\x05f_K\xf3F\x10g\x8e \x83;\nW u\x0f\xe7\"\xfc\x11d2HA\x87\xc9\xfb6\x1f\xc9\"A2\x8f\x14t\x95\xbbWsQ. \x12\xd9$H\xe5\x93\xc2-{xOa\x19%(\xcd)\x01\x8eU\x82\x92\xbc\x12\x1c\xcd,A\x1e\xb7\x04\xa5\xd8%\xc8\xe2\x97\xc2\x8f\x03~\xef\xe5\x13pLpB\x96 N\xc33A\"\xd3\x04y\\S\xac\x0b\xc6\xb1MP\x96o\x82\x04\xc6 \xd29'\xc8`\x9d\x10]&v?\xe5\xa3\x99'\x88qO\x80\x1f\x9e!\xf8'H\x1c\xc5%sPAo){&cKY\x90\x89\x82$.\nJ\xb3Q\x90\xc9G\x85\xdb\x15r\xff\xe3LN\xca\xeb\x8f#\xf7=.\xc3K\x01\x1e\xfb\x01\x0c7\x05i\xec\x14\xc4\xe0\x84L\x86\n\x10~\x03\xc2h!\x9e\n\xb2\x82\x8b\xe7\xaa\x00Q\xcb\x0c\xbe\nr\x19+\xc0E\xf5h\xd6\n\xf0\xbc\x15 \x99+@sW\x80\x0bz:\x7f\x05I\x0c\x16\xc4\xf6&.\xc2bA*\x8f\x05\x99L\x16\xa4qY\x80\xb8 \xb1=\x88\xa3\xe7\xe39-(\xc8j\x01\xa6h\x81\xa7\xac\x1c\xb7\x05\x18v\x0b\x8e\xe0\xb7\xbc\x0e9b\x7f\xe1\xa2\x1c\x17DY.\xc8\xe5\xb9\xbc\xde0\xfb #\xb8.\x88\xef#\x9c\xcewy]E\xf7\x0f\xceb\xbf\xbc\xde\xa2\xfb\x06\x97c\xc0\x00\xc5\x81A\x06\x0b\x06i<\x18\xe40a\x90\xcc\x85A|;\xdcX)\xb1\xbc\x0e\x96\x11\x83\x1cN\x0cRY1\x08W<\x87\x19\xf3:C\xed\xff\x9b\xc3\x8e\x05\x1f\x08\xcc\xbe\xbf\x05\x192\x88qd\x10f\xc9\xbc\xe7\xe42fP\xb0\xed&\xb0f\x90\xc4\x9bA`\x84\x12K\xc9\x01&]\x8c\x7fk\xd3!\xf9\x91\xd2F\xa7)\x90\x0eM\xcd\xf4-\xda\xa6\x91\x82\xbe?\xb6\xb2G\xe6c\xcaN\xfdx;\x8f\xdfum\xbb\xf2\x8at\xd1:^\x8a\xd3\xa75T\xa8\xdc]\xbdS\xbe\xdd\x95\x0d=\x1b\x81 \x14R\x0dw\xfb[\x7f\xf2\x1be\x88+\x01\xf2j\x80\xd4)\x01?\x19\x06 sH\xc6\x8aj\x96\x90\xa9[B\x8av\x19\xf54j\x9b\x18\xfd\x12Jk\x98\x90\xa3cBI-\x13\x92\xf4\xcc\xa8+;\xe7B\xa2\xa6 etM(\xabm\xc2\x11\xfa&dh\x9cQ\x87\xe2\x95\x9a\xaasBQ\xad\x13\xb2\xf5N\xc0j\x9eQ/SM\x14\xab{Bi\xed\x13\x8a\xe8\x9f\x90\xaf\x81BI\x1d\x14\x92\xb4\xd0\xa8\xabI\xae\x07\x9c\x1e\n\xa7\xd3D\xe1\xc4\xba(\x9cN\x1b\x85\x0c}\x14R4\xd2\xa8';7\x04\xe0uRH\xd5J\xa3\xded?\x91\xa2\x97B\x9ef\n\xa5uSH\xd6N\xa1\x94~\n\x18\x0d\x15\xd2\x86\x8eH-\x152F\x99I\x9aj\xd4\x1b7\xb9'\x90\xba*$\x968Q_\x0d\xfa\x9a\x8ef\x91\x1a+\xa4\xea\xacAO\x08\x0d\x16J\xeb\xb0\x90\xa8\xc5B\xa6\x1e\x1bs\x88\xd5d\xa1\xa8.\x0bi\xf2!`\xf5YH\xd7h\x01#J\x1c\xa1\xd5\x02\xd2\x7fd\xc2\xb2\xa0n\x0b\xd9\xc1O\xd3o\x01Y\xf3L\x1d\x17\x8e\xd1r\x01\x1f\xf1\"\x9a.\xa4\xe9\xba\x90\xa0\xedB\x92\xbe\x0b\xf8\x9b\x92\xa7\xf3B\xb2\xd6\x0b1\xbd\x17Jj\xbe\x90\xa3\xfb\xc2\x11\xda/\xa4\xeb\xbf\x80\xbcI1\x1d\x18\xb0~\xd2\xf4`(\xac \x03\xb6\x98\x91'6]\x1f\x0e\xba\xbb\xbd\xc7i\xc4\x90\xa9\x13\x07\x1d\xea\x1c Q\xad\x182\xf5\xe2\xa0Cn\xe6\xf6\x82\x9a1d\xe8\xc6Agc\x8e\x10\xc4\xb4\nR?\x86\xb8\x86\x0ceud\xc0h\xc9\x90\xa8'G\xee\xbf\x95g$\xa8)C\x86\xae\x1ct\xf6\xf1\xea\xed\x19R[\x86L}\x19\xd25f\xc8\xd5\x99!Kk\x86x\xd7\x04\x08\xdd\x0e\x12\xb4\xbb\x14\xdd\x19r\xb5g\xc8\xd1\x9f!\x1e\x8c\xa2:4`\xb5h(\xadGC\x82&\x0dY\xbat\xb4\x93\x8ej\xd3\x90\xa9O\xc3\x91\x1a5\x14n\xef\x89Z5$\xeb\xd5\x10\x19M\xc55]a\x97\xfb\xdb\xff\xc9\xee\xe7[@\xee\xf6\xb7\x9bz!s4X\x8b\x80\x8d\xdc\x1ck_R\x0c\x17\xf7L\xb5\x1b\x1e\x19\xe0\x8a1\x8f\x1a\x01\x0c\x8a\xb2\xf7\xf8\xbe^7\x15\xdfw\x88\x85\x06$\xe9\x06\x8c$]\x92t'F\x92n\xd4!I\xba@\x92\xee\xc4H\xd2%I\xd7i$\xe9*#I\x97$]\x92tI\xd2\x8d8$I\x17\xa9'\x90\xa4K\x92.I\xba$\xe9\x92\xa4+\x8d$\xdd\x89\x91\xa4K\x92\xaee$\xe9\xba\x8d$\xdd\x88a%.\x92tm#I7t I\xba\xdfL\xd2\xfd`4\xd2\xb9\xaa{\xc7\xbe>g\xcd\xa2\x15\xcd}\x10RcS9\xe2\xc4\xcbMU7\xd7\xec+W\xaf\x1f\xef\xf1;q\xdc\x0dg_y\\\x9e\x8dNv\xe1*;\x16-PY\xf5\xd2\x14U\x96\xf3\xd8A\x872\x1d\xb8\x9cD\xd13\xf8Q\x8dg\x88\xb7\xf3(\xb5M\xc9\xa2mV\xf5:\x7f\xf9\xb5\xdc\xb0\xe4\xb5t2}9*\xc7\xbaI\xce\x97`{\xdd\x85\x96f#\xd4s\x8cr.\x13\xbd\x1f\xd7\n\xb0\xb3\x81\xde\xe0\xd8k\xf0\xd5\xd2{98\x91}\x9f\xd7\x9b\x1cw\xd6\xcd'\xf1\x12\xd8VK\xcf|\xe5\xa2c2\xe47\xbc\xf6\xd7\x13QG3\x9d\xbb\xac8{.|\xe57\x11]\xa2\xebz{\xf0\xe4\x0b\xc7\xa2[\xd7@\x86\xa9\xe1] O\xed-c\x8d\xaa\xa5\xf3\xed\x13.\x8f\xbc#o\xc5%\x0e\xef\xc7P4\xf1\xceb\xb5\x9c\xe2\xaf\x1a\xa8\x1b\xce\xba\xe7\xe0I\x1d\xbc\xe8\xda\xbe\x7f\xae\xdb\xad\xf3\x08g~\xf2P)\xdf\xd6\xbd\x14\x81\x0f\xf2\xde?S\xfbZ\xb4\x8d\x15F\xf5\xf9\xe6\x1eq[\x84\x8c\xb7|\x8e\xd2\x8d{ \xf8\xd2\xca{\x9e\xc1\xf0\xd3g6\xaaq\xb7\xc9h\x8b\x8c\xca\x0b\xa1\xcdtF\x1b\xb6\xcb\xd1{\x96\x0c;\xe7\xc0\xae\xea{%i\xaa\xfdu\xfe\xb1g=?S\xbf{\x9c\xc9}\x16\xa4\x9b\xd0\xd6:\x17\xdc\x1a5\xc9]L|/6\xd1\xe4\x98\x14X\x9b\x16\xb6mg\xb6\xf8p*9r\x97\x8d#\x839\xdb\xc6\xc4\xb6\xd8s=l\xf2\xe1\xdb\xf5\xc5\x12\x08}\xf5\xb5\x03m\xef\x97\xe29\xfcK%7\xd7x\x065\xef\x8d\xc4\xdd\xc3\xbeQ\x9b\x05,\x95*\xf7\xa5\xee\x0f\xdbG\xbc\xc3\xb6\xf7TR\xb5\x9al\xc2V7\xb0\xbe\xba|=l\xe4`\x86\x88=|\x11\xf7\xccu{\xdco\xe7E\xdb)\x1frd\xdc\xa9\xca\x0fc|1\x98\x97\x02\x9f\x1d\x19g8\xcc\x19\x1f\xda\xedX\xee\xe0\x98\xb2c;\xd9g\xc2\x1f\xabn\xb8I\xb1\xaf\xbeIXd\xfb\xf6}\xefM\x87\x87\xba\xf5\x1c<\x86r/\x11\xdfV\x1b\x93\xf8\xab\xfdm\xd4\xff\xcbO\x9f\xc3\xe4\xed\xd2\xd9\x0b\xef\x1e\"\xe2~\xa9\xc9\x9f\xe1<\xdd\xa5\xdaO\xcdt\xd3\x8e\x06\xf6\x8d\xe2s\xd8R\xf1\x11\xa7\xdc\xbbC^\xc0\xd7\xc9:\x1f_1l\xf4\x9d ^Tk\xc7\xdc\x95y\xd8\xeb\x86\xff\xf4\xfb\xd9\xaf\xba\x19%\x95a\xc9xUo\x1e\xc9\x9e#<\xc2@F\xbbBL\xe7\xa0,\x95u4b\xab\xd7!G2\x8eh\xb6\x11\xb3\xd5F\x84iLe\x19%\xab\xe8\xf5\x86e\x18]S\xb2\xc9\xec\"\x9eY\x9c0\x89^\x7fxV\xf1HF1\x8dM\xd4|\x92\xbf\xd8)Lb*\x8b\x18\xdcB#\x85ALb\x0f-\xb6\xd0\xef\x10\xc7\x1c\xa2XC\xec\x96\x19\x08\xc6\xb0\x18[x\x1cS\x98\xc1\x12\x16a\x08\xf1\xec\xe0\x94\x0d\x0c\xf4O\x9e\x8f\x1dc'`\x05O\xc5\x08\x9e\x80\x0dLa\x02\xd1,\xe0\x84\xf5\x0b\xf6\xe1q\x060\x89\xfd\x83\xe0\xd6\x17X\xe6\xcf1w\x1a\xea\x8dS\x19?\xc3\xf0\xf9_\x82Q\xb6\xefh\xa6/\xc8\xf2!\x86@\xd1\x8fk\xfc()\x89\xd5\x93Q\x94,\x9e\xbf\xc3\x8e2z\x98\x92%2y\xa1m,\xf0,^\x12\x83\x17\xe3\xecr\xf8:\xcd\xd09\xfdE\xb9\xba\x1c\x9e\x0e\x02\xbb\x94\xc48\xba2\xfc\x1c\x12\xdd\x8a\xf2r \x9c\\\x08\xce\xc8\xe1\xe2B\xfe<\xdaa!\xfe--xx\xde\x0d\x13\xa1\x04\xbe-\x8bk\x8bD\xeeh\x8e\x0d\xc9\xafa\xb85\x1c\xaf\x16 j:\x9f\x86\xe7\xd2\xbc\x8f\xe2\x91;\xd3OS\xbdn\xdan&)\x98\xa7qz \x15\x99co\xecm\xdbn\x98\x95\xfa\xc3q\x03;\xf6\x99u\xbd\xf7\x0d3\xbby\xfa\xe8\xf9\x8d\xab-j\xa8c\xee'a\xe2G\\\x83)\x84Fb\xb1\xf39\xc5\x0fu\xb3\x10o\xc0\xb6\xdf\xb6\xfd\xf3~\xf9 ~<\xfb\xc3OE\xa3\xc1\xab\xf5d\x80\xf0\xaf\xda\xdb\x8b\xa5\xdc\xf2\xe8\x85\x1e\x1a\xf7/>\xff\xf4b\xc9\xab\xf5s\xdeUM\xbfb\xdds\x0d\xfd\xe8\xb3\xd7l\xc0Q\xfa\xfdv[u\xf7\x93\xa8]4\x8bv[7\xeb7\xd7\xd5\xfaZ{\xd0`P/kP\xb3^I\xbew\x0c\xc4A`\xae\xd3\x1b\xbah\x9c\xff\x15\xcf\xc4\x18(\xa9\x90I\x9ar[-E\xd4\xbfT\x9d\x1eH\xee{\xd6\x8d\x9b8\xad\xeb\xcfl\xbe9T\xbbcj\xf4u\xb1|\x19,\xa4>\xdeP4V\xcc\xbe\xff\xfd\x8f?~\xefGq\xa0\xdf/\x16\xac\xefW\xfb\xcd)\x19\x9c\xe9\xdd\xb0\x8d?\x00\xce\"Z\xca\x0dooxW\xb9@\x1fe\x08A'F\xef\x81l+\xd7\xed\xb5\xb8\xce\xf4KY\xbd(t\xd7\xa7Z\x94\xe8J\x1d}\xa7m\xb7lhx\x1d[\xc2\xaak\x03\xbc\x84\xea\x96\x17\xac\xfe<\xaa@\x06\x85\xd3\x90C\xcf\x9a\xa5G\x80Q?\x9d48\x1f\xe4%\xe6\xb0\xb2\x19\x03\x1b\xddj\xa1\xde\x12*<\xac\xf137V\xfd\x9c\xc7\x98X\x9c\xb4NW&\xe0\xb3Zyo\xc4]\xc5\x9f\xf9\xd9M\x18\xd8\x96gj\xb1\xa8\xf78\xd1}Lo\xab\xf8g\xdd\xc9\xc6\xe5z\x84\x82Uq\xf41c\x8d\xa0\x9a\xf6\x81\xc1\xa8\xdf2\xfeE\xf4~\xfc\x8bD_\xbaC\x9d,T\x92\xa1\x13\x1e/\xce%\xbe\xae\xe0mg\x97|\xd8#\x8ff\xf7\xc1\xaeX\x9any\xf6\x13\xc1\xda\x04k\xc7\x1e\x19\x82\xb5 \xd6\x9e\xda\xa1\xe4\xa4[\xd0\xe5\xf8\x19\xa3n\x94N\xbb:\xfe\xd9\x04u\xe2!|\xcb\xe4\xd084FL\x05\xbf\x1d\xb7K\xb1\xe0\xc1\xd1\xf2\xc8\x83\x8fO(\x01\xe1\xb3_ \x08\x8f\xb5\xe6\xd1\x08\x08' \xdcm\x04\x84K# \xfc\xd0\x08\x08' \xdcg\x04\x84\x13\x10.\x8d\x80p\x02\xc2 \x08' \\\x19\x01\xe1\x04\x84\x13\x10N@8\x01\xe1\x04\x84O\xcd\xffiK@8\x01\xe1\x1e# \x9c\x80p\x02\xc2\xcb\x00\xe1\x06\x9e\xb0\x9c\x84\xbe>\x9f\xb6\x03p\xed\xc31f\x90\x89$\xb1x\xebH\x0d8\xe8\xd9\xd3\xd0\xd6Z\x02\x1bX\x03B\xb6\xd1\x88\xf1\xa9\xa9bB\xb6O\x18\xdc8lL\xc8v\x89(\x12\xb2M\xc8\xf6\xaf\x1f\xd9\x96/\xfd\x00\xa2})\x7f\x1f\x08l \xc9\xe8\xd3a\xdb.\xf7\x1b\xa6\xc6\x0dN^\xfaR\x1fyi\x1f\xf1h i;\x14\xb6y]A\x14\xd3h\xea\xc5\xa7\xc6\x9b\x879\xe8\x18\xa2\xceAJ,\xcd\xcd\x865k~\xe7\x9f\xe0B\xc8 (!d[}\xfdF\xd7\x8aa~\xeftXu\xe3\x9c\x12\\f\x10\x0b\x1d\xdb\xc8)\xfa\xe0V\xb7Cc6\xb7\xca%\x1a,y\xe5I\x1d^\xe0\x16vl}\xc3\xbe\x1e\x15\xd2_u+xs]\xad\xd17Z\xdfNy\x92\xebN\xde\xd6\xed\xc9n\xe47\x8f\x8c\xf7\xf9\xf8c\xdd\xa6F\xcc\xe3\xe9\xb6n\xd7]\xb5\xbbs\xcdo\xb6]\xb5\xd8\x9c\xaekSo\x80\x9bzY(\x9a\x01\xac\x18\x101\x05\xa9\x90\x8b\"]\xbc\x99\x7f\xcb^\xbc1\xe31\x15\x13]v5Z\x08\xf8[T\x9b\x8d\xba\x0b\x9fYW\xaf\x1c_\xb9S[V\xdcG\xbaT\xfd\xa7\x1b9x{<\xd1z\xd5\x7fz-\xc7\xaa\xb3h\x8d\xa3U\x15\xad~\xf8\xee\x17\xb5\x088\x9c\xc4)\x14\x8c\xad\xdc\xf0\xe1Q\x05\xe3/u\xe3\x0c\xc6\xb6n\xea\xed~;\x8e\xea\x87\x98\xdc\x05X\xc6\xe1C~\xd1nw\x1b\xc6\xa3\x9bd\xc8\xb8i\x1a\xc9\x1aNy\xb1\xb2]\xc7vU\xc7n\xd6U`\x87\x89o\x1d\xc3KU\xa8?U\xfd\xc1d\xd2\xd6\x84o]\x99\xcf\xd5}\x88\xa6\x02X\xee;3\xad\xa2*+c\x13\x8aa\xcf\xab5s>\xe8\x9e\x93\xd8W\xb6\xd8\xf3G\x16\xc4sU\xa8\xe2AT\x95U\xaaG(\x8a\xd8\xe0\xad\x18\xbbQ%\x8a\xc5\xce\xcd]\x1b\xf3\xf2\xd7\xc6\xa2\xaf*e\xf1\x17\x96\xb2%k\xdam\xf8\x10\xe4M\x17\x16\x8b\x802\xa4;\x0c/d\xecu[\x8fK#*\xe0\xed'\xa67o\xa9T\x15\xcd\x94B\xd5,\xa1\n\xef\xe8\xa3*\x11\xdbW\xf8\xdd\xfb\xeb\xf3\x97R\x91\xd3\x0dQI[\xb5\x84\x96.\x1a\xae_\x11\x03(\x16\xde\xd4\xd8R\x05tn\xfc\xe0\xe1\xc3nL\xfd\xf0\xad\x0d\xb7\xf7\xb0n\xd7\xad\x9cv\xf7\xab\xc8\x98g\xeeg\xc6^m]\xbd\xff\xf8\xc8\xad\x18\x1b\x08\xca\xea>\xb6K\xd2\xb0G\x92\xeebb\xdd\x7f\xfc\x81\xf3md`\xec\xbd\xf4\x80\x1eU\x8eO\xb9\xc7\x9f\x9c\x033\xba\xd0\xbe\x9f\x8f\x82T\x06\x9a\xfe\xae\xdeI-\x16\x16\xac\xe1]p\x13\xefj\xc4m\x87\x15\xab\xb7\xf7P\xc1\x1b9\xe9\x11\x18\xe7V\xbb\xdd\xcd\xa6n>\x05\x16Z\x1c9\x94\x95@`\xcd\xefo\x96Z\xb9\x89ui\x91G\x19\xd3\xe6\xf4v\x11\xc3\xb5\xc1\\\x1bn%\xca+Q@+f\xce\xed{Fc_wu\xe7!\xeab\xc5y\xb5\xdb\xbd\x15\xf1\x9d\xb4\x9eH\xe3\xa9v;\x8f7y\xab\x0e~\x1b\xd6u\xc9KL\x14p\xeb\"+\xcd\xaf\xce\xa6\xb0&\xde\x10k\xbc\xd4U\xa2\xab\xb9\xe4_\xd5\x82-]\xae\xab\xcb\xd73\x7f\xb4P\x8b\x16jE\x9fx\xec\x8b\x9b\x16j\xd1B-\xb7\xd1B-i\xb4P\xeb\xd0h\xa1\x16-\xd4\xf2\x19-\xd4\xa2\x85Z\xd2h\xa1\x16-\xd4\xa2\x85Z\xb4PK\x19-\xd4\xa2\x85Z\xb4P\x8b\x16j\xd1B-Z\xa855\xff\xa7--\xd4\xa2\x85Z\x1e\xa3\x85Z\xb4P\x8b\x16j\xe1\x17j%\xf1\xdd\xe6\xdf\xbf\xec{\xd6\xfdS\x9d\x16\xc9\xc5\xad\xb1m\x17\xf4\xad\xd4\xd8\xe1\xa3_\xae\xdaRi\xb3\xc7T\xb7`M\xc0\xeaU^\xd6`L7x\xe5{\xa9<,[\xa6\xe6V\xe4\x94Xe.\xf6L\xf7\xe3\x1a\xb6\x1f\xf4\xb5i\x1a\xdeAQ\x80f\xbf\xd9\x98sM/\xea\xe2\xd1\xf5O\x8f\x17DW\xc5\xf4\xc9WY$zX\x85\x8aN\xc0`f0\x8a\xebO8\xf5)G{\nkLY\n\x93\xbc\x84\xc7aT_*\xa0.ejK\xde\x19y\x9c\xb2t\x94\xae\x94\xa5*A\xb5\xd9\xf8\xa2\x88\xd3\x94r\x14\xa5\xd0\x87VH\xa99N\xab\xc9Pk\x8a\xe85\xc5\x15\x9b\xa8fs\x02\xd5\xe6T\xba\xcd \x94\x9b\x14\xed&W\xbd \xf6\xe11\xfd\xa6\xa0\x82\x83\xd5p\x12U\x9c\xe2:N\\\xc99Z\xcb\xa1\xf5>\xd1\x92\xe5i;NW\xb4\xde'G\xe5\x89\xe9\xb4\xdb\xb1\xdc\xc1i\x9d\x8e\xed\x98\x9c~\xffc\xd5\x0d7)\xf2\xf18\x0d\x8bl\xdf\xbe\xcf\xc7\x00\xbbu\xf00\xca\xf1\xa6\x1a\xa5\xa5\xa0[zhI\x99\x9a\x89\xdcr\xfd\x1e\xec\xf1N z\x86\xbe\xfd\xaca\x91\xaf\x11\x0e\x03\x91\xc9\xf7\xde\xf8\xadd7\xc4\x9c\x8d\x07\x0f\xaa\x13\xd9_S\x7f\x03\xf8\x8a;\x8c!\x9dc\xdf\xee\x1b\xd5bZXolg]|\xb8\xecK\xc7g\xb7\xfcEv?O\x0f\xf6Y\x91s\xc1\xf5l'\x15;\x14\x16\xb7\xf3\xc3\x89\xeaO\xdb\x1ec\xa2\xe5\x195\xd2\xb6\xc7e\x83\x1b\xdf\xb0\x97\xb6=.\x11E\xda\xf6\x98\xb6=\xfeun{|0\xe1<\xf9\x83\x7f\xde\xd9\x8a\xd8\x95}\xc6d\xd2x\xe2\x0b\xf4\xdc\x8a\x9e\xfe\xb12f\x0d\x9e\xcc\xc0L\xffa2\xb5<\xb9\x8a>\xe0\xd1\xce0;\x82h\xdbC\x8c\xe3\x17\x1d\xab\xb8\xebcH\x19b \xae\xe7%^+G\xf3\xc92\xed\xdftFv\x04\xdc\xe5\x11\xbd\x0b\xebvU\xc7=\x13S)\x85\nLM\xbe\xb6.t0=+\xe7\xb2\xe5 \xb4n>\xb7\x9b\xcf\xee\xe7\xd8\xb6h\xc5\xfe\x93\xcc\xcb\xd6\xcb\x83yY\xf1\x82\x90\x93\xaf^w\xf3;\x0bu\xef\x9f\x98\x95`\xa9\xe3\xd7\xf8\x94\xd0\xb4O1#\x92\x9ew\xfb\x85|\xdbU\x93Bx \xa7\x0bK\xd8U-\xb4m\x16l'\x1d|\xa7\x96\x04|'C\xd0U\x03\x9f\xd0\xb7\x12\x8bv\xb9k\x18\xff\xd2v\x9f\x0e&\x04i\xce\x96\xe6l\xe3O\"\xcd\xd9\xd2\x9c\xadm\xc9s\xb6\x93\xe1\x0fj\xea\xd6\xe5\xe5\xc5t\xacFko\xb5\xd1\x0c\xee\xafa\x06w\xfa\xb9Q~\n4:c\x10\xe2\x8e|3\xa1r\xf09\x8c\xbc\x02\x15*\\\x19Sf{\x1c\xee+;rR\xd7v\xe5\xfa\x0e\xe8\xd5\x94\xae\x9cI\x988\xacW\x87/\x005(\xa7\xf9\\\x9a\xcf\xa5\xf9\\\x9a\xcf-\x1cE\x9a\xcf\xa5\xf9\xdc_\xe7|\xae\x19\x19\xc9}\x0e\x86\xff\xf1\xcf\xe3\x9a \xa2\xfe\x90\xf6\x1d~\xd1\x13\xb6j\xcfx\xed`27;8yb\xaa\xf4H\xe7eg\x01\xb1\xed!F\xe6\xdfl\x86\xf0\xa3L}\x03\xf5R\xf5O\xb3\x048\xb3i\xf7\xa9\xc9G/\xbf\x94\xba\x00\x7f\xdeo\xab\xe6y\xc7\xaa\xa5\xec\xba\xec\xa41\xc1\xab\xdb\xad\xe4\xe8B\xbc7\xe3V\xcb\xab*\x85\xe8\x18B\xc5\xe0\x1d\xab\xfa}w\xda\x89\xea\xab\xe9\x04\xad\xb9&T\x0b\xf5ZP\xb7N&!i\x17\xb5\x9c\x9c\xf0\xae\xc5\x02\x80xp\xdb/M \xf2\xfc\x95\xe3\x83F\x96\xb5\xfd\xd2 \x1aX1abV\x8e\xe1\x1bQ_\xc0\x7f\xf1\xbamnx}T37\x0f\xe3\xb2\xe2\xec\xb9\xf0\x15.\xea \x98\xc8e?5\xf2a\x18\x17\xd2\xdd\xac\x18\xbb\xe1\xed'\xd6xz\x96p\x7f\xa6\xcc\xdb\xab)\x8b\xf4m\xcab=\x9c\xb2%k\xdam\xe8\x00T\x8c\x85U[\xf1(\x14p\x15\x9f\xe34\xf6\xba\xad\x1b\x95iH\xbc\x1cAF]\xe7\x93P\x153\x03\xb0\xaaYB\xe5\x07\xfaM\xe1CIM\x00\xde\xbd\xbf>\x7f)Wz\xaa\xa3\xf5\x92\xc9Z&\xc3\xb8h\xb8\x9e&\x18\x12\x90\xf4\x8e\xa9>\xdb\xf4Z35\xcb\x17\xbap_\xaf\x9b\x8a\xef;\xd6\x0f#\x121X_\xb7\xebV.\xe5\xf2\xadL\x8e\xf7ko\xeb^\x8eiW\x8c\xe9\xe8\xc9\xb0\xf5*\x88\xe6ka[7\xf5v\xbf\x85u%\xbe\xf9\xeb\x85'\x1f\x06\xa8\xd4Y25\x91\x1e\x97\x84\x13X\xf9\x1f(]\xf2\x0fC?1\xa4\x1d\xd1#\xa0e\xc5+%7\xa9\xa1\x8f\xcf\x19I@$\x01\xc5\x1f\x04\x92\x80H\x02\xb2m*\x01\xf9Z\x8f\xfc\xbe\x1b\xbe\xaf\xf2\x85\x9f\xf1;\xef\xea\xf2\xf5<@\xfa\xed`\xfe\x97$\xa0\x83\xf8\xfc\xd6% L\x8f\xa0\x8c\xd2\xafR\xfaU\xb7Q\xfaUi\x94~\xf5\xd0(\xfd*\xa5_\xf5\x19\xa5_\xa5\xf4\xab\xd2(\xfd\xaa\xbfMS\xfaUe\x94~\x95\xd2\xafF\x93\x88R\xfa\xd5\xdc\xc8Q\xfaUJ\xbf\xea0J\xbfJ\xe9W)\xfd*\xa5_\xa5\xf4\xab\x94~\x95\xd2\xaf\xfe\xe6\xd3\xaf\x12R\x9f\xc6+\x13R\x7f\xc2\xe0\xc6apB\xeaKD\x91\x90zB\xea\x7fKH\xfd\x8b_\xacu\x8a\xffT\xe7G\x12\xa5\x0c\xa4\xd9\x1c\xb5\xaf\x1b\xf5\x9cI\x8a\xf0\xb6\xdd\xab\xe6>\x00\xacr\xf6\x94\x9b\xb4\xb2\x83\xbbay\xa4\x93\xc5\xd7\xbf=z\x14\xbf(2\xe7\x03\xea\xa3\x93\xfbx\xbe+\x1b\xa5\xf7\x83\xf4\xd1\xd2\x1d\x05\xd1G\x11z\xec\xe5s\xf1\xf90<\x8f\xbd\xbaWL)\x8b\xcdG\x82\x19@\xe6\xb1\x159\n\x97\x0f\xc2\xf2\x99%@\x80\xf2\x08L>zq\x1c\"\x7f\x04 \x9f\x80\xc7\xf3\x08\x1c\x1fD\xe3\x83\xfd\x93\xb2\x18\x8f\x05\x18(>\x1aQ@\x01\xf1\x087\x18m\x10\xd2Qx\x04\xf0^\x16wG\xc2\xeey\xa8{\xac\x1f*\x8c\xb9\xe3!w\xef#Q\x08pG\xa1\xa9(2u\xc6\xa2\xce\xfc\x11\x85J\x14j\xa9\x9e\x8a(T\xa2P\xddF\x14\xaa4\xa2P\x0f\x8d(T\xa2P}F\x14*Q\xa8\xd2\x88B%\n\x95(T\xa2P\x95\x11\x85J\x14*Q\xa8D\xa1\x12\x85J\x14\xea\xd4\xfc\x9f\xb6D\xa1\x12\x85\xea1\xa2P\x89B%\n\xb5\x0c\x85\x8aH#~q\xb8\x07\x8a\xc9\xbfm\x9dr\xe4\x96\xff\xe0\xc3KJpG/\xe4\x0c]\xd5\x88\x1f\xd6]\xbb\x0fm\xd9\xf4'\xf1\xfb\xab\xe1x\x8de\x8dj\xe0\xba\xab\x1a.\xf3\xa6\x83re\xfa\xdf _4\xf3\xf2\xc4\x04\xe4\x91bF\xaaR\x8fC\xff\xb2n\\\x81\xf9\x1fL\xde\xcf\xc0\xdc\x8f\xa3\xedk\xa9y\xb6\xff\xfa\x97\xaaWQd\xfe1\x1c\x18\xc1Z\xb4 \xe7\x11\xcaC\xf9,\x8f#>c\x95\x11U\x96\xc8\x1c\xdc\xd1|\x07\x8f\xa8\x9d\x80\xab6 g\xcd\x8c\xa5*\x9fAg\xee\xe9\xaf\xc0\xf7`i\x05\x14\xe2*(d(\xa1\xe1\nT\xfc\x0e\xad\x86B)E\x142U\xd1\xa0C\x11\\\xb42\n\xc7\xab\xa3\x90\xac\x90\x06]i\xe5&I%\x85\xd2J)$\xaa\xa5\x90\xaa\x98\x86[\xf6\xa0\xa6bUS(\xad\x9c\x02N=\x85\x92\n*\x1c\xad\xa2B\x9e\x92\n\xa5\xd4T\xc8RT\xc3\x8fC\xa5vO\x89>7'QV\xe1\x84\xea*\x9cFa\x85D\x95\x15\xf2\x94\xd6X\x17\x8cS[\xa1\xac\xe2\n \xaa+\xa4+\xaf\x90\xa1\xbe\"\xba\xcc\x1f\x10\n,\x94Pa!\xa6\xc4\x02~x\x86Pd!q\x14\x97\xac\xcc\x06\xbdI\xd5\x16\xa1\xceBB)\x0b\xaa\xb4\x90\xa4\xd4Bi\xb5\x162\x15\xdbp\xbb\xea\xe3\xaa-\xe4+\xb7^\x7f\xe2\x8a1\xf5\x16\x8a)\xb8\x80\x17\"\x01\xa3\xe4B\x9a\x9a\x0b1\xb9$S\xd5\x05\x84\xdf\xc0Tm!\x85\x17\xb2\x82\x8bWz\x01Q\xcb\x0c\xc5\x17rU_\xc0E\xf5h\xf5\x17\xf0\n0 U`@+\xc1\x80\x0bz\xba\"\x0cI\xaa0\x84\x94a(\xa5\x0eC\xaaB\x0c\x99*1\xa4)\xc5\x80\xb8 !\xc5\x180\xe7\xe3\x95c(\xa8\x1e\x03\xa6h\x81\xa7\xac\x9c\x92\x0c\x185\x19\x8eP\x94\xbd\x0e\xe5\xbc`@U\x86\xd2\xca2D\xd5e\xc8U\x98\xbd\xde\xd4\xf7ox*\x00\xa14CXm\x86,\xc5\xd9\xeb*\xa8DC\xae\x1a\xed\xf5\xa6\x86\x91\x81I\xb7r\xaa4\xa0\x94i\xc8P\xa7!M\xa1\x86\x1c\x95\x1a\x92\x95j\x08w#\x10Q\x0f!AA\xc4\xaa\xd6\x90\xa3\\C\xaaz\x0d\xe1\x8a\xe7\xa8\xd8^g\x96F\x8c}dpjv\xf0\x81h\xd6aE\x1b\xca\xaa\xda\x10S\xb6!\xacn{\xcf\xc9U\xbd\xa1`\xdbMP\xbf!I\x01\x87\xc0\x08E+e\xd7U\xb7V\xa99FEo\x10\xc6d\xcb\xbbe\xac1\xba\x99\xd3\xd7p8ie\xd1I\x16\xd2\xcaH+#\xad\x8c\xb42\xd2\xcaH+\x03\xd2\xcaH+\x9b\x18ie\xcaH+#\xad\xcc6\xd2\xca(\xe1\xf41\x88G\n\xde\x91\x81vP\xc2iJ8M \xa7\xb1hFQ,#\x07\xc9\xa0\x84\xd3\xbe\xc3\xa2\xe8E\x02v\x81I\xa7\x9c\x82[P\xc2iJ8\x8d@'(\xe14d\xe2\x11 h\x04%\x9c.\x80>D\xb1\x87\\\xe4\xc1\xfb\xae\xa1\x84\xd3\x87F \xa7\xfd\xb8B\x1cUH\xc5\x14\x12\x10\x85d^\xe3\xf3(\x1e\xb93\xfd4\xd5\xeb\xa6\xedf:\x85y\x1a\xa7\x97P\x919\xf6\xc6\xde\xb6\xed\x86Y\xcb\xbc\x1d7\xb0c\x9fY795t\xf3\xf4\xd1\xf3\x1bW[\x14S\xc7\xdcO\xc2\xc4\x8f\xb8\x06SHO\xdb-Y7\x9f\xa8\xfcP7\x0b\xf6\x12\x16m\xbfm\xfb\xe7\xfd\xf2\x13\xfcx\xf6\x87\x9f\x8aF\xa3\xf4~\x11\xe25\x1d\xd8.\xe2c\xcf:\xdcn\x11\xd2\x91\xb9\xf3\x93\xcd\"\xa6>\x9e\x98Z\xd3^\x11Qt\x85\xf6\x8a\xa0\xbd\"\x0e\x8fA,\xb0\xc6\x08^\xc6R\xa1\xa5\xa03\xb7r\x15\x98\xca-\x0d/A\x1c`\x82\x0c\x88)\\\x01\xca\x7f\x93\x0b6A2\xdc\x14tE\xf9o(\xffM.\x00\x05y\x10\x14\x94\x02\xa1 \x0b\x86\n?\x0e\x94\xff&\x0d\x8e\x82D@\n\xf2 \xa9X\x17\xccQ\xa0\x14\x94\x85\xa5 \x01\x98\x82th\n2\xc0)D\x97I\xf9o\x94%CUAo\x94\xff\x86\xf2\xdf\xcc\xac\x0c|\x05x\x86\x080\x10\x16\xa4\x81X\x10#\x1d2\x81,@\xf8Edj9\x12\xce\x82\xac\xe0\xe2!-@\xd42\x03\xd6\x82\\`\x0bpQ=\x1a\xdc\x02<\xbc\x05H\x80\x0b\xd0\x10\x17\xe0\x82\x9e\x0esA\x12\xd0\x05\x94\xff&\x9e$&\xf8s\xf4|<\xf4\x05\x05\xc1/\xc0\x14\x8d\xf2\xdf\x94\x85\xc2 \n\x86A.\x1c\xe6\xf5F\xf9o(\xff\x8d\xcf\x92\x013H\x86\xcc\x80\xf2\xdf8-\x07@\xf3:\xa3\xfc7\xc6(\xff\x8d\xc3h\xaf\x08\x87a\xe7/\x80\xb42\xd2\xcal#\xad\x8c\xb42\xd2\xcaH+#\xad\x8c\xb42\xd2\xca\xe6FZ\x99\xc3\xb0\xa5$\xad,\xdc\xaeH+;4\xd2\xcaH+\xcb\x9e~#\xad\x8c\xb4\xb2\x90\x91Vf,Z4\xd2\xcaH+\xb3\x8c\xb42\xd2\xcaH+#\xad\x8c\xb4\xb2\xc1J\xb5\xdd\x87\xd4\xcah\xaf\x88\xc1=\xed\x15a\x19\xed\x15A{E\xd0^\x11\xcaN\xbbW\xc4\xc1=\x93K\xe1\xa7\x8b\xcd\xf3\xb7\x8a\x98-Z\x9f\x1dC\x1bG(\xa3\x8d#h\xe3\x88\xd1h\xe3\x08\xda8b\xb4\xa2\x9cH\n#\x92\xc4\x87\xd0\xc6\x11\xc7\xb2 \x19\x1cH\x11\x06$\x9d\xff\xa0\x8d#\x8e\xe1=RX\x8f\x0c\xce\x836\x8e\xa0\x8d#h\xe3\x08,\xa7Q\x94\xd1\xc8\xe13h\xe3\x08\xdfaQ\x0e#\x81\xc1\xc0l\x8b\x90\xc2^\xd0\xc6\x11\xb4q\x04\x82\xa3\xa0\x8d# \x93\x95H\xe0$h\xe3\x88\x02\x1cD\x94\x81\xc8\xe5\x1f\xbc\xef\x1a\xda8\xe2\xd0h\xe3\x08?\xbb\x10\xe7\x16R\x99\x85\x04^!\x99UH\xe3\x14h\xe3\x884\x16\x816\x8e\x18\x8c6\x8e\xd0\xf6\xeb\xd98B\xe6\xc8\xf5\x95\xfd\xe9\xfb\xe0F\x11\x07[D\x88\xcfh#\xbf\x9d\xcd*\x92\x9aA{V\x15\xda\xf9!%Z\xb4\xf3\x83\xb2\x13\x077\xbeg\x01\xed\xfcP\"\x8a\xb4\xf3\x03\xed\xfc\xf0\x1b\xde\xf9A\xc2}\x81\xfd\x1e\xac\xf0}\xecY\xf7'y\xb8,x\xcd\xecm\x1f\xe4\x9fe\x8b\x17\xf1\xd3CQ\xb3\x1f\x80=B\x19\xdcM\x85\x14\xe9\xa5\xfe\xcc\x1a\x18\x86;\x07{F\xa8\x8b\xeb_\x1f\xf1~\x11cDm\xe3\x0f@\xac|\xfb\xfd\".\xde\x1c\x0cIg\x9bB\xd4\xbd\xde\x05\x8c}\xad{\xcf\x1a\xfc\x9eI\x0d Zl\x1f\x86\xa4\xcc\xbd\xcf\xd7\xd4b\x08\xe3dG3k\xbc\xad\n\xe8\xad[\xed\x97\x12\xa5T\xe5\xfc\xf5\x9b\xd5\xf6\xa3\x84\x88\xa0^\xaa'v\x86\x12\xb9x_e\xb2\xef\xcdoG\xfa\xea\x7f\xdeo\xab\xe6y\xc7\xaa\xa5|w\xd9\xec\xcd\xb8G\x9c\xd3\x85\xfd<\x1f]\x0c\xf3\xfda{U\xe50w\xd1y\xfe\x8eu\xdb\xba\xef\xeb\xb6\xf1f#\n=\xe9\xca\xbc\xcf\xbb2|%\x02\xed\xf6r,\xa8\xfe\x9a\xd2S\x02\xc36'\xed\xd0\x7f\xcb\xbdz\xc4\xd7\xa8\x9f\xe5\x8aE\xc64-\xd3O\xcf\xc1r\xf1\xa7v\xa5\xae4;\x9d`r\x82\xc9\xe3-\x9a`r\x82\xc9m\x9bJYQ\x06\\\x0d\x1e\x8f\xe3\xbf\xf5\xe8\xf7\xea\xf2\xf5\x9b\xb7\x99\x01\xbb'<\xb8\x96\x1c\x06\x873@\xdcM\x7f\xeb\x1f\x1f7\xfc]\x94b\x8c\"\xdcQ\xd9\x05\xcf\xde\x95\x80\xb7c\xe8\xb6o\\6Z\x1cd\x8e\xa1\x82e\x91m\x1f\xb0\xfd\x0dj\x98\x07j\xfb1\xedh[9\x12\xd1\x8e\x02\xda\xd8\x02d\xc1\xd9Q4\x9bG\xc0\xec \x96\x8d-\xba\xb7U\xe6\x01\xd9~\xb0+\x10\x8bl\x18\x1b\x87Q\x16\xa0( \xa2$\x88\xd2\xf9;A\x94\x96\x11DI\x10\xe5h\x04Qr\x82(\xddF\x10\xa51\x82( \xa2$\x88\x129J\"\x88r0\x82(m#\x88\x92 J\x87\x11D\xe9:\x86 J\x82( \xa2$\x88rj\xfeO[\x82( \xa2\xf4\x18A\x94\x04Q\x12D\xf9\xa0\x10\xa5$\xcd\xec\xdeh.\xb1\x9d\x1e\xa24$F\xbc\xd8J\xca3\xf0\xe4Q\x85\xc4\xa1\x92\xa7!N^l\xc5c\xd6\x05\xf2\x10\x0e\xc2\xe1_\xd4\x91\x07)\x08\xb5\x07\xf9\x1a\xd4\xc0\xc9\x81T\xedfJ\xb4\xc7'&J\x8f\x14-\x99\x84\xc86\x9e\xaf\xe49\xe7\x99(\x1d\x17\xa5\xe3\x8a\xd3\x0c\x94\x8e\x8b\xd2q\xd9\xe6L\xc7u\xf0\x18N9\x12\xdd\xf3\x16\xc0I\xcc[\x81\xf6aVF\x18 a$\xa3\x11FB\x18\xc9h\x84\x91p\xc2H\xdcF\x18\x891\xc2H\x08#!\x8c\x049J\"\x8cd0\xc2Hl#\x8c\x840\x12\x87\x11F\xe2:\x860\x12\xc2H\x08#!\x8cdj\xfeO[\xc2H\x08#\xf1\x18a$\x84\x91\x10FB\x18 \x16#\xb1\xd2vL\x12q\x19\xa8\xe2\xd8,b8\xb6\x84\xd2p\xe5\xe68\xa24\\'\x0cn<\x81\x14\xa5\xe1*\x11EJ\xc3Ei\xb8~\xc3i\xb8\xac\xec5/~\x11/\xe4@\x1e\xae\x8f=\xeb\xect2v\n.\xcb\x8fag,\x1eR{: !-oOL\x08\x1e)\x08\x19L\xf3\xc3\xf3y\x94\xc7\x0f\xbeDs\x81% ?\xa8\xed\x9c\x0fG\xb6\xa2MY\xc9\xb3\xc6\xbb!\x9ed\xff\xe6\xc6\xb1\xbc`1\xa2IY1Qx\xa4\x14\xd44:\xb6\xf1\x07P\x1a\x1f\x05\x994\xdb\xd9o|\x0c\xbc\x9b\x15\xfa7\xf1\x8b\xe9\xc6\xca0\xb8\x84\x0f\x950\x85\x13#;=\x16\x9e\xb5\xcb\xa9\xed\xaa\x8e5<\x1a\xe0b\x05vn\xa2\xa8\na\xca\xeet\xd0xw\x1fD\xb5\x01}\xf5w\x96\xc0\x99\x1a)\xfby<\xba V\x18\xde\x8c~gEs=P\xeat\xb3\xc5\xf9\x14\x0b\x19p\x90\xben\xd6\x1b\xab \xbb\xfdQFF\xca\xc8H\x19\x19)##\x1c\x9f\x91\xd1\xbd\xb3\xa7\x19\xf4\xc431*\x92l\x18x]]\xbe\x9e\xf9#\xa8\x8c\xa0\xb2\xd8\xab5\xfe\xf0+#\xa8\x8c\xa02\xb7\x11T&\x8d\xa0\xb2C#\xa8\x8c\xa02\x9f\x11TFP\x994\x82\xca\x08*#\xa8\x8c\xa02e\x04\x95\x11TFP\x19Ae\x04\x95\x11T65\xff\xa7-Ae\x04\x95y\x8c\xa02\x82\xca\x08*{4P\xd9\x00\x01\x15\x06\xb3\xa2D\x19e1LK\x11GY\x0cO\x18\xdcx\x1b\xa5,\x86%\xa2HY\x0c)\x8b\xe1o \x8b\xa1\x1b\xd5}\xf1\xcbH)\x07\xd2\x17\x1a(n\xbe\x87s\xdd\xa8\xe7L\xfcV\xdd\xb6{n\xbf\xbf\xd5\xc4/\x1f\xb2\x19\x0e\x03\x02\x17\xbe\xfb\xc4\x04\xe0q\xd3\xbbEq\xbe(\x83\x1b\x95%\xf0\x10Z\x11\xfa6\\\xce\x10\xc8\x1a\xc7X\xcbP\xb7\x11\xe6\xb6`A\xf3h[?k\x1b\xbd\xd7Gs\xb6Q\xca\x16[\x84<\xc2\xb6\x1c_\x8b!\xe3\x12\xc18\xe2\xe2\x88\x8bs\xfdN\\\x9ce\xc4\xc5\x11\x177\x1aqq\x9c\xb88\xb7\x11\x17g\x8c\xb88\xe2\xe2\x88\x8bC\x8e\x92\x88\x8b\x1b\x8c\xb88\xdb\x88\x8b#.\xcea\xc4\xc5\xb9\x8e!.\x8e\xb88\xe2\xe2\x88\x8b\x9b\x9a\xff\xd3\x96\xb88\xe2\xe2m\x1a\xb5\xd6\xf1\xc6\xd0\xac\xa6\xf3\x899{\xb0\xcc\xc2B{\x87\xa5D\xcb3\x1bD{\x87\x95\x0dn|\xd7+\xda;\xacD\x14i\xef0\xda;\xec\xd7\xb9w\x18\x8a\x18\x0f\xa0\xe1\x1f\xf4\xb123\x96\x93\xfd\xeeMr\xb3J#\xdb\xb3\xad\x8b\xa6\xbb\x84\xd9\xee\x9e\x98\n?R>\xdb\n\x8dm\xfc\x01\x08\x96o\x0fg\x07\xd4\x9bh~;\xc3\xbd\x8aO\xa5[\xc6\xfcr\xe0\xa2\x93d\x9a\xbb\xcaC\xae\xbap\x8dC\xa9\xc80\xc9\xc8\\8\xba\xdeL*\\\xab`\xe9c\xa5.v\x9f\x0e6Z\x13et\x9e\xc2\xber\xd65\xd5&\x1aQ\x0c\x0dn\x8d\xfa\xcf\xb5_Q\x06\x85\xe3\xd5\xbd\xbf\x14\x9c}\xe5E/\x7f\xad\x11\x94p\xdd\x1b^\xfb\x9f.g\xad\xf4\x19\xb0h\x9bF\xbd\x12\xe5\x17r\xa8n\xd1\xc7\x1c\x10\x8f\xba\xb0\xbb\xaa\xbf\x9b\xf6\xec\x87\x16\xea\x86F\xf3vH\xa3!\xca\xac\x0cSre=\xaf:\xef]\x1e\x0dq\xbfGC=\x14\xa3\xc5\xbb\xb1\xd1.\x9a%\xfbj\xda\xd0\x00\xb5\x99\xc7_\x8e\xbdD#\x0b\x00s\xa3\x8d\x9d\x05\xaf\xd6*\x10~:A\x19k\xbc\x0f\xe4h\xbf\xfeX\xb1f\x19\x8b\x14\xaf\xd6\x85#\x95R\xf5\xebj\x0d\x1d[\xb1\x8e5\x0b\x06O\xe54\x86\x9e\xdaxf\x1eY\xf5\x81\x13\x9al2\xc6\xf8\"$\x9f\x0dE\x13\xfd\x9b\xba\xb2\xb5\xb4\xe2g\xb4\x9c\xda\xdb\x1bg\xabk\xe9y\xed\xb1\xae\x98\xee\xf3c\xb7\x99m\x9f\xad\x16MI\xa4Bq\x93\xf5\"\xe2L\xbbz[7\x9f2\xfa\xcd\xd07f\xbc\xbf\x8c\xf4\x95\x88\xc8\x9a\xf7\x88\x1a\x8fn\xaa\xf9W\xf63\xd1PV{\xb9\xb4\x06\x16\x15g\xeb\xb6\xab\xff]\xce&:=V{~\xe7Z,\xa7\x0c_\xa0W\xd2OtVa\xd16\x9fY\xd7W\xa8y\xaab3>\xce\x1d\xeb\xdb\xae^\xd7M\xb5\xd1\x0b\xceuwc\x95\xcf\xe9s\x182,o<\x93\x9d\xca\n\xb5\x85\xc8;\x13\xf7\xbe\x94\xae0\x8f\xd7\xb5F\xa8\x87J\x86O\x8a\xdf$e\xac\xd9oc\xdd\xcas\xb8|\xff\xe1\xfa\xe6\xea\xfc\xe7\xf3\xab\xf3w\xaf\xcfo\xae\xffvy~\xf3\xf1\xdd\x87\xcb\xf3\xd7\x17?_\x9c\xbf\xc9:\xff\xea\xfc\xf2\xed\xdf\xb2\xce\xfc\xd7\x8f\xef\xaf\xcf\xb3\xce\xbc:\x17\x7f\x0d\x9ej\xd6\xcb\x1eUg\x0c\x9f?Z4\xbe/\xe1]\x8b\xbc\xf1\xd6\xea\x81X\xff\x1f\xb8-/\xd5:\xcbq\x0c>\xcbf\xb1\xdb\xdc\x9bt\x13\xe3b\x85\xc0Db\xe4\x9a\xf2\x86\x86\xaf\xf9\x8f}\xcb\xc7%\x04\x05\xae\xa9\x9aB\xb4\xa2V\xff\x83\xbej$\x85\x8b2\xf4\x13\x8a\xeaL\x95\x1dL\xfd\x8f=\"\xa2\xcc\x12\x9cz\xb0BG\x9f\x92K]\xc2\x83\xba\xcd\x07\x08\xdf\xf7r\x88\x10\xc0\x7f\xa5\xa9\x95\xc4\x03U\")\x8c\xb6\xd9\x04V\x8e*\x1bR:\x89`\x18\xc5\x15\xd1/\x99\xac%m\xcf\xaf\x86\xa2\xfb\x07L\xb2\xe5\xc5\x9e\xf9x\xec^\xa9\x1c.\xc3\x18\xc4j\xeb=\xfa\x85#\xf1q\xb6\xac9[~\xe3rZ_9o\xab\x9e\x83*\x04\x88\x13\xa3\xa5\x96\xf9\xb6\x8e(\xaa.\x82L\x19\x13\xb9\x98\xf5\x8e\xb2V\x8ej<\xa6nT\xa5E\xb8\xab\xdbv\xcf\xa1\x82\xben\xd6\x1b\xa7\xbb`\x02\xaf\xd0\xf7\x13\xa5\xdf\xa2\xf4[\x94~K\xdbo;\xfd\x96\xaf\xf5H,p\x02\xdf\xa1\xb68tyy1e\xf8f\x87\x8c \xb5\x86\x1f(\x9f\xd6\xecW\xca\xa7\x85\xe9\x19\x94Q>-\xca\xa7\xe56\xca\xa7%\x8d\xf2i\x1d\x1a\xe5\xd3\xa2|Z>\xa3|Z\x94OK\x1a\xe5\xd3\xa2|Z\x94O\x8b\xf2i)\xa3|Z\x94O\x8b\xf2iQ>-\xca\xa7E\xf9\xb4\xa6\xe6\xff\xb4\xa5|Z\x94O\xcbc\x94O\x8b\xf2iQ>\xad\x87\xcc\xa7\xc5[K&V\x1c\xd7t\x1a\xf5\xf4\x89\xb4(\x95TZ\x9e\x1eJ%u\xc2\xe0\xc6\xdb(\xa5\x92*\x11EJ%E\xa9\xa4~\xcb\xa9\xa4^\xfc\xa2a\xfe\x7f*_\xae\xa4R\x92\x963\xb9\xa4D[\x9b`q)\xf9\xa4.G\x8c\xeeQ\xa7\x91*J\xf4E\x93AE\xc5\x07<\x87\x96\x9c\xeb)\x90\x15)\x96\xd1\x89\x07\x89\x1a@es:,\xf6\xb1\xb9\x9c\xbeA\x90\xb19\x9c\xa2\x19\x9c\xa2e:\x84kS\xb27\xf9s7e\\\x18\x91\xb7)\x9c\xb5\xc9Q\x97\x8c\x9cM\xc1\xe7\x10\xa2\xcf\"\xa0\xb25\xf1\x00\xa4e,\x9ay ZRe\xf1\xf2*C\xe5\x1c\x88\xde\xd7\xd1\x10\xcd}\xb4\x18\xe5:\x1az\xfd\xbc#\x9d\xb0\xcb8>\xfd \"\xcf\xc0\xaf7>\xd1\xec\x02\x88\x84' \xd1\x19W\x82c\xf3\x98\xc4\xb2\x94\x14\xcdQ\xa2\x9d\x1d\x97<)\x9e:\x89\xfa\x89\x99=\xfcs@\xfd\x84\xdb\xa8\x9f\x088;&\x93Q8\x8f\x11\xf5\x103{\xd8'\x00\x99\xb3\xe87\xdbC\xa0\xf2\x14!\xf2\xf4$D\x07_\xe1r\xf9\x89\xf0\xd9\x89\x12r\x13\xa5\xd7\xf9\xb8\xbcD\xe6c\xf4\xe8\xacD\xdaQVN\"\xffwT\xac\xe7\x0b\xf6z\xd1X\x8e\xef\x95\x12\x99\x88By\x88\xb0EA\xe5 Be \x8a^\x11\xd1\xa1\x1c\xb6\xb0\xe3r\x0f\xe12\x0f\x15\xb8\xe7G\xe7b\x96n\xe2\x8fMJ\xb6\xa1\xe8\x0dQ\x16\xcf4\x14\xcd\x83\x93qv<\xcbPn\x8e\xa1\xcc\x0cC\x05\xf2\x0bahec\xd1\x98&\xe4\x16Bdn\x80\x07\xc9+\xf4\xed\xb3\n}\xe3\x9cB\xbbxF!\xe4S\x88\xe8\x1c\x95\x1dL=cs a2 \x9d\xa8\xb0\x91g\xa1l\x06\xa1\xbc\xfcAy\xd9\x83\xac\xbc\x0c\x85r\x07\xc5\"\x96\x997\x08\xbck\xfb\xbcY\x8309\x83tiS3\x06E\x9bY\xe8\x9d\x94\x9e+(1SPj\x9e\xa0\xa4,AI9\x8223\x04\xe1re\x14\xce\x0et\xd2\xdc@\xdf>3\xd0\x03\xe4\x05\xfafY\x81\x109\x81\xa2O(.\xcf\x8e\xee\x1fR\xb2\x01\xe1r\x01\x95-_~\x16\xa0@\x0e\xa0h\x11\xf5\xc5\xe3\xf9\x7f\xac\xb7\xccq\xd9\x7f|/\x17\xc9`\xa8\x97\x18\"]\x87N\xd0!\x8bsu\xf9z\xe6\x8b\xd2rPZ\x8e\xd8\x18\x12\xfb\xa1Di9(-\x87\xdb(-\x874J\xcbqh\x94\x96\x83\xd2r\xf8\x8c\xd2rPZ\x0ei\x94\x96\x83\xd2rPZ\x0eJ\xcb\xa1\x8c\xd2rPZ\x0eJ\xcbAi9(-\x07\xa5\xe5\x98\x9a\xff\xd3\x96\xd2rPZ\x0e\x8fQZ\x0eJ\xcbAi9\x1e2-\x87{\x19\xe6\xa6\x9e|\x99}\x83\xd4\x1c\n\x0f\x8a\x17\\\xb1\xaa&\x97\xc8\xb7\xc9 Rz!\xf6\x8b\x8a\xf3jq\xb7e\x8d\xe1,}\x8b\xb2_\x8d\x07\x0e\xeb\xb3\xe5\xb4\x84\xf5w;0w\xd5g\x93dD\xad\xd5\x1eBz\xb0J\xdbr\xfd\xc4\xc4\xea\x91.\xd8>\x08\x97m\xfc\x01\x84\xbd\xe8\x82\xef\xa4\x89-\xcc\x1e\xa3\x81I-\xf4C\xcd\xdb\xe1/\xb5\x7f\xe6r\x0c\xb6\xc5\xdb{\x8f\x1e\x17\xf6z\\F\xb8\xbf\x87\x08\xd3a0\xdc\x95\xf6y\x1a\xea\xec<\"V\xd7\xd0rz\xcc\x82\xfa\x91k\\\x0d\xf8\xd8X|\xe7)R0k\xbc+\x82\"\x0f\x03 \x1e\x08@\xa8\xdd\x80\xbb\xdd\x80\x9c55\x96\xaa|\x07\x9d\xb9\xa7?\x03\xf3\x01\xa5\x15p\x88\xab\xe0\x90\xa1\x84\x87+P\xf1;\xb4\x1a\x0e\xa5\x14q\xc8T\xc5\x83\x0eEp\xd1\xca8\x1c\xaf\x8eC\xb2B\x1et\xa5\x95\xbb$\x95\x1cJ+\xe5\x90\xa8\x96C\xaab\x1en\xd9\x83\x9a\x8eU\xcd\xa1\xb4r\x0e8\xf5\x1cJ*\xe8p\xb4\x8a\x0eyJ:\x94R\xd3!KQ\x0f?\x0e\x95\"\xd2\xa3\xcf\xcdI\x94u8\xa1\xba\x0e\xa7Q\xd8!Qe\x87<\xa5=\xd6\x05\xe3\xd4v(\xab\xb8C\x82\xea\x0e\xe9\xca;d\xa8\xef\x88.\xf3\x07\x84\x02\x0f%Tx\x88)\xf1\x80\x1f\x9e!\x14yH\x1c\xc5%+\xf3AoR\xb5G\xa8\xf3\x90P\xca\x82*=$)\xf5PZ\xad\x87L\xc5>\xdc\xae\xfa\xb8j\x0f\xf9\xca\xbd\xd7\x9f\xb8bL\xbd\x87b\n>\xe0\x85h\xc0(\xf9\x90\xa6\xe6CL.\xcbT\xf5\x01\xe170U_H\xe1\x87\xac\xe0\xe2\x95~@\xd42C\xf1\x87\\\xd5\x1fpQ=Z\xfd\x07<\x01\x00H\n\x00\xd0$\x00\xe0\x82\x9eN\x04@\x12\x15\x00!2\x00J\xd1\x01\x90J\x08@&%\x00i\xa4\x00 nB\x88\x18\x00\xcc\xf9xr\x00\n\xd2\x03\x80)Z\xe0)+G\x12\x00\x86&\x80#\x88\x02\xafCq`\x88*\x80\xd2d\x01D\xe9\x02\xc8%\x0c\xbc\xde\xd4\xf7ox*\x00A\x1a@\x986\x80,\xe2\xc0\xeb*H\"@.\x8d\xe0\xf5\xa6\x86\x91\x81I\xb7rT\x02\xa0\xc8\x04\xc8\xa0\x13 \x8dP\x80\x1cJ\x01\x92I\x05\x08w#\x10Q\x8f!AA\xc6R\x0b\x90C.@*\xbd\x00\xe1\x8a\xe7P\x0c^g\x16#\x80}dp4C\xf0\x81h\xd6a\xa2\x01\xcaR\x0d\x10#\x1b L7x\xcf\xc9\xa5\x1e\xa0`\xdbM\xa0\x1f \x89\x80\x80\xc0\x08\xc5\xac\x9dV2\xd7\x80\xee\x87D1\x93\xd3i\xd4\xfd\xa6\xb9(*^\xa9D\x14v\x1et\xaf\xc71[\xbdO\x9f\xce\xca+n\xb6\x14\xf1\xaf.E-\xec\xf6N\xd3\xe0\xb2\x1f\x0c\x1b\x9b\xe8\x95\xce\xc3\x1e'\xb0\xab\xfa^M\xed\xaa\x9dP\xfe\xb1g=?S\xbf{\x9c\x8d[\xc0\x846A\xb9\xe0\xd6\x13,\xf7\x9b\xf0M\x00p\x99!\xae\xea\x184-l\xdb\xcel\xc6\xe0\x9c\x05\x93\xfb!\x1c\x19\xccxJ.\xef\x1c\xd2\xb0\x1d\x83o\x7f\x0ek)\x93\xaf\xbev\xa0\xed\x9d-<\x87\x7f\xa9\xe46\x08\xcf\xa0\xe6\xbd\x99\xe6\xefa\xdfH%\x84-\xd5L\xe6\x97\xba?l\x1f\xf1i1{\xf7\x1bU\xab ?V7\xb0\xbe\xba|=.\x8c\xd7\xddW\xaf\xb2\xfa\xb9n\x8f[eZ\xb4\x9d\xf2!{\xeaNU~x\xcf\x88\x17\x8a\x9c\x1c\xb5#\xe3\x0c\x879\xe3C\xbb\x1d\xcb\x1d\xec\xf7:\xb6\x93I\xe8\xe1\x8fU7\xdc\xa4\xd8\xc8b\x12\x16\xd9\xbe}\xe3\x8aiw\xa6[\xcf\xc1c8d\x1c\xb0\x80\x1dT\xf2\x01\x97\x9f\x17s\xa8H\xdc!\xcaC@y\x08b\xd3\xfe\xf1\xee@Y*\x8da\xa6\xb0\xbd\x0e\xb1$FQ\n\x83\xf2\x10P\x1e\x82\xd1\x8a\xd2\x15)dE\x12UAy\x08\x8e%(2\xe8\x89\"\xe4D:5Ay\x08\x8e\xa1$R\x08\x89\x0c:\x82\xf2\x10P\x1e\x02\xcaC\x80\xa5\x1b\x8a\x92\x0d9T\x03\xe5!\xf0\x1d\x16\xa5\x17\x12\xc8\x05\xcc*\xfb\x14b\x81\xf2\x10P\x1e\x02\x04}@y\x08 \x930H\xa0\x0b(\x0fA\x01z J\x0e\xe4R\x03\xdew\x0d\xe5!84\xcaC@y\x08fVbM8V\xd1OV\xf3\x93\x94|\xcaC\x90\xa9\xd8S\x1e\x02c\xa7\xcbC0n\xf5%\xa5v9g?\xdb\x89\xfeT\xcb\xfb\x8f\xceB\xc0g+\xf2\xbfMV\x02pm\x96\xff\x89\xdd\xfbJ?S\x16\xb5\xa2_\xe9\x97\x96\xbd\x17\xbe-a\x9e\x0d\xf2\xbf\x9c\xb3[\xcf&\xb7d\x00L\xca\x81\x90\xa4/\x13\xf3\xb7\x8d\xfc\xa8oW\xab\x9eq\xf1\x9d<-.X\x9aC\xcf&\x9b\x97\xe4\xec\xa6\xef\x0d\xe3d\x06\xc7\x11DU>_\x1cg\xb3'\xba22\x94\xcd~+7c\xd3\x7f\x93\xfd\xdb\xa2j\x86\xcdU\xbe\xdc\xb1\xc6\x04~\xdf\x0c3\x86\xb3\x0f\x85\x0b\xe9m\xc3\xfa~\x0c\xa1\x9ac\xdb\xf7\"\xd4\x9fXb<\xa7\xeeO\x1c\xdcx\x1b\xdd\xd4\xdb\x1a\x1b]y\xac\x91\xb9}\xdc\x84\x9aM\xb6[\xb0\x16\xc5\xf7\x9b\x99\xca\xac\xe6\x8e\xec?]\xac`\xc3V\xdcp&\x1a<1\xa3q9\x11\xae\x1e\x10u\x11\x11\xe7\xdb{`\xd5\xe2\x0e\xaa\xdd\xee\x01\xa3h\xd3\x1f\xe3\xf9\xa1XZg\xc8\xfeU\xed\xdc#z \x10\xff\xa8\x9be\xbd\xa88\x1b$1\x1dAy\xa0nH\xb6\xbb\xbaYl\xf6\xcb\xd9X\xbbRW\x194\xc9\xd9\x1d\x93\n\xb75U.^\x96c\x9d\xe63\xe7\x1f/\xfa\xd9\xdd\x9aUA~\x9et\xac\xd7,\x82|\xbc\xc6\xe7QV\xeab\xf7\xe9\xa3\x84\xae\xa0\x9e|\xb78Oa_9\xeb\x9a*\xce\xd1c\x88\xec\xa7\xed0\x92?\xd7~E\x19\x14\xa2X\xf7\xfeRp\xf65\xb2'l\xe2\xe5\xaf5\x9f\x13\xae{\xc3\xeb\xd0F\xb2\x8eZ\xe93\xac\xcd\x86\xcdZ\x05\xefU\xa2\x8f9 \x1euawU\x7f7\xed\xec\x0f-\xd4\x0d\x8d\x16Y;\x00\xb82+\xc3\x94\\Y\xcf\xab\xce{\x97GC\xdc\xef\xd1P\x0f\xc5h\xf1nl4\xb9\xe0\xc1\xb4\xa1\x81\xf8\xb3\x17\xb4\x1cj\xb4\x9c\xda[\x9f\x89o\xd4\xb5\xf4T\xf7XWL\xf7\xf9\xb1\xdb\xcc6\x80R+\xca$o\xa2\xa0\xd2z\x11q\xa6]\xbd\xad\x9bO\x19\xfdf\xe8\x1b3\xde_\xa2\xd6\xa5c\xbe\xe6\xaf\xd5xt\x92\xe3@\x96\xfc\x99h(\xab\xbd\\w\x04\x8b\x8a\xb3u\xdb\xd5\xff^Y\x93\x8bS\xab\xf6\xfc\xce\xb5\x92P\x19\xbe@\xaf\xa4\x9f\xe8\xac\xc2\xa2m>\xb3\xae\xafP\xf3T\xc5f|\xac\xd67NY\xb5]\xbd\xae\x9bj\xa3n\xb8\xe9n\xac\xf29}\x0eC\x86\xe5\x8dg\xb2SY\xa1\xb6\x10yg\xe2\xde\x97\xd2\x15\xe6\xf1\xba\xd6|\xf9P\xc9\xf0I\xf1\x9b\xa4\x8c5\xfbm\xac[y\x0e\x97\xef?\\\xdf\\\x9d\xff|~u\xfe\xee\xf5\xf9\xcd\xf5\xdf.\xcfo>\xbe\xfbpy\xfe\xfa\xe2\xe7\x8b\xf37Y\xe7_\x9d_\xbe\xfd[\xd6\x99\xff\xfa\xf1\xfd\xf5y\xd6\x99W\xe7\xe2\xaf\xc1S\xcdb\xe2\xa3\xea\x8cY\xbc0Z4\xbe/\xe1]\x8b\xbc\xf1\xd6\xd2\x8aX\xff\x1f\xb8-/\xd5\"\xd4q\x0c>\x19\x13wl\xb7\xb9\xd7\xf8\x91\xb5\x92#0\x91\x18\xb9\xa6\xbc\xa1\xe1k\xfec\xdf\xf2q}E\x81k\xaa\xa6\x10\xad\xa8\xd5\xff\xa0\xaf\x1a\xc9F\xa3\x0c\xfd\x84\xa2:Se\x07S\xffc\x8f\x88(\xb3\xa4\xca\x1e\xac\xd0\xd1\xa7\xe4R\x97\xf0\xa0n\xf3\x01\xc2\xf7\xbd\x1c\"\x04\xd8hij\x99\xf5\x00\x9aH0\xa3m6\x81e\xb5\xca\xe4\xda n\xe0S-\xc2\"\xfa%]\xcf\xcb\xb6\xe7WC\xd1\xfd\x03&\x9d))\xfc\xcc\xc7c\xf7\n6\xb5$\xbf\xf4\x18\xc4j\xeb=\xa3Tc\x94jL\x1a\xa5\x1a\xa3Tc\x94j\x8cR\x8d)\xa3Tc\x94j\x8cR\x8dQ\xaa1J5F\xa9\xc6\xa6\xe6\xff\xb4\xa5Tc\x94j\xccc\x94j\x8cR\x8dQ\xaa\xb1\x87L56\xc9$\xa5(\xaec\xf3`\x1d|\xcdG2\xce\x8c\xf9\x0b\x10\xe5\xd6 \x07NP\xec\xd4\xf4]\x94\x12+-\xdf\x10\xa5\xc4:ap\xe3\xc9\x9c(%V\x89(RJ,J\x89\xf5\xebL\x89\xd5\xb1J\xa7\xbc\xfa\xfc;\xff\xd6\xceb\xfc\x11\xc8\x80ue\x9c\\\xca\x03\x95\x9e\xd6\xc3,]\xa5:F\x0df4\x92n\xae\xa2\x1dN2a\xcd\x9c>1\xb5\x7f\xac\xc9\xb0\xac\x18\xd9\xe6u\x05Q\x94$\x9a\xd4**\xa3\xe0y:\xc7\x18Q\xf4\x17\xc3\x8aZ\x89Y\xa9\x9b\xdb1\xa5\xa38\xdcul]\xf7\x9culyc\xee\xb7\xa7\xe4\x1a\x0bU.\xad\xa5\x8dW\x83\x07s\xff\xff\xaa\x87L\xba5\x04\x02\x11X>\x17cv\x00X#:\xc9\xc0\x12\x1bw_spTt\xfd\x04\xc0\xff\xbacR\xc8\x8b\xd6\x15\xb5\x02X\x17\xdcq\xc4\xaac\xec\xc6\x9fO\xca{\x0f~\xee\x18\xbbf_\xf9\x7f\xca\xc8\x9b\xe0z*a\x8dz\xfd\x81\x13\xb6\xad\xbe\xdelX\xb3\xe6w\xb1\x82\x95\xd8Y\x1a\xd7p\xae\xef\x98(\x17\xa8r\xa9\xb1C\xb8\x9e\x01gw\x95W\xe2\xec\xd8\xfa\x86}\x8d\xd5;\xb2h\x0b\xa3\x81*\xbbb\xeb\xf3\xaf\xaa6r\xac7\xad\x92\xbeaz\xe4\x11\x90;\xf4\x02,5\x18\x11\xbd=o\xf5\x90\xf6\x8b\xfc60\xf8X?\xf9L\x08\xb04 \xd70\xa9\x80\x1eN\xd2\x85n\x98\xd9\xb1~\xfeb\x9c\xcc\xff\xed\x0e\x1e<\x17,\xa3y\xf8\xe1M\xe9\xecu]O\xa8.\xdf\x01q.G\x00\xb3\x82\xe5\xd3\xaeSGpu\xf9\x9a\x00W\x02\\\xa3\xdd\x03\xb6s \xc0\x95\x00W\xb7\x11\xe0*\x8d\x00\xd7C#\xc0\x95\x00W\x9f\x11\xe0J\x80\xab4\x02\\ p%\xc0\x95\x00We\x04\xb8\x12\xe0J\x80+\x01\xae\x04\xb8\x12\xe0:5\xff\xa7-\x01\xae\x04\xb8z\x8c\x00W\x02\\ p}H\xc0\xd5\x82\x17&\xcc\xa8\xcd\x92@\x160\x8a\xc3\xc8\xcap7r\xbf\xba_t\xf6\xcf\x7f\x8e'!P\x9c \x84#\xb1\xd9a;:+\xd7\x96\x9b\xc0yb\x02\xf3H\xd9\x9bY\\l\xe3\x0f\xa0\x8fE\xb9\x9d\xa4\xf9!L\xca\xeb#7\xa3\x1b\xd8\xac\xe8\x86t\xbb\xbd\x87\xf2\x08'\xa8-\\\xdd\xf9&\xd4\xad\xab.j\x86\xbf]\xd4\xd9{\xd0\x9d`\xe7\xbc\xa1t\xb3\x1d@\x9c\xe7#f\x18\x8f\xdeI\x8dG\xb4\\\xc0\xdd=@\xce \x1aK\xd5u\x83\xce\xdc\x93{\x81\xaf\xdd\xd2\xfa.\xc45^\xc8\xd0y\xc3\x15\xa8\xf8\x1dZ\xeb\x85Rz/dj\xbeA\x87\"\xb8h\xdd\x17\x8e\xd7~!Y\xff\x0d\xba\xd2\xbaT\x92\x06\x0c\xa5u`H\xd4\x82!U\x0f\x0e\xb7\xecA+\xc6j\xc2PZ\x17\x06\x9c6\x0c%\xf5a8Z#\x86<\x9d\x18Ji\xc5\x90\xa5\x17\x87\x1f\x87J\xe5=\x8f>7'\xd1\x8d\xe1\x84\xda1\x9cF?\x86D\x0d\x19\xf2t\xe4X\x17\x8c\xd3\x92\xa1\xac\x9e\x0c \x9a2\xa4\xeb\xca\x90\xa1-#\xba\xcc\x1f\x10\xfa2\x94\xd0\x98!6\n\x04\xfc\xf0\x0c\xa17C\xe2(.Yw\x0ez\x93\x9a4B{\x86\x84R\x16\xd4\xa0!I\x87\x86\xd2Z4d\xea\xd1\xe1v\xd5\xc75i\xc8\xd7\xa5\xbd\xfe\xc4\x15c\xda4\x14\xd3\xa7\x01/\xb3\x02F\xa7\x864\xad\x1abbP\xa6f\x0d\x08\xbf\x81\x89\xe8B\xfa5d\x05\x17\xafc\x03\xa2\x96\x19z6\xe4j\xda\x80\x8b\xea\xd1\xda6\xe0\xf5m@j\xdc\x80\xd6\xb9\x01\x17\xf4t\xbd\x1b\x924o\x08\xe9\xdePJ\xfb\x86T\xfd\x1b25pH\xd3\xc1\x01q\x13Bz8`\xce\xc7\xeb\xe2PP\x1b\x07L\xd1\x02OY9\x9d\x1c0Z9\x1c\xa1\x97{\x1d\x8a\x03C\x9a9\x94\xd6\xcd!\xaa\x9dC\xae~\xee\xf5\xa6\xbe\x7f\xc3S\x01\x08\x1d\x1d\xc2Z:d\xe9\xe9^WA\x9d\x1dr\xb5v\xaf75\x8c\x0cL\xba\x95\xd3\xdc\x01\xa5\xbbC\x86\xf6\x0ei\xfa;\xe4h\xf0\x90\xac\xc3C\xb8\x1b\x81\x886\n \xfa(V\x93\x87\x1c]\x1eR\xb5y\x08WxG(\xa7\xd9\x89\xd8\xc8k\x8es\x86-\x02\xb5\x007\xdd'\xb1\xe2\x95\xceH1n?\xe5\xf3F\xfbP\xd1>Tq\xe5\x9d\xf6\xa1\xeai\x1f*\xcb\x12\xf6\xa1\x1a\xb8\x9b\x02\xcb\xf2i\x07*Z\xa0\xef\xfc\x9d\x16\xe8[F\x0b\xf4i\x81\xfehE\xc1\x8c\x14(# \xc8\xa0\x05\xfa\xc7\xc2\x17\x19\xe0E\x11\xe8\"\x1d\xb8\xa0\x05\xfa\xc7\x00\x16)pE\x06XA\x0b\xf4i\x81>-\xd0\xc7\x82\x11E\xa1\x88\x1c \x82\x16\xe8\xfb\x0e\x8b\x82\x0f \xd0\x03f\xf9y\n\xec@\x0b\xf4i\x81>\x02\\\xa0\x05\xfa\x90 '$\x80 \xb4@\xbf\x00x\x10\x85\x0er\x81\x03\xef\xbb\x86\x16\xe8\x1f\x1a-\xd0\xa7\x05\xfa3+\xb1X\x1a\x0b\x03$\x83\x00I\x10\x00-\xd0\xcf\x14\xfbi\x81\xbe\xb1\xd3-\xd0W\xfb\xf5L\xf2a\xeb\xb5\xbc\x9e\xe5\xea\x96\xefS-\xda\xb7\xb6\x0eQ\xeb\x99}\xf5\xb9\x14E\xad\x97\x8f\xa5\xb4\xfb~\xf2Y\x1eR\xfa\x9f\x9aY\xe3\x1f\xe0c/\xde\xe1\xde\x1aL_\n&\xb5\xfa\xba\x95\x1bP\xb5C\xfet9b\x10Cku\xff\xea\xa5\xdc5e\x98\x9f\xa8T\x7fr6\x8bG\xea\xa6&\xb3\x88\xd0f\\)\xd1\xf2Le\xd1f\\e\x83\x1b\xdfF\x8a6\xe3*\x11E\xda\x8c\x8b6\xe3\xfa-o\xc6\xe5K\n\xf4\xe2\x17\xf3O\xf1wu\x9dP\x8a\xa0\xf06]r\x0e_\xfcE\xe5\x08\x1a\xc6B\xce\x0cAOL4\x1ey\x82\xa0\xa2\xc0f4\xcdOTc\xc2c\x86YY|<\xd9z\x82\xb9zNR\xe6#\xb2\xf4\x84\xcb\x19\xca\xd0\x13\xcf\xcfsLv\x9e\x80\xb8\x18lR\x10mV\x80\x00\xb8\x10\xf7 \x90\"\xa0\xb2,\x8c+\xe0/)\x1bOQ\x94+\ns\x95\xc6\xb9\xf0@W!\xa4+\x0f\xea\n\xb8K\xcc\xbfs$\xd8U\x1a\xedJ\x84\xbb\n\xe3]i\x80W\"\xe2\x15j\xc3\x19\x19w\x8ab^(\xd0\xab \xeau,\xec\x95\x85{\x15\x02\xber\x90\xaf\x803t\x86\x9d\x13`_\xa7\x03\xbfN\x82~\xa5\xc1_\xc5\xf1/,\x00V\x14\x01\xc3C`\xc9\x18X:\x08\x16\xed\nq\xb9t\x8e\x86\xc1\xa2ytP\x03*\x04\x12\x962\xeaJ\xc6\xc2B/At\xf6\x1c\\\xf9\n\xc2a)xXa@,\x0f\x11\x0b\xb5 T\xc6\x9cLL\xcc\xe3\x8d\xa3\xb2\xe5\x94A\xc5\xd0\xbc\x13\x02\x17K\x02\xc6b !r\xa0\xb1\x98O\xaf\n\\\x08\x1dK\x0f&\x1e\x1f\x8b\xd5-\x03!\xcb\x84\xc8\x10q<\x1a$C\xa3d8\x98\x0c\x8b\x93!\x82\x9c\x8e\x94\xa5@e\xc1\xfc7E\xc0\xb2D\xb4,\x0f.K\xc2\xcbbA\x0f\xe7\xbc\x89\x9c\x8b\xc7\xcc\xca\x81f\xd1By\x9f\x9fr\xb8\x19\x028\xcbG\xce<\xeex4\xc3MQ\xec,\x06\x9ee\xa2g\x1e_\xf1\xcc6\x08\xfc,\x92\xd5\xa64\x82V\x1cB\xf3ch%A4\x0c\x8a\x96\x0e\xa3%\xe1h\x19@Z*\x92\x16\xc9T\x13.\x1d\x16\x12\xc2\x82i\x19hZ\"\x9c\x16\xa8n\x0e\xa0\xe6q\x85\xc8M\x93\x03\xa9\x05\x9a|\x1f\x8e\xf7\xaf\x83\xb5\xe6<\xae\x86\x13\xc7\xc4\xf9\xee\xd5\xb1\xe6\xb81H\xe2m?82\xc5\xd1\x7f\x98-\x96=\xb8\x88>\xec\x11\xaf\x9b5E\xbe\x99\x05\xd46\xfe\x00\x02ft\xf1m\xd2\x04^`1k|\xa7\x0fpu^\xa2\xcf7\xcb]\xeb\xfepm\xae\xd7\xd7\x18r\xe7!\xb1\xea\x86V\xc4b\xd6\xc4:W\xc5\x1e4z\xf7-\xb9k;~W5\xcb\x1b\xb7\xdc\xae\x0cqWt >J}xt+U|k\xb5\xb0z?[\xc1u\xba[\xd6\xfdnS\xdd\xdf\x1c;\xd7\xab\x0b\xf5W\x95\x12C\xbc\x9aF5T_\xc3$bP\xc9JbE\x0b7\xab\xc3\xceb\xc6\x91(\x9a@\xa1$\x9163_\xd6\xec\x99w\x9d\xf5]\xc6h\xbb#\xda\xee(\xd6Zi\xbb#5\xbc\xa7\xed\x8e\x8c9\xb7;:x\x0c5\xcav0.BQm._/\\#9q\xa7\x88h#\xa2-\xf6\x8a\x8fw\x0b\xca\x88h#\xa2\xcdmD\xb4I#\xa2\xed\xd0\x88h#\xa2\xcdgD\xb4\x11\xd1&\x8d\x886\"\xda\x88h#\xa2M\x19\x11mD\xb4\x11\xd1FD\x1b\x11mD\xb4M\xcd\xffiKD\x1b\x11m\x1e#\xa2\x8d\x886\"\xda\x1e\x94h\x8b\xb0D\xdf\x9e\x0b\xa3\x0dt\xd2v'\xa1\x0dtN\x18\xdcx\x1b\xa5\x0dtJD\x916\xd0\xa1\x0dt~\xc3\x1b\xe8\xb8(a\xfc\xde9\x07X^\n'\x9c\xc8\x07?11\xfa\xcf\x83\x07\x17e\x04\xa3\x90oT\xd1(@\xb6\x95\x83{\x83\x98\xe67\xde\xe8\x06\x83\xf4b\x80\xde\xe8\x1d(\x08\xf3\"P^lqJa\xbc\xa1\xc6S\x0e\xe1E\x01\xbcN|7\x11\xbc+\xc9\xdd\x11v\xa7\x8d\xb0;\xc2\xeeF#\xec\x8e\xb0\xbb\xd1\x08\xbb\xe3\x84\xdd\xb9\x8d\xb0;c\x84\xdd\x11vG\xd8\x1dr\x94D\xd8\xdd`\x84\xdd\xd9F\xd8\x1daw\x0e#\xec\xceu\x0caw\x84\xdd\x11vG\xd8\xdd\xd4\xfc\x9f\xb6\x84\xdd\x11v\xe71\xc2\xee\x08\xbb#\xec\x8e\xb0;\xc8O\xc7v\x08\x13\x0cU:\xb6\xe4\xa5\xb2\xb3\x89/`I]\xc8\xdb\x17\xc8\xbav)\x7fwR\x13\xdbv\xb9\xdf0\xab\x01\xe8sg\x94\x84\xbc\x94r\xf3\xc4\xd4\xf1\x91\x02\x12v0l\xf3\xba\x82\xa8\xe4\xd6\xf3\xaaYV\x9d$.zg:6\x88H\x81\x10\x92\x03!V:e1Y\x10\x82\xa9\xca \xaa\x99\x8e\x16\xa7\x1b\x949\x18\x07\x11\x1f\xa8\x9b\xbe^\xb2I\x87\xe0\xf5\xa2|D\x0b\x1d\x9c\xca\x83\xb1,\xd7\xe2?\xd3\xe2xO\xb2\x9bg\xb1\x02\x047\x9f\x07xjd\x9d\x1f\xe0\xfc+g\x8dx%Z\xe5\x98\x05\xd2\xbf\xcf\xab2\xf9\x02\xac\xc4\xf8\xb4\xe6P\xedv\x1b)\xc3\xfare\xc5K\xf8A7\xf4+uy\xdf.z\xfa\xa8X|m\xa0vW/>\x89\xb7\x7f\x13\xd0|\xd5\xce\xab\xc5\x9d\xd2*\xac\xc2yn\x81d\x90\x1dr\xbe2|A^-\x97\x1d\xeb\xfb\xe9m\xf7\x84\\\xf5I\xe1k\x1e\xbd\xc9\x1f\x8fh\xec\x80\xab\x1e \xe7j\x8d\xa5\xea\xedAg\xeeI\xd7\xc0,Di\xdd\x1d\xe2\xda;d\xe8\xef\xe1\nT\xfc\x0e\xad\xc1C)\x1d\x1e2\xb5\xf8\xa0C\x11\\\xb4\x1e\x0f\xc7k\xf2\x90\xac\xcb\x07]i\xbd0I\x9b\x87\xd2\xfa<$j\xf4\x90\xaa\xd3\x87[\xf6\xa0\xe1c\xb5z(\xad\xd7\x03N\xb3\x87\x92\xba=\x1c\xad\xddC\x9e~\x0f\xa54|\xc8\xd2\xf1\xc3\x8fC\xd5\xb3e\\\xcb\x87\xd3\xe8\xf9pBM\x1fN\xa3\xebC\xa2\xb6\x0fy\xfa~\xac\x0b\xc6i\xfcPV\xe7\x87\x04\xad\x1f\xd2\xf5~\xc8\xd0\xfc\x11]\xe6\x0f\x08\xdd\x1fJh\xff\x10\xd3\xff\x01?\x01\x107!\xc4)\x00\xe6|<\xaf\x00\x05\x99\x05\xc0\x14-\xf0\x94\x95\xe3\x17\x00\xc30\xc0\x11\x1c\x83\xd7\xa180\xc42@i\x9e\x01\xa2L\x03\xe4r\x0d^o\xea\xfb7<\x15\x80\xe0\x1b \xcc8@\x16\xe7\xe0u\x15\xe4\x1f \x97\x81\xf0zS\xc3\xc8\xc0\xa4[9\x16\x02P<\x04d0\x11\x90\xc6E@\x0e\x1b\x01\xc9|\x04\x84\xbb\x11\x88h\xd6\x90\xa0[cY \xc8\xe1% \x95\x99\x80p\xc5s\xd8 \xaf3\x8bL\xc0>28\x86\"\xf8@4\xeb0G\x01eY\n\x88\xf1\x14\x10f*\xbc\xe7\xe4\xb2\x16P\xb0\xed&0\x17\x90\xc4]@`\x84b\x96YK\x95\x0b\xa1\x83J\xb1\xb0n\x9b\x9be\xc5\x8f\x91\x04\xcd<\x88p\xf3\x9c\xd7[\xdf\xad\x19\x96\x81o\xe5\x10\xf2@J\xfeR\xf5\x01\x15yXE-\x8f=\\E-^K\xea\x9b\xb9^\xb8kM\xbb\x06\xd1\xaeA\xf1\xec\x00\xb4kPO\xbb\x06Y\x96\xb4k\x90D\x86\xf0y\x18\x149E\x89\x18(\x11\x83\xe3wJ\xc4`\x19%b\xa0D\x0c\xa3\x15\x05=R \x8f$\xc0\x83\x121\x1c\x0bsd\x80\x1cE \x8et\x80\x83\x121\x1c\x03l\xa4\xc0\x1a\x19\xa0\x06%b\xa0D\x0c\x94\x88\x01\x0bZ\x14\x85,r\x00\x0bJ\xc4\xe0;,\nR$@\x14\x984\x03)\xf0\x04%b\xa0D\x0c\x08\x10\x82\x121@&\xec\x90\x00:P\"\x86\x02 C\x14b\xc8\x05\x18\xbc\xef\x1aJ\xc4ph\x94\x88\x81\x121\xcc\xac\xc4\xa2x,\\\x90\x0c\x16$A\x05\x94\x88!\x13\x1e\xa0D\x0c\xc6N\x98\x88\xc1\xb3\xca\xdfr\x91\x9e\xd3 5\xfd\x82Z\xb2{f\xf4\x12_\xf1g\xdf\xcf\xb9\x9a\xc7A{\xf3\xe9\x1c9\xda\x86K\xc3\xc8\xd2-\x82\xfaD\xb6&\x91\xa9C\xd8z\xc3\xc4\xdf\xe1'z\x86\xde\x90\xa51\xcc\xb4\x84yxf\xbaB\x8e\x960\xd3\x0c\xe6W\x98^ W3\x18\xb4\x81\xa9\xfb\x83\xc1T\x8e6\xe0\xd3\x00\x8e\x9a\xf7G\xcd\xf5c\xe7\xf4\xb3\xe7\xf1s\xe7\xee\xdds\xf4\x85\xe6\xe5K\xce\xc5\x17\x9a\x7f\x8f\xcd\xb9\xe7\xcd\xb3\x07\xe6\xd3\xd3\xe7\xd0\x83s\xe5\x88\xf9\xf1\xdc9q\xcf\xdcw\xe6|w\xce\xbeC\xb3\xd7\xe4\xecm(\x9f\x0d\xeb\x9c\xd0\xab0sb{\x9c\xc0>\x0cz\xd9\xbay\xa6\xf1\xc7\xfcK\x07 =B@\x9c\x95\x97\xe4cozE\xedc\xa9^\x80*\x86\x93\xb3\xe4[\xbb\xeea\xdd\xca\xdd\x94\xdaa\xdf;\xf9\xb5]\xaf\xac\x13e\xf7\xb7\xe9\xdb1@\x85\xe3A{#\xa6D+\xd2zho\xc42\xc1\x8d\xef\xeaG{#\x96\x88\"\xed\x8dH{#\xfe\x86\xf7FT\x87\xfc\xa2\xfe\x11\xdb\x1bQ\xaa\xc7\xfe\x8c\x84\xf8\xbd\x11\xad\xa5\x02\x8f<\x1ba\xd1u\x0b\xd1\x9c\x82\x9e\xdel4rjyj\xd9\x13\xcdSK\x9fv\x0e8Cg\xfc+4==\xb5\x92\x93\xd5S+4u=\xb5\xd8D\xf6\xd4\xf2\xa6\xb5#=~\x1c \xcf\x99\xfe\x0e5\x10$D\x8e\x9a&\x9fZ\xea\xa4y\xb4+\xc4\xe5\xf6\xcb\x9c\\\xb7-\x92\xd7\x0f5\xa0B \xe5)\xa3\xae\xe4\xd9\xf7\xd0K\x10\x9d\xcd\x0fW\xbe\x82py\n^^\x180\xcfC\xccC-\x08\x95\xc1/\x133\xf7x\xe3\xa8\xec}ePs4/\x8d\xc0\xcd\x93\x80\xf3X\x82\xaa\x1c\xe8<\xe6\xd3K\x91\x15B\xcf\xd3\x83\x89\xc7\xcfcu\xcb@\xd03!tD\x1c\x8f\x06\xd1\xd1(:\x0eF\xc7\xe2\xe8\x88 \xa7#\xe9)Pz0\x1f_\x110=\x11M\xcf\x83\xd3\x93\xf0\xf4X\xd0\xc39\xf8\"\xe7\xe21\xf5r\xa0z\xb4P\xde\xe7\xa7\x1c\xae\x8e\x00\xd6\xf3\x91u\x8f;\x1e\xcd\xb8W\x14[\x8f\x81\xeb\x99\xe8\xba\xc7W<\xd3\x1e\x02_\x8fd\xd9+\x8d\xb0\x17\x87\xd8\xfd\x18{I\x90\x1d\x83\xb2\xa7\xc3\xecI8{\x06\xd0\x9e\x8a\xb4G2\xe7\x85K\x87\x85\x8c\xb1`{\x06\xda\x9e\x08\xb7\x07\xaa\x9b\x03\xb8{\\!r\xe5\xe5@\xee\x81&\x1f\xcf\x93W\x10t\x8f\xe6\xc8;\x05\xec^\xaa-&\x00\xef)\xc8\xbbo|\x90\x96\xff\x0e\x91\xfd.:c\x80\xcb|wL\xde\xbbc\xb3\xde!\xf2U\xa5\xa5\xab\xa2lU\x94\xad\xca\xf5;e\xab\xb2\x8c\xb2UQ\xb6\xaa\xd1\x8a\xca\x91)bd\x92\x14I\xd9\xaa\x8e\x15 3\xe4\xc7\"\xe2c\xba\xf4H\xd9\xaa\x8e\x91\x1cS\x04\xc7\xc2r#Nl,(5b\x85F\xc7\x87\x00e\xab\x9a\x1aBZ\xc4\x8e\x92\x92eE\xcaV\x85\x12\x13s\xa4D\xcaV\xe5;,*\x1f&\x88\x87\x98\\L)\xc2!e\xab\xa2lU\x08y\x90\xb2UA\xa6 \x98 \x07R\xb6\xaa\x02\xf2_T\xfc\xcb\x95\xfe\xbc\xef\x1a\xcaVuh\x94\xad\x8a\xb2U\xcd\xacD\xe6 \xac\xa8\x97,\xe9% z\x94\xad*S\xc4\xa3lU\xc6N\x98\xadJ\xb4\x85\xf1.iimX\x17\xfa\xad\xf3V\x0dKX\xe3Ux\x98\xa2\xc6\xd6\xeb\x8a\x0f\xde\xcd\xfd\x8b\xcf\xbf{\xb1\xa8\xbb\xc5~S\xf1\xbaY\xbf\xf8e\xc9\x9av\x1bX\x96kM\x0d\xbc\x1e\xcf\x9353\x8aM\xb5\x1d\x16\x93\xb7\x9fX\xd3\x83u\x01\xf36\xdfV\xdd'\xa9\xe1\x0e\xde&\x13\xddj=\xaf,\x8b\xfe\xdbdI\xafue\xfd\xf3\xa3]\xd7k\xd5\xfdF\x85g\xc2>u0\xb2\xe6\xb3\xaf\xe2\xff\x8f\xbd\xf7k\x8e\x1bW\xf2D\xdf\xfbS\xe4\xed\x87=\xdd\xb3nu\xcc\x99\xfb\xe4\xb83q}l\xb9[;n[+\xc9\xb31\xbb1\xa1CUA%\x8e\xab\xc8Z\x92e[{\xe7|\xf7\x1bD\x02$\x08$\xfe\x10\x80lw\x0f\xf2\xa5\xdd%2\xf1\x87@\x02\xc8_\xe6\x0f\xf6\xb6g!\xda\x9b\xd5\xa5\xb1\xec\x99\x84h\xcb.\xe0\xbcu\x19z`1cs\x92\xe1\x19Txy\x88\xf0\x14\x826\xbd\xf5:%\x9a\xbd\x9dY\x89\xea\x08\x9a\xbaT\x92:\x83\x98.\x95\x96\x8e?\xb2\x9c\xe6\xaa\xfa%%\x9d`\x82\x8b\xef\xde\x04*9\x85>N\x9d\x99&\x91\x9c\x83F\x8e\x9e\xe1\xd2\x8f\x89\x979\xe3\x95\xd0\x86o\xf2u\xdbB\xdf\x1e\xd8\xed\xb4V\x93\xbey\xc5T\xab\x1fNu\xcb\xa3wQ\xecf\xa7J\xa8/\xba.\xc0^\xdcX\xdd#\x8c$m\x88P\xa5\x10\xfd\xc1\xf9\xe7\x90\xa5\x05Mw\xf0\xdab\xde%\x9fc\x81I\xbe\x1b>\xc7}\xf0\xde;\xe0I\xfb\x12f]\xf5O>\xa9\x83\xc0{\xdc\xad7\xb6\xcf\xfa\xd6]\xd2N\x7f\x8c\xb4\xcb\xd8\x15/]\xcam\xeb\xcbIi\xbba=\xf8Vu\xf7M\xea\x7f\xd3\xe6\x88\x9c\x1d/\xdb\xba \x9e\x15|\x1b\xee\x1c\x19\xe8SvmDHk\x1e\xfbv\xd1\x0c\x02;\x9a\xe2\x0d\x17\x00\xd2\xe28\xdc\xd7\xbb\xa6\x1aN\x1d\xeb\xa7}\xf1\xb8\x10\xef\xda]\xcb\xa1\x98q\x8e\xa0\xfbC\xc2\x81\xfd\xd9\xc7\x7f8{q<\xbe\xa9\x9b\x0f\xfd\xe5h9\xfb\xe0\xfe\xe4A\x83\xf5\xf0x\xbb\x15\xe8\x8eg\xd6\x89\xe9\xf5Jl\x1b\xe4\xeb _\x87;\x1e\xb1\xcb{h\x8eD\x86}\xdd|\x00\xf6\xf9Xw\"\xc7\xcf\x0dv\xf0\xf4\xe18\xde\xfd\x03\xdb\x9d\xc1\xcd\xa7z\x18X\xf7\x0c~\xa9\x87_Ow\xcf\x80\x0d\x1b5\xe8g\xec?~Z]U\xde{\xf1\x96\x8c\xb0W\xcbV\x8b\x1dOw\xb2h\x10\x9f{Q\x85~X\xe4\xee \xf5\xd7\xe3\xafr\x1fHt\xa6V1\xd6\x9c\x0ej\xfd\x7f\x82\x17\x97\x97o.^\xbe\xb8\xb9x\xf7\xf6\xf6\xcd\xc5\xdb\x7f\xbe\xbd\xbeyqs~{\xf1\xf6\xe2\xe6\xe2\xc5\x9b\x8b\xffy\xfe\xea\xf6\xfd\xdb\xeb\xcb\xf3\x97\x17\xaf/\xce_\x85\xbc\xfa/\xe7W\x17\xaf\xe5\xef\xd77/\xaen\"\xde;\xbf\xbazw\xb5\xfa\xad\xeb\xf7/_\x9e__\x87\xbcws\xf1\xdb\xf9\xab\xdbw\xefo\xa6\x87\xa5\x93.\xb6K\xec\xfb\xd5\xb5\xbd\xfc\x1c^\xe0\x8c\x1b\x17\xb7\x7f\xc7\xf8\xe7\xc5\xf6\x9a\x1f\xf8E\x96\x17\x04\x94C}\x12\xb3\x90~\xa8\xf8\xcd\x01wl\\h?\xb2\xce\xb8\x13!\xac\x00\xfe\xed\x16\xea\xb9\xc3\x91mG#*\xcf\xed\xa8^L\x84c\xd7nX\xdf\xaf/J|\xf0Ea\xcb\xea+\xde\xe8e\xb2\x8f\x7fd,\xb4\x0e\xf5a\xdc\xf8\x9c\xf8B\xb7g\xf0\xa9\xaa\xb9_L\xfa\x83\xd5\xf6\x88b\xda\xae\xda\xec\xd9m\xa7\xfa\\`\x9e\xba\xef\xf8\x9f\xe5n}r(I\xa73\xfe\x8cP\xbf$\xae=T[&W \xd4\x1ec;uVa\xab s\xb0\x08K\xbe\xddWr\x9f}\xf1j\xc6\xf8y\xd5\x95\xc7EG\xe0\xf40(\x98\x13\x8a\xc7.\xbc\xe6z\xb1*X\x8d\xaa\x11e\x02\x96\xa9\xbc\xbb\xa9\xf6\xfb\xdb\xe5\xaa\xa5(|Y\xed\xf7\xc4\xea5\xfe2\xb9\x13Y7VL\xf9\x06D\x8b\x1d\xfee\xbbg\xd9\xba\xa6\x81\xab\x97\xc0\xbe\xb6-i\xa7\xdbO\x0d\xeb\xfa\x87\xfa\xa8\xf8\xbc\xa8In\xef$\x08\xac\x07\x9931V\xee\x81}\x06\xd6l\xda\xf1\x000\x96\x81=\xcb\xc7\xf8\\'\xd9\xd1\xbcn\x8f@\x07\x1a)\xcd\xa4B\x83\xaa\x8dp\x90\xc86\xab#`?\x1e\xe2\xc2\x87\xa1\xadQ/\xb9\x9e\x8bW\xfa\xd4\x9dg\x02\x964\xcf\xe1\xb1\xc9\x8c\n2\xa5\x06+\x9eC\x0c\xab\xb18\xf7\x89\xa1z\xe0\x86\xa8k\x0f\xaa/I\xd4A\xb5K\xaa\xf7\x90;\x06\xe7c!w\xf1\x8c\xcf\xf3m\xc68\x93\xd0\x18\xea+\xea\n3#\x0c/9\xcf\xae\xf1oj\xd7U*nHXSG\xf9\xe0\x9cV\x16\xa4%d \xff\xca>\xff$\xc7\xab\xf0\x1d\xce\xf6\x98\x1fd\xf0\xec\xc2\xf7\xf3\xb8g\xd3TM\x87\x9d\xb8\n\x903I\xad\xd5\xa4_[)DF%\xaf\xdd\xf8\x8cXv m\xfa\x05K\xf7U\xbdg\xfa\xdc\xc0\xda\xbc\xe6\x7fZ~4|<\xeb\x07[\x0fON5<\xe7\xd0)\xef\x8a\xc5i\x05\x0f\xba\xe3g\x1a\xeb{\xea&\xdf\x82$\xc6\x18\x97w\xcf\xe1\xc8N\x80!\x17\x0f\xa1\x8c\x93_hFa0\x081\xf8\xce\xc2\xa4\xc3\xe0g\xc8|u:\x9f\xd4\xad\xa9U\xbd\xdf\x8b\xc3\xecw\x8a.\xed\xe0ic\xe8\xe0*\xb8\xbb}\xc3\x9a\xa1\x13\xd9h\xaa\xc1\x0e9\xd6^\xcf\xc7\x1d\xa3\xe5\xea)f\xed\xde\xda\xf7\x9a\xe3\xf4\x12\xf6\x8ezr {cic\xfd\xfbR\xfe`\xcai\x85>\xa9\xac\xedI\xe7)\x858\xa1\x04vF\xdc\xe9$Ly\xf2\xc9$\xac\x98\xc8S\x89\xff\xcb\xa7\x9dH\xf4\x1d\x045\xe3&\x0f!\xcf\xf82]\\\xb5\xc2\x18\xbb\xdf\xb7\x9ffc\xc47\x0e\xfds\x10\x1f\xf0\x19\xf0\xce\x1e\xff!\xba\xe3\xf5\xfb7\xcf@\x1d\xc4\x84\x11\xf8K\xdd\xae\xf4\xef\x1d\xaa\xcf\xb7{\xd6\xec\x86\x87@S9\xe1\x08\xa2;\xa6\"\xa7\xa6\xdb\xbds\xa2\xaapW\xb7\xbb\xae:><\xd2\xadx\xf9P\xd5\xcd\xcb\xb6\xb9\xafw\xc1\xedXz\x96\xdc>]E?m\x84\xf9\xe6s|\x08\xd7=\xd3\x8f7\x1e$-~V\xae\xfc)\x1d\x8bj7oY?H\xbf\xb3\xec\xdcJ\xdc[2\xb4\xaaCK\xfc\xaa\x97\x13\xb4\x13\x1d\xc8`\x1d\xeb~\xc2\x9d\xff\x1d\xcb\xdaCl\xbf\xec\\=1\x0c=4\x13O\x14\xff\x0eW\xad)\xb2\xb2\xee\x0c\xf1\\;\x91\x0c;\x06/\x89\x9bW'\x8aM'\x8aCg\xe6\xca1\xfa\xc8\xc2\x9c\x13\xc3\x97\xa3\xf0\xe2h\xda,,9\xb1\xdc8\xf4\xad\xcc8s\x8c2\"xp\xec|7\x89,7A\xdc6\xe1\x1c6 \xcc5\xb1|56^\x9all4y9h\xb21\xcf\xf8\xf9f\xe2Xf(\xa7\x8b\x85[f=\xa3\x8c\x879f\x08\xe1\x8b\x89e\x89\xb1\xb2\xc1Dr\xc0\x10\xde\x12\xaf\x83\xd6`yq\xaf\xa0\x91\x8c.\x96k\x9aE\xff~\xe7/;\x8e\xb3e\xc9\xcf\xa2\xa83\x99Z2\xf0\xb3$\xb0\xb2\x98\xa3\\_\x0c\x13\x18X,l+)\x1c+Nr\x10\x0b\x9f\x8a\x97E\xc5$&\x08gL1\xdf\xfd\x1b\xd5\xd6(N\x94\x90\xc6\xfa\xf8O\xecm\xf3r\x9d\xac`8!\xdb\x1c\xc9f\xe2\xe40\xb13\x97\xb8\xf8J\xc8N\x08\xe5&\xf11\x92h<$ \xec#\x01\x9c#\xe1L#^~\x11\x82\x8e\xc3(\x8ex\xc6\xc7\x1b\x92\xc6\x16BVJ\xf9%\x8a\x0f\xc4\xc6\xfd\x91\xc2\xf8A\xb0{\xc4rz\x90\xfc\x1d \xac\x1d\xc6V\xdb\xca\xcba\xb0q\xe4\xe1\xe0\x88g\xde\xd0X6\xa2\xb85\xac<\x1aa\xec\x19^\xce\x0cq\x90\xf61e\x88\xc7\x9c\xfc\x18\x06a\x84YZ(\x1b\x81\x9b\x01#\x90\xf7\"\x80\xedbQ\xe5\x04f\x0b\x83\xc5\"\x81\xbb\x82\xe2\xa9\x88c\xa7\xa0\x98(\xf2\xf1O\xc4\x7f]/\xd7\x84\x8fab6\xd3\x14H(o\xfd\xb5\xfa\x05\xd9\xe7\x81u\xe34D\x07\xa1\xe2m[\\\xab\xbai\x9b\x86G\xff\xab-\x9fP\xb4W\xdco\xa8a\x9e\xc7\xaem\xef\x0d\xc0\xfar\xfcuY\x9d9\x12\x81\xbf\xe2\xae\xd9\xac/\xdc\xe1w<\xdd-#\xcb\xad\xef\xdbu\x80\xd5q\x08>0\xd2O \x99\xd1\x89\x08NG\"du&BN\x87\"\xb8\x9c\x8a\x90\xe6X\x84\x8c\xceE\xf0:\x18!\xd6\xc9\x08)\x8eF\xaa\xc7\xfc4\xdd\xd1\x0eGB\x97\x97\x9a;\xc5\xf1H\xa8s\xd2q\xe7u@B\xba\x13\x12\xf2;\"!\xcd\x19 i\x0eIz\x8a\x92\x95\xcc\xe6\xa6\x84\xec\xaeJ\xc8\xe9\xae\x84 \x97%\xe4t[\x82\xc3u \x89\xeeKj\x8e[\xa8\xb0\x83\x9c\x9a\x90\xec\xd8$\x14\xd2\xc4\xd7\x91\xeeN\x88\x0c\x10s\x12\\\xfb\xd7\xffH\x17(e\xf6\x1ct\xd6\xeez\xa4\xb9C5e.\xf2\xea\x0cnQ\xc8\xed\x1a\x05\xc2=\n\xe9.RM\x9b\xe90\x85D\xa7)\xf8|\x89\xe0&\xa3\xf6:P\xc1\xca\xee\x1a\xeeH\xb5\xeb0N\xc9INUX\xd1\x19>\xe7*x\xdb\xedu\xb2\xc2:G+\xb8\xfa#\xd2\xe1\n>\xa7+x)\xa3}d\xd1\xd6N\nu\xc2B\x80#\x16hR\xe8\x04\x87,\x849ea\x95c\x16B\x9c\xb3`\xe7K&\x8b\xb7<\xebs\xd6B\xb2\xc3\x16\\\x15\xd5~\xcd\xea\xbc\x85D\x07\xae\xa6\x8a&k\xce\xea\xd2\x85\xccn]\xf0Q.\x93d\xcby\\\xbc\x90\xd3\xcd\x0b\xd9]\xbd\x10\xec\xee\x85\x10\x97/\x84\xbb}!\xd0\xf5\x0b6\xbe`\xba\xf4PG\xa1\x9f\x089\xd0\x15\x0ca\xee`\xa0\x9a\x91\xd3-\x0c\xa9\xaeaM\x17Ih\x9c\xcfY\x0cY\x1d\xc6\x90<\x1e\xbc\x8ec\x08p\x1e\x83\xb1\xea\xd82M.Ow\xff\xcc\x1e\xf5\x8c\x81\xe3\xe9n_o8\xab\x06\x95]!\xbd\xc9\xe6\xadn\"\x06\xd5X\x98\xc7u\x03m1\x95\xabeI\x9f)\xae\xdc\xe2\xca-\xae\xdc\xe2\xca-\xae\xdc\xe2\xca-\xae\xdc\xe2\xca\x9d\xa4\xb8r\x8b+WJq\xe5z]\x9a\xc5\x95[\\\xb9\x86\x14Wn\x9c\x874\xfc\xd9\xe2\xca-\xae\\\xe2#\x14W\xeeB\x8a+\xb7\xb8r\x8b+7\x87+\xf7z\" \xd2\xbc\xb9\x0f$\x93\x900\x19\x97\xfb\xaann\xd8g\xfd\xe0\xa6\x13\x06\x1d\xc7\xe7n\x07\xf6y\x08L\x1b\xb4z\x9ce\x81\xaej\xa2\x11\x14\xd4Ku\x83\xd4\xdd\xfae\x0e0\xf9O\x08o\xd6\xd4\x1b\xe2w\x1em|\xbbQ\xe8\x1a`\xae\xa4\x95j\x01\x9f\x97\xa4\xb0d\x04\xf3\xac+\xa5\xb3\x0f\x0e\xa2\xc6\xdd\xc2\xdfx\xdf\xb5\x0b\xff\x02\xee\xbf6\xac\xfe8\xbbu&\xca\xceV\xf8A\x9a\xedt+\x12\xfeOXC\xae\xf9\xb3\xfa\xb4\x90\xc8\x9a\xf4! \x82C\xac=\xb2\x0c\xeaD\x94\xb2\x82a\xc5.\xfa\xefJ\xb6\xcd\xa0%\xb5\xb4\xf9\xa1\x1a\x9e\xf1\x93\xa3@H\xd4%m\xdc\x04\xa8\x9d\xb7\xab?\xb2e/\x8d\xff\xac;\xfe=\xf4\x11\xa9\x8d\xa0\xb9BP\x89\xef'\x1e\x98\xear\xc7\x86O\xa3\xa1\x18>qT\xa4\xb3\x0d\xcf\x89\xde2`<\x92\xd4\x9c\xae\xde\x8c\xa3\x996)\xa6]ed\xa2\x96\xd6\x8d\xa8\x85\xffT\x81{\xb9\xcb\x7fr\xc6\x8e\x95\xe6\xe7\x14\xf1>w\xaa\xd5\x9bu\xecoo\xeb\xcd\x87\xb1-+m\xeaW5\x98\xcb:\x07\x18\xcda\xa6\x89\xec\xa1\x11o[\x86'R\xdb\xae\xec\x0e\x82a\xd7\xd9\"\xfaj\x89\x85%\x98\xc8u\xad,\xa7\x0b\xf2R\x81\xd9H\xa6S\xc9\xe2\xaa(\xd4vd\xe3\xd8\x92\x93\xac\xffp\xbb\xf1\xdcm\x00\xebj\xff\xa2\xff\xf0\x92\xdbI\xad\xf6\xf3\x0d\x19X{\x0e\x0c\xe1\x8e\xa3\xea?\xcc\xf5\x86\xa5KB\xa9\xec\x81\xef\x19\xb3V\xf6\xb7q\xe3FT\xf6P7\xf5\xe1t\x98\xef\xfc\x99\xea\xac,]\x9bv<\xd6,\x10\x0c\xad\xa7\x17\xbcv\x04\xff\xdc\xb1c\xc7\xaac\xb7\xbb\xca`\xd9\x8ao\xd3%*\xfd\xa5\xea\x8d\x05m\xba\x1ayWI\xa8\x8f#?3\x15\x9f\xa2\x07+\x87\x06D\xf9\xb9\x1f\xc6\xe3\x1b5\x10\xc5C\xec3\xdb\x9c\x86\xcc\x8d:G\xa5\xc9\x8d\xc2\xca\xe1\xf9A\xdf]P\x8d\xb9g\xec\x96\xbe\xfdcy\xf9\xa1q\xe9!y\x00\xb1G\xcbhw\x90\xa8:\x88\xe3\x9c^#\xe7\xe3\xf6\x8b{\x92o(A\xc9wO J\xc8m%(\xd4Hy\xcd\xd8\x8b\x035\xa7\xe7\x81r\xcf\xd8\x84tW\x8f\xd6C\xad\x18\xc8\xfa\xa46\x87\x89\xbe\x9c\xab\x0bI\xe0\x1a\xb5\xa0\x96\xe7FF\xfaqLnn%\x99\x97\xb3\xbf*\xab\xbeP\xa0nK\xe4\xb6\xf5\xeeq\xdc\xbe\xe9I\xc4\xd6ep\xed\xf1!q\x01\xf4\xb3\xda\xdb\x19\xed#\x8a[\xc9bO\x90\xb3\xcbcu\x16\xf6\xfa\x15\xde\x8al\xb7\xb0D1\xd5\xdb\xa8\xfc=e\x1b~\xa7|\xcc\xf4\x0eVz\x1b#=\xc1F\x1f|JKa\xa0\xd7\xef\x8f\x00\xbf\x0d!\xae\xaa\xa8\xa6\xdd\xfer0\xc1\xf2\x8a\xd5 sA\x19\x8a\x00\xa3p&G}\xb0uH>\xcc\xad\x1e\xad\xd4\x94\x0d\xfd\xc8yF\xa7ed\xd2\xa3\xd2p\xab\xd9\xed\n\xba\x1e\xf8y\xb0nv{\xdd\xa8\x10\x8b\xd9\xfa\xb1\x10\xbcX\xac<-\xc9\x13\x98\xfeQ\x82L\x1fu\xf2\x04\x97\xf5\xb1\x84\x19Q\xa7\xd0\xf5z\xa8\x81\x93t\x01W'\x83\xd5\x8d\xe2y\xcd\x17\x9e\x1c\xedR14\xa5\xf8U\x0ce\xc2\xcfb\xfc\x1e\xeel\x01\xc7\xf8\xcb\xe7t\x01\xbb\xe3\x05,\xd7v\x99\xbbg\xc8\xe0\x84\xe1zS\x1d1\xb0\xca\x19#\x9e\xbe\xe57\xd1F-\xf5\x8e\xabw\xc15\xac\xe5v+\xf5\n^EW\xea5\xbc\x93\"\xa1`q\x10RT\xc8\xbbW&\x94\xe7\xd0nO\xd6\xe3\xca\xcc\x97\x17pZ18\xedV|\x89\xa1\\\x80\x91\x9e\xe4hMp\x1c\xe2\x93\x1bs%6\x96\x0b0P\xca\x05\x18\xf2\xf5\xac\xc9\x8a \x89\x8a I\x8a\x84\xc1\xc8\x98\x8e\x987\x151[\x1a\xa2?\x051[\xfaa\xb9\x00\xa3\\\x80\xb1\"M\xb0\\\x80!:Z\xd5\x98\x92\x00\x18r'D\xb9\x00C\x91r\x01F\xb9\x00c\xc5]\x13\xfeg|\x89xiIx\xe5\x02\x0c!9\xd3\xeb\xac\xa9u\xe5\x02\x8cr\x01\xc6\xe21\x7f\x9a\\\xb9\x00#> .\xfe\xebz\x93\xdf|\x89o\xee\x0b0Ry\xcb\x0c\xbf\xc2\x92\xb3\xcc\xceWFp\x95\x15\x17]q\xd1I).:\x94\xe2\xa2\x93\xaf\x17\x17]q\xd1\x15\x17]q\xd1\x15\x17\x9d\xf2\xff\xc5EW\\t\xc5EW\\tR\x8a\x8b\xae\xb8\xe8\x8a\x8b\xae\xb8\xe8\xa0\xb8\xe8~\xcf.\xbaD\n\xaa\x05\xe9\x14E8E\xee\xffI\xf7`\n\xc9\x94)*lQ\xe0\xf6\x18pk^,\xb8\xda\x0c`\xcd8\x0c\xa3\x8f\x91b\xd2\xc8L\xea\x03\xca&Y\xae\x93\xb8f\x08}Z\xad\xfb\xa1\x1a\xf4\x13\xbd0\x1c\xe3_\xa4=\xb0|\x1b\xa2=\xac9\x19!\xf8?\xc1\x8b\xcb\xcb7\x17/_\xdc\\\xbc{{\xfb\xe6\xe2\xed?\xdf^\xdf\xbc\xb89\xbf\xbdx{qs\xf1\xe2\xcd\xc5\xff<\x7fu\xfb\xfe\xed\xf5\xe5\xf9\xcb\x8b\xd7\x17\xe7\xafB_\xff\x97\xf3\xab\x8b\xd7\xf2\xf7\xeb\x9b\x17W7\x91\xef\x9e_]\xbd\xbb\x8az\xf3\xfa\xfd\xcb\x97\xe7\xd7\xd7\xa1\xef\xde\\\xfcv\xfe\xea\xf6\xdd\xfb\x9b\xc5\x0bb\xdb\xfa<\xa5\x9b\xdc^\x95\xb5_\xe09\xbc\x98\xd9\xdf\xfe\xdd\xf4\xf7sB8\xee\xac5\x02\xdd\xdd\xe5Q\x9f\xcc(l\x1c\x95\xdd0\xee\xf5\xd9hx\x89\x0c\xf4\x15\x85\xf0o\xbb(\x82\xfbb\x17\xb9/\xcb\x9c\xa5c\xd7n\xd4\xfb\xcfW\x15'\x06\xc4\xa2\xc0e3l9Q\xeeB\xa6\x91\xb3\xd0<\xd4\x07\xb6\x85\xf6\xc4\xb3@\xf6\x0c>U5\xa7\xd9\x93\xe1\xf0j\xbb\x94\xa2\x04\x8bB\xa7\xb2;H\xb1\x19#k*\xfa\xa0\xd1\x91\xcd\x8c\x81\x87j+\xf9\xc64eF\x8eE\x94\xb5\xd7s\x19\xc1gh\x1d9U07\xdd\xcfB!\xc5\xceF1\xa9L\xaf\xceJ\x96\n)\x16\x92\x06Eq\x1e\xd6\x8aI\xa9=g\xcb\x9d\xb5\xe5Y\xb5\xc1\xd7\x8b`_\xbdW\xf3\x05\xa8\xe2\xe8@XQ'rU\x87x~\x01\x8b6mo`\xf8\x9c\x84\xd8\xd80\xa4\x10\xac\x18R\xa2\xb70)l\x19\x84:\xdb\xa0G\x88\x8c4f\xff\xa1WK\x0c\xfb\x03\xb7\x95]{\x10s|T \xeb\xa4\x9aN\xddW\xf5\xaeY H\xfc\x980\xbe\xc3wS\xe3\x0cE\x9bMm\x0e\"\xcc\x9cX/\xac\xf3\xf8\x1a\xff\xbe\xa4\x07\x99\x17\x19\xdb\" t\xc4O[\xcb\x9d/\xe0\x1b+0W\xfdW\xe3\xec\xa7\xac \xf2\x1cx\x87iv\xcb\x0c9U,\x97\xd5Me\x05V\xc6:S\x7f%\x8f\xca\xcb\xb5N\x1cPym\xc7gle\xe1L\xd5\xa9\x9cG\xb9\xaf\xea=\xa3\xe6\x1d\xd6\xee5\xff\xf3\xf2#\xe3+O\xf6\x81\xf9F)\xadO\xcfG\x15\xd8U\x8b\xb3\xe3\x1c\x014\xb6a\xe6\x84\x06;\xe31\xb8\x8a\xbd\xb72\x1f\x83\xb2\xe0\xadg?\xfe4Z#\x85\xf8\x18\x85';>M\x1d\xcf'\xd5kjY\xef\xf7\"\x03\xf3;M\xdf\x92\x95q\xe9\x8a\xa0y\xaa+\xd4\xc9\xbd\x1b\xde\\\xd6\xef\x80\xb0\xb2an\x0f\x92*z8u\xf3\x94\x17\xea\xe4\xe6\x92\xc7F\xf0\x1d{\x0b;6\x90i\xa8\xa7\x1e\xfd\x84bE\xa9\xb7\xe1\x8e\x99w|I\\\xed\x94\xc1\x95Tw\xcb\xe4\xe5\x054\xfd7\x8ea\xe6\xd8MY\xdf\xb19.,/\xd0\x06\x93\xea\xcfW\xc2\xdbcs\x01I\xfa\"[\x0b\x96\xfb\x18\xfe\x89y\x87\xeb\xc3\xfc\x05\xc6\x11\xb2\x99\xa7Y\x1b\x19\xbd\xf8P\xe2\xc5c\xb5\x13\x19\xf8\xcfuU\x97\xd3\x9f\xb4\x84\xf1\xe9\xe7N\x8c\x11\xed\x9b\x07\xb9\xe2\x1a\xf6yX\xa6\x13C\x88\xcdpGQ\x18\xfb\x1bY\x8a<\xc8\x8c\xff\x94Y\xf7\xbd\xd8N^V\xbb\x89\xca\x0b\xff\xae)\xf9\xdf\xe3$\xe1\xaf\x8f\xea\xc6\x0e`ph\xfb\x01\x18\x0f\x8e\xe1q4gp1(\xee\xfa\xe3\xf0\x08\xf5\xbd>\x88\x1eX\xc7xtS\xd3\xc2\xa1\xed\xe4Nk\x11Z2\xb4C\x15\x1a\x83\x19A\x8d\xc1\xd5\xf3\xde\xe0\xff\x98y[d`\x95\x12\x0f\xa4\xd7_\xed(\xbe{\xbe\xe5J\xf4-\xf6\xb8T\xf4lx\x06\xf5\xd0\xcb\xa8\xb0\x1eN\x0d\x0e\xa2-\x06\xef|\xaa\x95ac\xff\x86X\xa4\xb0\x93\xb5\x0c\xb1\x9a\xe0\x90\xba\x81\xdd\xd5\xe5\xcbi J\x9c\xa2\x1f\xb7\xa2\x1d\xd36\xce\x9b\xb6\xc3\x079\x86\"\xad\xa9\x846\xc6\x1d\x0c?a\xa8\xcd\\\xb4M>y\xdd\x1e\xe6J\x91\xf7pt\xec\xc8\x97J\xf8K\xd5M=k\xbb\x17f\xd1F>\xb8t\xe4\x0c\xc1\x0c\xda\xb3\xe5\xb7\xe0k\xd7\x17\xd9fc\x99\xd1\xd7\x184$g\xb1+\xcb\x99\xc3N\x06\xaf:\xcb\x15\x81\x98)\xa1\\{\x01\xcc\xe7\xfa\xf2\x9eb\xe7\x8d\xbd\x83f\xd4\x03{t\xfd2M\xb2i|\xc5U:\x16i\xa1\xb0\x96,h\x8b\xf3\xa4\xe0:'x\xbc7\x9e\x93B\x16\xdc\xc5\x85\xbc\x84\xd6\xc0r\xfa\x8b\xc1_HE&\xff\xbf\x14\x02\x83 Da\x9cm\xa3\x90\x98\xf5H@\xb8\x82\x004&\xf4m\n\x8f }\x97FdB<\xeb\xda+9P\x19\x1f.\xb3\xfe{\xa8\xee\x7fC\xd9\xbfc\xf0\xac\x1b\x9b \xee\xc84t&\xb4\x98l\xf8Lh\x81\x89\x08M\xc8H\xca\x81\xd1\xb8Q\x1a\x97\xd9\xca\x8a\xd4\x90XM\xf4ZA\xf9\x95\xbd\x06\xda\x03\x93D\xe06!\xc8M\xb6jE\xe27\x1e\x00\xc2\xbdjEA;\xa4&[\x07z\x1c\x8b>\xd7\xa2w\xdb\x00\xfe\x0f\x00\xden\x00\x01\xb3\xac\xc2\x84\xac\x9a\x1cX\x91\x17-\xca\xd8\x98|\x98Q0j\xe4\xc7\x8d\x9c\xc8\x91\xb7\xf1\x9e\xc1\x9c\x17?\xb2#H4\x86dG\x91\x92q\xa4$$)\xda\x08[\xf1\xa4<\x88R\xb2ep\xe0J\xde\x91\x04\x90\x19[\xf2\xa2Kk\xaa\xe4\x98\xd9y1&;\xcad\xc7\x99\x92\x91\xa6\xe4\x0f\xef\xc0\x9b\xd6\xf4r\x0c\xe6\xe4D\x9d\x9c\x85\xbbQ\x9d\xfc\xd8\x93\x07}\xcaQ\xd7l\x18T R\x10\x8bC\x99HTq\xec\x17\xc7~q\xec\xffN\x1c\xfb!\xb0\xf1\xec\xcd7\xce\xb1\xe2w\x91\xd0\x81czl\xaf\xd0&\xbc\xf7\xba\xcf\x0e\xb1\xc0\xf1\x10\xa0\xdd\xa4\xe9p>O\xb7\x1b\xffQ b\xbcy{\x05\xe0\x0b0T\xdd\x8e\x85^6GO\xd6e7\x06#\x06xg\xb6\xe1\xfb\x0c\x83\x81\xe7\x97\x0b\x00\\\xd6\x89\xb2N\xfc\x1e\xd7 \xba\x97\\\x96\xd9\x0f\xfdj~-\x1d\xf3\x9d\xcdF\x00\xdak\xa9\xc4\x19i\xef\x82\x17\x0d/\xc2K\x19q\xe21\xddp\x1b\x8f\xc8\x03J\xaau\xf6b\xb8S \xebW\xd0o\x1b\xbdUW\x89-\xeb\x07\xb9L\xc8[\x9c$\xc9\xd9\xd0\x9a\xcb\x98\xf8\x1b]\xf2j\xd7\xce@\x92\x99\xcd\x7fs\x1c\xa0}@\x15\xe4\xa57C\xb1\x93\x9c\xa1\xe4\xa3:C\xc9Fx\x86b\xa5=C\x19\xe2\xc9\xcfPrQ\xa0\xa1\xb8\x89\xd0P\xa2\xe8\xd0P\xa2I\xd1\xe8\xbe{<\xca\x1b\xa8(j4\x94h\x824R\x1b:4,4i()di\xa4\xc2\xd3\x11*\xdeVKy\x11\xc4i\xa4\"+\x99\x1aJ\"\xa5\x9aT\x12@\xacF\xbe\x19L\xb6\x86\x92@\xb9\x86\x92@\xbcf\x9b\xe8\x96\xaaf\xa3dC\xc9K\xcc\x86\x92\x8d\x9e\x0d\xc5O\xd2\x86\x92\x8d\xaa\x0d\xc5F\xd8\x86\x92B\xdbF\xdb\n\x82\xca\x0de\x08!tC\x89\xa5u#\x95\xd9\xa8\xdeP\" \xdfP\xac\x80\x8cgKa=\xbb\xa2\x84\xec8\"\xe9\xe0hc*)\xe2\xf0\x1bi\xcf\xf8j\x93F\x10g\xa8\xe3\x84q\x04M\x1cJ\x06\xb28\x944\xca8C\x1d\xdf\xd1\x90\x9b\x87D\xfa8\xb3$\x83N\x0e%\x85T\x0e\xc5\xc9\xb6\x86b!\x98C\xf1\xd2\xcc\xa1\x10\x0cW\\\xc2)\xe7Plz\x0cN\xa1D\x12:\x94\xf0\xce\xf1\x11\xd2\xa1\xf8z\xc1KN\x87\xb2\x82\xa2\x0e\xc5\xd1;\x91tu(N\xd2:\x14;u\xdd\xf4w+\x81\x1d\x8a\xa3\xd3B\xc9\xecP|\x94v(\x1a\xb1\x1dJ\x02\xbd\x1dJ\x00\xc9\x1dJ8\xd5\x1d\x8a\x97\xf0\x0e\xc5\xd6\x89&\xf9\x1d\x8a\xf5y\x1f\x11\x1eJ\x1a\x1d\x1e\x8a\xa3\xca\xc6\xefI\x04y\x866\x8d0\x0f%\x856\xcf,\xc1\xa0\xd1CI\"\xd33\xab\xbc$\xd7C\xc9I\xb1\x87b%\xdaC1\xe8\xf6P\xf2\x90\xee\xa1d\xa3\xdeC\xc9K\xc0\x87\x12F\xc3\x87\xe2%\xe3C\x11\x0e\x1f\x1f%\xdf\xe2a'1\x1f\n1\xbd\x80\xa4qC %ssS\xf5 ]a\x84}\xe2a?m\x1f\n\xd1\xa0\x9c\x14~(ID~\x866\x83\xd8\x0f%\x1f\xbd\x9fRL\x16\x92?\x94\xd41\xe2%\xfc\x13\xea<\xb4\x7f(\xfa\xd2d\x8f:\x138)\x1dx\xc3\xc7\xc9\xe7\x81u\xa39@\xff\xbe\xe2\xc1&\x02d7m\xd3\xb0\xcd@9q\xa7\x90+\xf2\x9ac\x94\xe3|\x1d\xef,\x12\x8b]\x12\xf7\x0d\x8b\x90]\xfe\xa2\xbb\xc6\xba\xd68\xb7\xbaq\x05\xf0,\x0e\x8d\x10\x10\xf2\xe6r\xd8\x83\xff\x84\x0d\x01\x07W)\xb1\xce{\xab\xc2\xe5)\xd4\xb2\x0d\x8ct\xe2[\x959\x9c\xfb\x10\xeb\xe0\xb7j\xe3\x95\xf28\xf9!\x87\xa3\x1f\xe2\x9d\xfdV}U\x90\xc3\x1f\xd2\x9c\xfe\x10\xeb\xf8\xb7W[\xde\x92\xe2s\xfeC$\x00`U6\xdf\x9c\xe2\x06\x01 \x01\x08\xb0+\x14\xb7\xa98\xc0\x00\xc8 \x08\x80\x1f\x14\x80\\\xc0\x00$\x81\x03\xb0\x1e \x80\x1c \x01$\x00\x05\x0e\xfbD\x9e\x8ef\xc9\x0c\x18\xc0\x13\x81\x06\x90\x1f8\x80\x15\xe0\x01D\x03\x08N\x1b\xee\x06\x11 \nH\xb0\xaar\xdf\x0b3\xcb\n@\x01r\x83\n\xe0\x05\x16 \x15\\\x80\x0c\x19\x1f\x1e\xa0\x01V\xec\x92r\x02\x0e\xe0\x05\x1d \xb0fq\xe0\x03\xa9J\xae\x11n\x00\x02r\x82\x10\x90\x06D\x90\xfa\xc4Bo\xdf\xd8$\x00\x12\xa4>\xfa\x8e\x9bY\xd2\x81 \x08\xf3\xbf\x83\x0f\xa0\x80p\x90\x02\\^\xc7\x08\xb0\x02<\xfa,\x9e\x96\x0c\xc0\x05\xac\xee\xbc0\x00\x03\x02{(\x10\xc8\x80\x180\x03\xfc=\x97\x04j@\x18\xb0\x01\x01\xe0\x06\x04\x01\x1c\xe0\xef\xd4u@\x07\x04\x83\x1d`\x03< \x07\xe8\x01k\x80\x0f\x88\x00? \x1c\x00\x01O'\xdb\x80\x10\xf0\xbd\x17\x06\x88@&P\x04|\xd5\xb1\xcc\x8c(\x80\x84\xd4d\xb9Uh\x96\xac@ 8\xc0\x12H\x00LHe\xd4\x8dD\xb3$\x00'\xa4>\xfb\xd1\xd6\x03\xa8\x80\x1dT\x81\xcc\xc0\n$\x81+\xa4:\np\x81X\xd0\xc5e\xb7,>jX \xc6@8 \x03kA\x19X\x05\xcc\x80}z\x83\xc3\xf9\x0e+\x1c\xf0! \x0d\xac\x05j`\x0dX\x03\xf6F&\x806\x8e9D\xfd%\x01\xcc\xa1\xc7\xb6\x0d\xd0\x81hP\x87Ve\x03z\xe0 \xc0\x1e\xc84\xe6\x02A\x1f\x08\x06~\xc0\xb2\x9a\xbbi\x07R.l\xa7\xfb{\xa6V\xb1l\x90\xec\x97\xb8\xcf\xe2\xe4[(pK\x81[\xc8\x1dO\x81[\n\xdcR\xe0\x16EQ\x81[\n\xdcR\xe0\x96Y\n\xdc2I\x81[\n\xdcR\xe0\x16X\x8d\x18\x14\xb8e!\xeb:\xaf\xc0-\xaa\x14\xb8\xa5\xc0-\xb3\x14\xb8E\x91\x02\xb7\x14\xb8\xa5\xc0-V)p\x0b\xfdB\x81[\n\xdc\xf2M\xc3-\xd7\x13\xab\xb3\x86\xb8<\x90\xd4\xcf\x8e\xb3\xd1\xe5\xbe\xaa\x9b\x1b\xf6y\xb00<\x1f\xc7\xbf\xdf\x0e\xec\xb3\xc1\xd7\x08\xfe\x03\xbe\x073\x9a\x8av4\x02\x8d\xbf`\xd8\xae\x1bh\xbb\xad\xe5t<\x1eB\x85w\xd0\xea\xff\x9d\xfam\xf1Wd?\xdb\xb4\xcd}\xbd\xb3\xe4\x0eq\xbe\xb1\x97\xfc\x89\xa5u\xc7\xb7\xc4x\xa0\xf3\x87t\x8dqyC\x117\x12\xf9\xdc\x13\xd6F\xa9\xd9[\x98\x02\xc5\x9d\x0dK\x96fC]\xdd\xf3\xbb?\x96\xeb\xdc\x13SaS\xadZ\xcf\x8e-Y\xd1\x0d]&e\xb6\x87\x8e\x94d\x0b\x14U\x18WNVs\xdf^\xd5@\xdd\x0c\xac\xfb \xda\x0e6]\xdb\xf7?\x99#r9\x84\x95./|\xa3\x85o\xb4\xf0\x8dV\x7f\x14\xbe\xd1~\xd1Y\x0b>\xeaq\xb3(\xeevR_\xfdy~\x17\xc6\xae\xc4\x83\xe5\x99\x83/\xf3\x15\x1e\x84\xcf\xc5\xc24q\x1b\x17\xf6\xccI\n{fa\xcf,\xec\x99\xa6\x0c!\x11\x1d1\xd1\x1cv\x8c5 \x92#6\x8a\xa3\xb0gBa\xcf\x84\xf4\xe8\x8c\xa7\x88\xcc\xc8\x1c\x95\x11\x1a\x91\x11\x17\x8da\xed\xea\xc2\x9eY\xd83yO\x15\xf6LU\x12\xa2(\n{fa\xcf\xa4\x1eY\x15\x0d\xe1\xeb\x85\xc0(\x88\xd5\x11\x10\x85=\x13\x82#\x1c\n{&\x14\xf6\xcc\xc2\x9eY\xd83WF\x16\x14\xf6Lj\x82\xac\x8b\x14X\x15%\x10\x1c!P\xd83\x0b{\xa6\x13\xad,\xec\x99\xab\xdc\xea\x85=\x93\x92\xa1\xa4s\nIv\xf4C\xbc\xb3\xdf\xaa\xaf\xa4s\x96t\xce\x92\xce\x19\x0f\x12@\x02P\xe0\xb0O\xe4\xe9h\x96\xcc\x80\x01<\x11h\x00\xf9\x81\x03X\x01\x1e@4\x80\xe0\xb4\xe1%\x9d\x93\x90\x92\xce\x19\x0b8\x80\x17t\x80\xc0\x9a\xc5\x81\x0f\xa4\xaa\x92\xce\xe9\x05$H}%\x9d3\x00\xac\x80\x92\xceY\xd29\xfd\x00\x07\xf8;u\x1d\xd0\x01\xc1`\x07\x94tN)%\x9d\xb3\xa4s\x96tNB\xe2\xc1\x15R]I\xe7$_\x08\x00f\xa0\xa4s\xc6\x826\x8e9D\xfd%\x01\xcc\xa1\xc7vI\xe7L\x06} \x18\xf8\x81\xa8t\xce\xc2\x9eI\xfe\xbd\xc0-\x8a\x14\xb8\xa5\xc0-\xb3\x14\xb8\xa5\xc0-\x16)p\x8b\x94\x02\xb7\x14\xb8\xa5\xc0-\x81\xbb\xa4\x02\xb7LR\xe0\x16U\n\xdcR\xe0\x16B\n\xdcB=S\xe0\x96\x02\xb7\x14\xb8\xa5\xc0-K)p\xcb\xf2\xf7\x02\xb7\x14\xb8\x05\xa5\xc0-\x05n\xa1U>!\xdcR\xd83M)\xec\x99\x85=\x13\xfeS\xb0g\xd2\xb5xS\xf7\x1c5\x91{\xdeJ2\xe4=\x03Vm\x1e8\xa21\xd5\x05\xf7\xd2\xdc\x076\x01\xb3\xdf9\xca\xf7qw\x16\x06\xce\xc2\xc0Y\x188\x9f\x86\x81S|\xd2%\xf7\xa6\x8f\x0e\xd3\xca\xc4\xa9*\xf9\xd9\xa6E\xe1\xe4tPr^4\x9b\xf6P7\xbbW7\xd5\xee\xa6\xab\x9a\xfe\x9eu\xa2\x03\xd7\xd3r\x8a\xcf\xf2\xc4\xcc\x9c\xdb\xa1\xda\xdd\x0e\xed\xed\xd0U\xdb5\xcb\x91}\xb9\xe1\x8dooF}K\xe3\x8f3@\xac\xa2\xe3S\xb83\x9f\x02\x00\x0cM\x83\xe8\xc2\x8em\xe1\xbek \xe78~\xd0\x0d\xab?\xce\x18\x86\x1c\xce\x02\xa2\xefY\xa3o\x90\xf0\xa7,\x8d\xbd\xe6\xaa\xf4UUftKTe\xc3\x8d\x84h.\xe3\xff2[+\xea\xfd\xdd\xf27l[\x96\xba^\xc9\x8e\xd2jk\xed\xc0\x87j\xb4]f\xd0\x8c\x8c\xa4x\xc6\xed\xbc\xf9Uv\xf5G\xb6\xec\xfe\xf1\x9fu\xc7?\xba:T\xc9\xaa\x12\x93g\xae1Tb\xe4\x88\x07\xa6\xca\xde\xb1\xe1\x13c\x0d\x0c\x9f\x96\x8b\xd6\xa9g\xdd\x8c\xbaP%\xca \xaa\x14\x82\xfb \xdc=\xf0\x18\x8ei\xc0j\xc5\xe2\x06OmR\xfb\xa9\xea\xb6\xbd\xda'\xe3\xcbc-\xc4Oe\xb7Pv\x0be\xb7\xf0\x05w\x0b\x00\xb1T\xfa\x0e\xa6\xef\x90\x95>\x9c\xfb\xdb\xa5-\x90\x0d\xfc\xb2\xea\xaa\xc3\xfaM\xc6\x91\xbf\x16g\x89\xea\xcd\x07\xf3\x0cn=\xcc\xdb\x8f\xf2\x87\xba\xb9\xdd\xb3f7<\x98\xc7y\xa7?\xc5\x11*q\xa8>g\xd6i\xb3\x0coE7\xe0\x07\xd0\xc6UW\x1d\xd8\xc0\xbaqm\xd9\xf3\x81-VE\xf9\xf94]\xb2K\xd5\xdf\xc7\x0dZr\x17wlw\xcb>\xaf\xea\x8a\xdf\xd5W\x19'N\xf0\x07\x90\xcc\xf1\xe3KjO\xdf\xd5mrG?Y\x0b\xffR\xb7\xab\x1bxW\xb7\xbb\xae:>\xa8P`\xdbU\x9b}\xfa\x9cE\xc3x[o#\x9bI,\xbd\xe0\xdc\xbc\x02\\\xf3\"/^\xe9\xdb\xd7\x8bWr\xe3\x8am\x13u\x13k\xde\xa6\xda\xef\xc9\xc8\xbf\xa1\x85\x8f\xac\xab\xef\xf9\x0e\x85r\x8en\xabA\x0f\xe2\xac\xfa\x0f\xb7|\x05\xffr\xad~\xd1\x7fx\xc9\x0f\x0fZ\xab\xe7\x1d\x08\xb6\x9a\xaf\xf1\xe8\xc5\xab\xfa\x0f\xe6fl\x94\xb9\xbdT\xe3\x0e\xdc\xe5\xfbE\x1b\xf7[\xdd\x90\x8d;\xd4M}8\x1d\x00\x8fMj\x1b\xe7\x03#\xa1n\xd3\x1e\x8e{6X\xdd\xdd\xbc\xfd\"\x00\x16\xfa\xd3f\xc3\xfa\x9e\xa3\xcd\xda\xb3\xc7\x8e\x1d\xab\x8e\xdd\xee*\xcb-\x10O\xd1\x17\x97X\xe8/Uo\x9c&\x0f\xb2\x1bv\x95\xdc\xca\xf1\x1d\xd7\xf6\xc4\xc1G\x1a\xc9\xc0F\xf0\xb6R}\xd1\x0f\xe3\x8e\x89\x9a8\xda\xc3\xec3\xdb\x9c\x86/\xdc\x19\xe7Xh\xb6\xce\xc0F A\xf5\x86\xaf\x13\xee\x19\xbb\xc5\x92m}\xb0\xf4\xcaH1\xbc3\xcb\x97\xa2Sm\xb6\xaci\x0f\xf4\x9f<\x1fe\x14[KP<\xaf\xfb0\x94Q^\xb6\xf5\xbc\xc3\xae`h?0\x81\x98TXu\xb9\xdd\xae\x9a-\x0f\x00\xe5\x15\xb2E#\xbe}ws\xfe\x9c\x07F\x88\x8f\x8f\x11\x065\x8f\x1d\xbdh\x06a\xf6\xa6x]\x15\x80%\x15\n?\x1e\xf9\xb7 #\xec\xf9I\xa7\xee\x10\x18\xd8\xb5\xbb\x96\xa3\x9df\xd0\x82k\x1c\xbff\xec\xc5\x81\xb2p\xf30\xbegl\nT\xaf\x1e\xdd\x98\xde\xd0\xca\xe9h3q\xf6A\xac;M\xa5\xbc\xe3o\x04\xef-\xe6\x99\xa2\xe9\xe1\xa6Y\x9e\xe4O\xc2G\xa0\xac83\xb3`{\x0f\x15lX3t\"\xdbj\xa9\xa8\x9a\xb3\x14&\xcf\xd9\xdd#Tv\x96\xc3\xeax\xbc\xd5.1\x82\xb8m\x0d\x8f\x93\xae\x87\xc7\xdb\xad\x000W\x9a<\xb9\x1d\x15\x88\x93T\x07R\x1d\xdc\xf1\xa4\x05>\xe6\x95fr\xcc\x8d}>\xd6\x9dv$\x10\xfa^\x1c\x8f\xfcf\xa8\xc5W\xf2|\xa4\xeax\xc4\x9b\x9d\xbe\xd3\x94 %\x0b\xd7\xac\xa2F\x9cO\xa7#\n\x1c\xda\xediO\x1c\x88\x89c\xa7\xf3\xc4+\xce\xba\xa2\xf8\xc0S-\xfe\xb0\xfeX\x8b\xefE\x9dk\x072\x8d\xd1\xfa\xd9\xdd\xf606Q\x91X\xc7\xec\xe9\x891I\x89t\xf2aT\xca!u\x85\x935\xd1p\x88O/\x8cL*4R\xb1\xdc\xa9\x84Q \x84Qi\x83sz eJ\xa9d\xc1\x98\x14A%\x15P\xd3fI\x0c\x8cM\x07\x9c\xd2\xfe\xf4\xd6\x10\x91\x921\xa9\x7f\xf6\x14\xbf\xc4\xc4\xbe\xa0t\xbe\xf0\xb4\xbd\x84d\xbd\xd8\x14=[*^\xb6\x04\xbc\xbciw\xd9\x92\xed\xfc)vq\x89uDg\xda\xd2\xe9\xd6'\xd1y\x92\xe5\x86\x90\x14\xb9\xd8\xc48k\x02\\d\xda\x1b\x91\xecf](\xc3\xa0(c\x05\x8dLb\x9b\x93\xd5\xa8\xfe\xfd\xce_v\\\x9a\xda2%MQg&\xa7eHIKHD3G\xb9\xbe\x18&$\x9dY\x12\xccR\xd2\xca\x9c\xf9P\x96\x142o\xe2\x98\x99\x8b\x11\x9e$f\xbe\xfb7\xaa\xadQi`!\x8d\xf5\xa5|\xd9\xdb\xe6M\xefZ\x91\xd4E\xb692\x81\xcb\x99\xb6eO\xd6r\xa5h\x91\x9d\x10\x9a\x8e\xe5K\xc2\xd2R\xaf\x12\x12\xae\x02\xd2\xac\xc2\x93\xab\xbc)UD\x06\x92Q\x1c\xf1\x8c/U*-A\x8a\xac\x94\xf2KT\n\x94-\xdd)%\xc9\x89Hh\x8aMc\"S\x96\x12\x12\x95\x8c\xad\xb65\x15\xc9H@\xca\x93v\x14\x9fl\xa4%\x16E\xa5\x13YS\x87\xc2\x12\x86\xbciB\x81\xc9A!)AF\x8e\x8cYZh\x02\x86;\xe9'0\xd5' \xc1gQ\xe5\x84d\x1e#q'!]\x87J\xcd\x89K\xc8\xa1\x92o\xf2\xa5\xdc\xc4\x7f]oz\x8d/\xa9\x86\xb8\xb3\xfe\x9f\x16\x91,\x9a\x8b-\xc8\x85'\xf0\xe5\xab\xcb\x97B\x93\xd3\x93w\xc5\x8f\xaa\xc1\xbe;\x01\xcc)\xbe;\xf4[^\xe3\xef\xaa'\xbdRP\xbc\x05\xba7\xbf\x1b\xee\xf7[s\x96\x11U\xfa\xd5\xc8\xcb\xe1\x83\x17\xb3'd\x8e\x8eH+0\xdd\xd6\x16.\xb65\x85\xce\x19MJ\xc1\xac\x91\x8e\x06^\xf8\xf8\x8c@\xc6\x16)M\xf7U\xbdg[\xa3\x9b_\xf3\x9f\x97\xbd\x8c\x8f&\xf70\xf7y\xack\xec\xf9\xf8\n6\x0e=8\x06g\xdeX7\x99\xbf$^\xc2\x01\xb7l\xc2\x02\xfbE\xe7\x89k\xb4\x9e\xbdVz'`\xd0jM#\x9b\x95\xd2\xa4 \xb6\x11\x9fg\x9e\xa5cKq\x956\x10\x85iL4\xed\x80\xe3\x02{a:\x13k\x18\xb8\xbd7\xae\xd59\x19\xd0\x1d\xda\\ruG\xfc\x1c\"\xe6OhA\xf1\xf3F\xff\x1e\xd2*\xad\xfb \xbc0\"\x02A\xf9>\xfa\x1a\xf0\xa2y\x0c\xee\xfe\xc1\x800\xc8\x8e\xb1;?2\xc1\x164d\x91\x07\xae\x88\x87*hp\x82\xda\xb3\x07\x00\x13\xd1\xa0\xc4\x0cC(\xdat\x1f\xccj0\"\x11\x88\xe0\x1fy\xd9)\x0b\x10\"\x11\x80\xe0\xe7\xb0\x85vUy2\xf0`\x9c\x7f\xf2\xc1\x0c \x10CFx!\x12Z\xc8 +d\x81\x14\xf2\xc1 Y\xa0\x047\x8c\x10\x0f!\x90\xa0AV\xc0\x808<,\xedAV\xa0 \x02$\x08\xd9\x08\x90\xc0\x80}m\xca \x08\x0c\x13\x18@\x97\x97\x03\x04P\xc9T&\x00 \xd1\xf9\x9f\xee\xf8_,5y]\xfd\xb1n~\xab\xd7\x9bp\xef;]\xfbK_b\x98K\x7f\xf9\xce\xdf\xf4\xb6\xacv\xe3\xfb\x1a\xe3r\xdf\xd3\xf5w\xba\xed\x03]\xf6F\xbb\"\\\xf5V7=\xed\xa2\xb7\xb9\xe7\x8dF\x86\xb8\xe5].y\xc5\x1d\x1f\xe9\x8a\xf7\xb8\xe1\xc3\\\xf0N\xf7\xbb\xe6\xe5^\xa8\xd7\xfe\xe6r\xb7\xc7\xbb\xda\x8d\n\x88\xff\xcb\xe6^\xcf\xe8Z\xcf\xe6V\xcf\xe5R'\xdd\xe9\x0bWz\xba\x1b=\x8b\x0b=\x9f\xfb\xdc\xef:w\xba\xcd\x03\\\xe6>w\xf9\xc2\xef\xbc\xd4\x1e\xeaD\xb5\xbb\xc8\x03\xdc\xe3\x1e\xd7\xf8T\xbd\\.\xf1\x8c\xee\xf0<\xae\xf0\xfe=f\xd4\xffe\xdfn>\xac\xe7\x89\xbb\xe3\xaf=\xad'\x92\x97\x11\xc3u\xfa\x17|\xd1\xc3\xc2z\xeaY\x87e\xf0a\xd5\xe0\xf1\xafm\x18Q \x83\xd6*\xb4\x12[O%\x84z\x95\x10\x14\xa5cUo\xd2M8\x8a\xf5\x1d\xef\xae\xb8B\xbd:\xd2?%\xca\x9b;f\x8aJ\x1454\xf4\xdd\xeb^\x99\xfet\xd7\x1f\xab\x0d#H\xc0\x02\x0e\xac$)\x90\x83gW\x14\xe6\xa2\xff\x92\x15\x82\xba\xe9\xeb-\x9b9\xed\x0dm\xbc\xc5\x82F\xca\xf8\xe3\x1d#\xfa\xc0\xd5\xdb\xef{\xd6\xf1\xaf\xafW\xed\xbe\xda\x0c\x93\x0fs\x1a\xa5\xbc\xa7\xc50\x18\x7f\xdf\xd5\x1f5\xa2}1\x94\x96U\x1b\xeb,?@\xe1\x90-\x1c\xb2\x85C\xf6\x0br\xc8:\x98`\x97\x0bjH\xfa\x0c\xbe\xe1\xca\x9e\xa1\x97\xee+\xf5\xd7\xd5+\xf8B\xe7\xd3.\xe4\xfc\x92\x10=\xd3#d\x0d}\x89/\xeavT\xe8\x83\x89\x9f|n\xc9\xb2\xdcqb\xb0\xeeXu\xc3\xe3\xfa\xc2\xa9\x9bS\x14\x85\xc6J\xca\xb7\x0f|%\xa9\x9b\x8f\xed\xfe#\xce \x9a\xd9\xddR\xe1od \xad\xb7\xc6\x12:\x8eX\xfb\xfa\xa96\x08\xea\xde\\C\xb9GY\xf9\xd5\xb5R\\-\x95a=\x86\xee\xb4\xc14\x8aEa\xcb\x1d\xc8\x85J\x0c? \xf8\xb7aG\xfe\xde\xf7\x08\x8d}\xcf[\xd6U\xd3\x19\x94g\xdb\xec\xa1a\xc3\xa7\xb6\xfb\xd0\x97\x15\xb5\xac\xa8eE\xfd\xb6VTr\x9ds.\xac\xea\xdb?/^\xa7y\xe6\x8c\xf5U}'xE5\x969rh\xa7.m\xf4\xa2\xe6,*j\xd5\xa2\xca&\xd7'\xb2h\xcb\xe4\xa5&n\x96u\xc8\xb1\x02\xcdk\x0f=\xc6b\xd6\x9bL+\x8dm\xf8M'\xc8\xe0\xb1g\xf8J\\\x03\"\x8f\x7f\xc4\xf0\x8c\xf8\x8b\x8c\xf0\x86\xe8~\x10\xb2\x90\xc5\x87Mtt\xa8\x8e\x8d/<\xde\x03\\\x17\xba\xa3\xc8tZh\xee\n\xdaQ\x91\xd1E\xa19'\xa4[B\x0cm\xd9\x10\x9e<\xfcKW5k\xf2\xfe\xf3t\xfe\x85iE\xc8^\xe5K\xfbn\xac\xa2h%\x8f'\xaa\x9a\x8d\x1c\xf0\xf8\xb7\xc09\xf6\x82\x98L\xbc_\xfd%\x14\x9a\xd2\xb5\xd1\x9a\xd9b5\xad\x91\x9aC|\x9cf\xae(\xcdBS\x8aRhJ\xe5\xebY\xe31\x13\xa21s\xc7bf\x8b\xc4\xcc\x1b\x87\x99-\n\xd3\x1f\x83\x99-\x02\xb3\xd0\x94\x16\x9a\xd2\x948\xcaBS\x9a\x16/\x19\xc2\xdcYhJ\x15)4\xa5\x85\xa6t\x05#\xa8\xff\x19_\xcccZ\xc4c\xa1)\x15\x923\xca\xb1\xd0\x94r \x8bl\xf4\xc65\x06F5\x86\xc44\x16\x9a\xd2YW\xe6\x18\xc6|\x11\x8c\xf9\xe2\x17\xe3\xbf\xae7v\xd1\x17\xb9h\\\xd5{Su;\xc67\x86\xb3\xd7nr\x9f\xcdN\\\xe1]\x13oO\x0f\x14\x8fZ\xf1\xa8\x15\x8fZ\xf1\xa8\x15\x8fZ\xf1\xa8\x15\x8fZ\xf1\xa8A\xf1\xa8\x15\x8f\x9a\"\xc5\xa3VZ\x8d>\xfde\xfcU\x1f\xeb\xe3Oi\xbd\xcau\x18\xb9a\xf4\x18\x02\xeb8\x02\xa5\xd3\xb9\xefY\x89\xb3\x97\x93O\xca\xd7\xec\xe5\xb9.\xc6s8\xfb\x97\xab\xbf G\x85m5T\x18\xb8\xbf\xe8\xec\x10sr\xf6\xcb\xfc5\x03\x8c\x8a\xf99\"\xa6\xb3\xf3\x13P\xddOu\xbd%A\x93\x8eL\x0e\xedn\x1c\xc4u\xbf\xe8I\xfd\xca\"\xa6\xda\xef5\xa6\x9b\xe78\x04w\xb5f\xb9\x1c\xad[cG\xbed\xf7N6C\xadg`\xe7N\xae7\xa1\x84\xea_\x9e\xeb\xc4?\xd9\xb4$\xaf\xcf \xe6\x0b\xf2\x13'\x03\x7f\xd1\x1c\xd7\xd8\xd8\x7fC\x91\x1e\xa9\x8fbd\x04\xa08\xda\x91\x92\x1d\xa0\x96i\xe1\x844\xbe\x028\xbe\x84|\x8db{\x06w3\xc0\xeb\xadE\xc9\x88z\xa2\xb8\xd8\x9f!+\x02\x8a\x92\x0d\x07E\xb1\xa2\xa1(\x94\xbb \x10\x13E\xc9\x85\x8c\xa2\xf8X\xa1!\x16%E\x89\xc6J\xe9\xbe\x9b\xee+\x03\x9a!\x1aRpSR\xdbt\x87\x19\x90L\xd1\x90\x88\xa1\x92\n\xc9{\xcdf\x89\xc1SIE\x0e&iHGZ\xa5\x92\x00\xbc\x95|3\x18\x83EI@bQ\x12\xf0X\xdbD\xb7T5\x1bR\x8b\x92\x17\xafE\xc9\x86\xda\xa2\xf8\xb1[\x94l\x08.\x8a\x9d\x99\x1a\x12\xd1\\\xdaV\x90\x0c\xd5\x00\x818/J,\xdaK*\xb3!\xc0(\x9180\n\xc9Z\x0d\xfe-\x85\x83\xbd\x1a\x02w\x1c\x91(1mL\xadL\xd6\x10P\x9b4\xdc\xd8P7\xdf\x1d\xa7\xb3ZC\x1e\x0c\x19%\x0dI6\xd4\x0d\xda\xcdr\xb3$\xa2\xcafI\x04\xd35$b\xcd(\x1e\xd2gp\xb1^C\x08\xfa\x8cBR\xe7\xaeB\xa2Qlz\x08:\xd2$l\x1a%\xbcs|85\x8a\xaf\x17\xbc\x985\xca\n\xe4\x1a\xc5\xd1;\x91(6\x8a\x87-\x1b<\x8c\xd9\xe0e\xcd\x06w\xa7\x85b\xdc(>\xa4\x1b\xc5`\xd1\x864\xd4\x1b%\x00\xfbF G\xc0Q\xbc88\x8a\xad\x13)vmp=\xef\xc3\xc7Q\xd2Pr\x14G\x95\x8d\xdf\x93psC\x9b\xc1\xc2\x0d\x89h\xbaY\x02\xc1\xcc\x0d\xa9\x18\xbbYe\x9d\xad\x1b2#\xef(\x0e\xd6n\xa0\x99\xbb!\x1b\x16\x8f\x92\x0d\x91G\xc9\x8b\xcb\xa3\x84\xa1\xf3(^\x8c\x1e%\x10\xa9_<\xeca\xf5\x06zz\x81\x85\xed\x19V`\xbc>\x86o\x08\xc7\xf1\xc5\xc3~4\x1f\x85hPNd\x1f% \xdf7\xb4\x11,\xe0\x90\x15\xf5W\x8a\xc9\x82\xfd\xa3\xa4\x8e\x11o\x1c\x80P\xe7e\x06\x07beK\xc9\xb5A!2n\x84\xea\xe2\x9f\x86\xe2\x9f.\xfe\xe9\xe2\x9f.\xfeiC\x8a\x7f\xba\xf8\xa7u)\xfe\xe9\xe2\x9f.\xfeiCQ\xf1O\x1b\x12\xee\x82-\xfei\xea\x91\xe2\x9f.\xfe\xe9\xe2\x9f\xd6\xa5\xf8\xa7\x8b\x7fZJ\xf1OC\xf1O\x17\xfft\xf1O\xfb\xc7\xc8\x97\xf0O\x13\x87\x99\x98\xfc5C\xc92\x9f\x8d0\xbbjZ\x1bJdr\x1b\x94+\x86\xca\x15C\xe5\x8a\xa1/{\xc5\x10\xcc\x9fu\x9e{\xe8kf\xdc\xff\xa1\xfc*o\xe8\x93\x1d\xf3\x9d\xf2\xf2\xf2v\"K\xce\x0d\x04\xdfO\xa4)Pn(r\xa5\xfa\\c\xf2\xe7\xea\x14\x1f\x914\x1aer\xac\xa9; \x13,$CG&\xba\xb2\xcfu?\xa8p\xc0S\xa6B\xcaB\xc7-\xa6\xd8p\xcb\x1a*\xef\x1f\xab\x8e5C\xce\x9c\xcc\x1f$\xc8\xf2\xa3\xd27X\x8c\xac\x93\xf2\xda\xb8\x0f\x0c\xfc\x16B\xff[\x05\xaf\x0bk\xa3j]V\x15\xa54\xe5\xd5\xacC+\\\x9f\x9ab`k\xc9\x9dSRg_7\xbb\xbd2XT-B\x035?\xec\xd3\x11'\xa1,u\xd5\xe4[\x9f`'j\xfb\xbbM\xb1K\x9a\xad\xe6|uM\x14\xd7TI\x9d\xb5\xd6y\x9b\\\xa1u\xb3\x97\x9a\xbf!\xe9\x83\xeb\xe7\xb0c\x16\x87\x14\xb8n&\xe7\x98\xcbe\x7f\\\xf6\xc7e\x7f\xfcE\xf7\xc7\xc4\xf2\x19\xb0\x9d]\xac\x9f\xc1\xbbW\xf1\xcb\xfa\x05T\xbc\x18e\x122n[\xe7\x85\x87{\x89\xb4(1\xc2\x00\xaf\xdf\xa8\xfdz:T\xcdO\x1d\xab\xb6|\xb6\xa8qV97i\xef\xe4\xc5\x88[\xdd\xb0\xd7=U\xd0\xd0\xb1\xaa?u\xa1v\xd5f'\xae\x96\xf7\x0eJ\xadPm\xf8\xcc\x17\xdd\xca#t\xdaM\xcd\xc7:w\xf6\x12t\xd8f\x1d\xdbO\xcdZ\xfe\x19kF~\xfb\xa9\xb1~T\xf2b\xf3\x95%M\xab\x9fP\xa6\xab\xaf\xdb\xe6v\xa8\x83\x07\x8f\x1c\xba\xdbj`?\x8d\xefQU\x18\xe4M\xb3\xdc\xc3X;\x07\xd6\xecI\xbf\xbdg\xecvh?\xb0\xa6\xa7*\xb3\x8a\x0dfu \xe8\x965\xed\xc1\xfc\xd9\xb9y\x01\xa8\x0e\xe3`Z\xf9\x9a/p\xe2e[+n\x03\xe0=\"\x90\x08\xac\xa6t\"T\xcd\x96\x87U\xf0JP\xd8\xff\xdbw7\xe7\xcf9\x8c\x82\xcf\x08\xac\xa2\xe6\xde\x88\x8bf\x10\xbb\xea\xc9q\xa9\xba\x8a\x0de\xc2\xea\x1a\xbf\xf7\xf5\xae\xa9\x86S\xc7z\xbe$\xd5\x1dBj\xbbv\xd7r\x7f\xedY\xd0|}S\xf7<\xfc\xf0\x9e1\xd1b\xde\xd4\x1e\x1b.\xe9\x15\x0fuS\x1fN\x07\xd8U=\x1c\xbbz3v\x10\xc6\xa1i\xea\xc4\xa9\x81b\x1d\xd7\x87\xa0\xdcKN\xf3d\x8aX\xd9\xef\xb5\x0d\xe5+\xbe\xde,U,V5m\xd9q:i\xe4\xca&\xcb\x0d_\xd5\"\xce\x85\xf2\xcd\xa7=\x18f?\x0f\xae^\x06cO<\xeb\x16\xc3\xc4\xd3\xce\xda%\xd1\xb6(\x86\x94E\xd8\x97|K#\xb98\x92\xcbcHU\xa3\x96H\xcb\"\x19Q\x9ec\xa1t.\x95A\x83\x9c^.\xa3\x16\xcc\xa0%\xd3\xbehZ\x96M\xe7\xc2\xe9^:\x1d\x8b\xa7g\xf9t-\xa0\x9eW}\x8bh\xcee4\xf3Bj_J\xd7.\xa6\xaeY\x9eyAu-\xa9\xa4\x19H\\V\x8b\x7f\xa6\xf8g\x8a\x7f\xe6k\xf8g\x96\xf0\xa3\xb1\xe7\\\xb3\xa7\xe5\xee\x1a\xa1\xcd\xbf\xbd}\xdf\xb3\xae\x90\x0b\xce\x12\x02\x86\x14r\xc1\x92\xbcY\x927)m%y\xb3$o\x96\xe4M(\xc9\x9bK)\xc9\x9b%y\xb3$ozkS\x927\xa1$oBI\xde,\xc9\x9b%y\xb3$o\x1aR\x927K\xf2\xa6\x94\x92\xbc %y\xb3$o\x96\xe4M\xff\x18\xf9\x12\xc9\x9b\x85\\\xb0\xf8\xa7\xc9?\x17\xfft\xf1O\x17\xfft\xf1O\x17\xff4!\xc5?]\xfc\xd3\xfe\x1dG\xf1O\x17\xff\xf4B\x8a\x7fZH\xf1O\x17\xfft\xf1OG9{\xc9\x9f\x8b\x7fZ\xff\xb1\xf8\xa7\x8b\x7f\xba\xf8\xa7M \xf5=\x16\xfft\xf1O\xfb\xc6\xc8\x97\xf0O\x17r\xc1\x92\x9cS\x92sJr\x8e\x90\xd0\xe4\x1c\x98?k\x12\xb9\xe0?-\xb2{\xe8\x94\x1bg\x8a\x8f\xfa\xfa\xcf\xcb\xf7e\x7f\x85q\xb4\x8c\xefrn\xc2\xdf\xc6/\xda\xadO\xf89\xe0{Q\x19?\x8b\xf9T\x8cY1f\xc5\x98}AcFf\x1a\xda\xec\xc1:k\xa4jXk\x88V[ \xbe#\x8a\xb2\x19\xd6D\xc2\x84\x19r\xf1\xca\x97/X\xf7Xe\x93;QP\xe3=9\xd1\xa8d\x13\xb4U\xac\xee\x11ZP\x14f\xac\x92\x9bND\xdd\xdfBnJ-\xbe\x8d\xd6Kx\x1aR-\xbd\x94#\xeb\x0eu\xdf/yA\xc1\xb2^\x82\x9bW\xc9^%\xc3>_\xce\xc5bw\xcb5eJ\x13m'.\x80\xb1wz8V\xdd [\xa1)[\xb6I~N9q\xf5\xc3\xcb\xf8S{\x8fZ\xbf\x03\xaf\xc1 \xb24\xba\x8dY\x9d\xda\xcc\xdfZ\xbf\xcb\xe1\xad\x89\xdb\xe4|\x03i\xcd)6\xc9n\x95\\F \x9eF5\xc26=)\xe5l\x88\x8dz\x02\xbe#\xd2R=%\xe3\x91Y\x96\xd5b\xd9m\x96\x87\xd6\xc6U9\xc2#\x93\xd5v\xe9\xd6+\xc2~\x953J9\xa3\x943\xca7tF ;\x9d\xe8{\x86\xf5|(\x8a!Z\xbds \xad\xe8\x8a\xed\xc3b\nl\xd9P\xd5\xfb8E\xdf\xc2>\xc4\xe4R\x19\xbf\x91\xb2\xc6\xcf\xbdE/\xf4O\xb6\x1717 +k6.\x13F\x9d\xe6\x15f\xb9\xb8\xf0\xd5}\xd6H6eu\xa0;U\x03p\x7f4\xd0*\xa9\xb6\x99\xa9M\x16\xf6\xcdx}~\xc4^2\xb5M\x00\xfbV\x01\x82\xab\xac\xee\x0fz\xcc6\x90[\x81\xc5K\x9a\x83`\xa1\xc3\xba\xf2\xe7\xfe:\\+1n\xc13v\xc13~\x01\x88M\xab\x18\xca\xe6\x9e\x0e\xbe\xd1of\xd9\x9b\xcdO\xbf\xe2\x96O\xbbc\x00\xad\xa1\xc2a\xa7}4\xeb\xea\xb10\xe8\xb8$\xae\xf2o\xa9\xadp.!\xd7\xeaE<\x01\xab\x05i{\xc9\x9e\xb5\xd8[\xbb\xa5\x0d\xbb\xc2\xc3,W\x1f\x96\xf4`\xb4\x0dA\xff\xc5\x15\xc4%\x1d\x11\x05\x87_\xc9\xb1<\xaa\x91}+t\xae\xbb\x80\x83<\x9a\xb9\xd4\x87_\xb7!^\x88\xbeh\x83\x1c\x99\xe2\x7f\x82\x87f\xe2\x88\\E\"\x1c\xfe\x8d\xc2)\x83W\x7f\x9f5\x04\xc1&5\xb0Ks\x02\xf7\xaf^\xb0\xc6\xf2\xeb*u5\xb3\xaf\xc1\xe9\xbbB\xbb\x85\xc7\xd7\xc2\xe0\xeb\x1cO&k\xaf(r\x08\xe4\xeb\xf50\xf5>\xc5\x1e\x9a\xe4\xe2\xb5\xae\x904\xff\xae\xe5q\xd7\xe1?\x9amWU\x92B\xb3;\xaf\x86\xb3\x84\xb3\xe9R\x07\xf8\x8c\x0c\xba4w\xeeb\xb0HK;\x8d\xde5|\xb9\x94\x99\x9dN\x9d\xc1v6\xdb\x16 \xd2\xe9K\x1d\xb1r-\xc8+\x9d\xbb\x89U\x08w\xe2fYo\x0c\x97m\xde\x15g\x11\xf8\x95\xd3\xa9@\xee\xcd\xd7\xfb[\x95\n*G\xca\x10\xcf\xaa\x987\xc7\xb6\x1f\xf8\x9cy1\x0c\xd5\xe6a4-_|\xd2,LO\xc8&z\xac\xb4\x9a\xe6>Z\xc9\xa9\xfa\x8a\xae)\x17Y5=\x9b\xb6i\xd8f\xec\xd9\xc9]=\xeaKm\x84\xb2\x01v\xd5N\xc9\x8f\x9e*\x92g\xe2]\xdcO\x83\xc2\xe8\x0c\x9e\x87\xac.v\xe4\xcaJ\xaf\xab\x03\x99\xcao]V\xdd\xe9k\x19\x13\xf7\xed)\xfb\xf9\x92\xf5\xb3\xa5\xe9[\x13\xf4\x87\xf8\xd4\xfc\\I\xf9\xeet\xfc\xa8D\xfc\xe8\x14|\xde^\x1dE\xb2&\xdfG\xa7\xdd\xe3\xdc\xd4\xb4Y\x12\xeeSR\xedyZ\xbd\xde\x1a\"\x93#&\xbd\xde\x9eJ\x9f\x98D\x1f\x94>\x1f\x9e*\x9f\x90$\x9f\x90\x1eO\x18\x8c\x8cI\xf0y\xd3\xdf\xb3%\xbe\xfbS\xde\xb3%\xbb\xdb\xd2\xdcS\x12\xdc\xc9d\xf6!$\x8d=6\x81\xdd\x9a\xac\x1e\x99\xa6N$\xa8[\x17\xca0\xa0\xd9XA#\x13\xd1\xe7\xa4s\xaa\x7f\xbf\xf3\x97\x9d\x96v\x8ei\xe6\x8a:3\xe1X\xb5C'C\xc3\xdb\xae\xde\xd5\xe3\xf6\x9aw\xa4\x1c\xedJ\xa9B\xcbdn\xb7\xb7\xfc\xb0\x15\xd5\xc7\xc1\xde\x18\xfe8=\x8cnD4\xc8T!\xfd1\xfb(f\xcd\xc9H\x0e\x01\xf8 .\xdf]\xdf\xdc^\x9d\xbf>\xbf:\x7f\xfb\xf2\xfc\xf6\xe6_/\xcfo\xdf\xbf\xbd\xbe<\x7fy\xf1\xfa\xe2\xfcU\xe0\x1bW\xe7\x97o\xfe5\xf0\xd9\xff\xfe\xfe\xdd\xcdy\xe0\xb3W\xe7\xe3\xaf\xda\xc3\x02\xc6}\xbe\xb2\xeen\x06\x8b\x80\xbex\x0eo[e\xe9\xb5\x85\x14\xb9;\xe99\x86\xe1\xcej\x16+p\xc7\x8e\xfbG B\xcd\x17e,\x0eW\x9eRx\xf7\xbaK\xf9\xdf\xa7v\x98\xa3\x8a\xa2J\xc1\x0f\xe3m\x8c2\xaf\x1c\xe5\x1c\xf5\x00t\x14\xc7h\x0er\xf2M\xf3|\x9e\xbfd\xd9\x1c\xf9\xcb\\8E-#J2j\xa5\x9b\xf4?\xf5\xdc\xa8\xcb\x80\xed)\x8a_Wx\xc2X\xcf=q+\xd7\x94\xba76C&=\x93\xb3Oz\xa0\xda~\xb8\x9a*d_\xaa\xf8\x175\xcd\x8f4\xe5\xb0\xaf\xc7%I.\x14\xca\xd0\xe8\xe1\x07V\xf3\xf8\xc4j\x1a\xe8\xcf\xa6!\xd2\xe1\x98\xfcq2\xb8\xc7\xfd\xe3m\xcf\x86\xa1nv\xa6G\xe2\x8a\xcf\x12\xf9g\xecO\xda\x05\xa1}?\xdd\x08\xfe\x04|N\xde^\x9f\xdf\xdc\\\xbc\xfd\xc5b<\xf4\xa7\xce\xff\xe5\xfc\xea_\xdf\xbd=w<\xf2\xfa\xdd\x9b7\xef\xfe\xc7\xf9\xd5\xb5\xe3\x99\xdf\xde\xdf\xbc\x7f\xf1\xc6\xf5\xc0\xf9\xdb\x9b\x8bwog\x1d\x93\xe1\xf3\xd7\xdan\xec\x1cm\x16\x06N\xe9\\\xda\xc8\xd9:\xe49\x9c\x7fd\xddc\xdb\xb0 \xa2\xe7!\xb4C\xab\x1a6\xfdK\xb9\xba\xef9\xbck\xf6\x8f\"\xd6\x9buSD!\xee/\x12K\xc1\x0f \x8aP\xb4\x1eN\xc3\x89\xa7\x03\xc8B\x13\x8b\x11\x9fQ\x14td\xedq\xcf\xa4\x0b\x80\x07^\x8b\xd9/t\xd1\xc5\x89\x12\xa6d\xd6m5\xf8\xd2\xc7\xbc\xc9\xac/e\"\xeb\xf8\x04\xb1\x01\xe3A+l[\x0fl\x9b\xa5\xbf#\xb95aiNc\xf85'\x05\x06L\x15\x96\x84\xd8\x0f\x01\xe8\xd75B3\xe3\xd3\xeb\xb3\x0d\x8fOO\xf6\xfety\x869P3;n&\xab\x17\x9f~\x97\x8e\x9e\xd9\x93\x02\xa3;\xcd\x87\xa29p4g\xd9\xe6\x84\x0d\xc1\xd2(4me1\x0eD\xcd\x86\xa9\x91\xb5]\x81\xaaE\x1f8\xed\xd8\x9a\xdb\xe7\xe8\xf0:z\xfd\x8e~\xcf\xa3\xc7\xf7\xe8\xddU\xa3x\xf7\xd6(~\x8f\\\x94O\xce\xa1\xcdr\xdf\xeb,\x0e?\xe4\x1f\xa1\xedV\x8f\xa4\x13\x05\x08ly>$ \x13\x160\xa9\x89C\xe1\\8\\\x99\xa3\x8a\xe4\x1f\xa7e\x8e\xda\xfe\x9c\xd8\xf2ow\x8e\xc6 v6\xcc\xae\xccNE\xf2\x8eP\xcb\xad\xd5\xb3\xfc\x81g\xa7\xf5\xce7\x14\x07x\x16\xd8\xf2\x90&\xc5\xc0~.\x8bC\x03\x82A\x90\xe0\xbaV\xc5\xc1\x82\xf3a%\x1a\x18\x9cT\xac\x82\x06)p\xd0eW\x9c\x14i\xae\xf3K\"HH\xc3\x84!\x05;\xa1B\x0fX\x98|\xf6L\x86\x0c}\xa0a\xf4\xb7\xb2\xd8~\xb7\xdd\xe7\xaf\xba\x86o\x08\x80\x180\x9f\xec b\x00D\xb6\xea=;\x90\xb8\x1eJ\\\x0d&&\xc1\x89>\x9f\xb7\x14o\x7f\xad\x83\x14\xbf$\xa8\xf8%a\xc5/\x06,:\xa1\xc5\x80\xb9\x11\xb0o0\xdcq>\x80\xd1\x0d1f\xad\x94u\xd5\xcf\x085\xae\x00\x1b\xd7\xc2\x8d\x0b\x0fy\"\xe0\xe8\xea\x93x\x14\xd2Pe\xa0\x92n\\r\xaaU(2\xe9\x1c\x1e\xb6+J\xc3P=\xeaY\x0bB\x19\x8eQ\x06\xa2\x94\x818\xe5j\xa4\xd2o\xb73\xa1\x95O\x84W~I\xc4\xf2\x8bb\x96_\x00\xb5t\xe2\x96A\x9bM\x1a;\x9c\xe6l\x08z\xe9\xc3/s\xd4c=\x8aI\xe2\x98!\xfb{;\x96\xb9\xb0\xd5qhf\xc9\xb1-9\xb6%\xc7\xf6k\xe4\xd8.Y\x8d)\xc8?$\xa2@}O\xe8\x0b\xe65\x96l\xfe%\xce\xa0\xc4\x19\x84tZ\x893\xa0\xd5\x948\x03\xdb\x1f\x03\x0e\xd6\xe0\x1b|\xb3\xf8\x0e\xd8\x90\x1d)(\x18\xe6\x7fJ\x0c\xb3\xc4\x19\x98\xf2M\x8f\xd32Gm\x7fNl\xf9\xb7;GK\x9c\x81*\xdf\xec\x08-q\x06%\xce`\x965\xad*q\x06\xba\xae\xc9\x16\x978\x83\x12g\x80\x0f\xfb\xe6S\x893\x08i\x93\x0f\xafB\xf1\xf6W\x893p\x95U\xe2\x0c\xf2V\xaa\xc4\x19\x98\xbaJ\x9cA\x893P\xa4\xc4\x19\xd8\xcb*q\x06%\xce`YT\x893(q\x06%\xce@Q\xf6\x87\x8c3\xa00\xffp&\xef\xc5\xeb\xb2\xb1NB\x03\xbe\xf9\xb9\xc6%\x16\x87\xa91<\xd5\xad\x8d\x7fC\xe3\xd9\xc6\xf86/\xce-\x8bs\xa3\x12\xb8=\xa1\x07g\xe2V$\xeb\x06\xe4\xe9\xb7\x1d_`\xb3\xf1\x84[\x0cu\xdb.F\xee\xf2\\rl\xfb\xbe\x1e_\xeb\x96;{~c\x898\xa9l\xaa\x86_\xd2IL \x81\x80\xa8\xb3\xc1\x19i\xa3\x01\x04\xa4y\xb7\x98vy\x80]\xef\xd76q\xb5\x85\xa7\xfe\x0bVBq\xa1/\x00-\xb2\n)\x80U$@\xa5\x7f\xde\xf7\xd2\x03\xfe\xcd~Z\x03\x94\xf9\x1a\x9fVCG\x16\xb8\x81\xeb\xd3\xc6\x00\x1a\xf3\x1e\x8d\x84)\\\xc5\x85\xc2\x10\x11\xb0\x831pz\xd6\xbdh\xfaOr\xf3\x1e2~\xa8\x08\xb9\x88\x0f\xb8\xd8\xf7]O!q[K\xdc\x99\x0e?(W\xe2/vl\xd3\x1e\x8e\xf5~\xac\x97\x80\x8a\xef\xea\xa6\xea\x1e\xa1\x12\xcb\xf2R\xc6\x1e\x11G\xd8\xe1\x81\x91(\x1f\xfb<\x1a|\xa8\xf9D>\xf5L\xde\x84;~z\x11J\xff\xa2y<\x83_\xdbO\xec#\xeb\xf0b\xdc\xf7Wo(p\x11\xed\x80\xb8\xa0\x97*\xac\xdf<\xb0\x03\x83\xbf>\x0c\xc3\xf1\xaf\xcf\xf0\xbf\xfd_\x9fA\xdbA\xd3\x8a\xbf>\xe3#j\\M\xe4.\x1d\x8f\xe3\x84\xba\xd3q<\xc5\x91\xb7\xef\xf29\xf0\x91_\x03\\\x0dp\xa8\x8e=\x0e\x8f\xb1\xe6cK\xa5\x1f\x8f;$k\\r\xab^x-\xfa\xe7\xe4\x97\xf9;\xb8\xb8\x9f\xeb9~Ny\x9f\xf2\xd4\x14a\xf7N\x07\xb6%/\x07\xff;x\xd1\xc0\xaf77\x97\xf0\xcb\xf9\x0d\xb4\xcdt\xe0\xe1\xd3\x0d\xaf\x13\xae\xccKFo\x1e\x8f\xec\xdf\xfe\xd7\xbf\x11\nAzW\x1b9\x12\xd0n\xf2>=v\xed\xf6\xb4\x19\xf7\x8b\xc0\xba\xae\xed\xa8\x9b\xa3\xff\x0e^\x1c\x8f\xfbzS\x89>\xe8\xd88\x96\xdaO\xb8\xfb\xdeT\x9bq.\xb7\xed\x87\xd3qrb\xe2J\xdc\x9a7\xff\x83\xc5\x1c\x01^\xa9\xdcv|;3>tP\xc6\xf2\x16\x07s%\x1b0\xfe\xfbc[o\xa1\"\xae\xfc\x07~\x02\x19\xab\xc3\xa7k\xc7\xee\xdb\x8e=\x93\xaf\x8e\x1a\xab\xa1\xbe\xab\xf7\xf5\xf0\x08\x0dc[\xe9.\xe6f\xa5\xfbh \xdch\x9b\xd1|5;\xc6\x1f\xe7\xb3\xe6\x0c~x\xdf3\xf8\xc8\xba\x1e\x9dM\x83\xbc_\x1a\xc7O\xd5T;\xba\xadw\x1d\xab>p\xff\x12\xaa<\xfb\x91\x1a o\xdb\x81=\xc7\xb3\xc6\xfd\xa9\xd9\xe0H\x1fk-\xac\xc4\xe6\xd4u\x1cUP\xbd\xf1\x8d\xa5\x83[\x0eB\x98nx\x90\xd6\xfe\xeet?\x1e\xf0X\xd5\xb3g\xfc\xee\xdez\x90\x05\xf1\x0d\x1b\xf7\x0bO\xf3\xe3\x8e\xed\xea\xa6\xa1\xc3\x19\xc6%\x964\xce\xe6\x15\xb6\xb4}\xbb\xe6\xb3\xa7G\x08`\x9c\x9e\x8dn\x0f\xe0\x07\x91\x0e\x87\x18\nN\xb7\x1f\xe1P\xef\x1e(+pGN\x7f\xde,\x1e\xbeP\x1f\x8e{v\x98\xae\x1b\x16~\xd8\x0d\xf4\xecP5C\xbd\xe9\xf5iA\xec\x15\xc0\xb7\xc4[\xb1)\x08Z\xff\x7f\x1b\xa7\xff\x1d\x83j,\xbc\xde*\x0b\xb8\xb1Z\xcb3\xe0]\xfb\x91\\\xfa\xa7\x00\x1b\xfeE\x16O\xb8\xeb\x81\x97\x8b\xcfH`\x03UwW\x0f\xfcnxG}\x84%\xd5\x94U\xfb\xb6\xd9\x89\xbb\xc4\xf5\xcf3\xda;n\x96\xb1>w\xe6\x96F-O\xeeN\x8c\xc1t\xa9_`/\xacq\x0f\xfd\xe9xl;\xbe\xa2\x1d\xab\xcd\x87\x9f\xf1^\xf9q\x1d\xc3o\xdb\xd33\x89Z\xca\xdb{8\x0dhN\xe44\xedGC\xa6\\\x86\xce\x1d@\xdc]1\xddS\x8f\x8dxa\xd8/\xfc$z\x19\xf2\xa2\xe9\xbf\x7f\x0e\x97c=\xc7\xf9)\xaa\\M\x0bU\xdd\xc0\xcb\xff\xfa_\xc9E\xe5u\xdb\xc2}\xdb\xc2?\xc2\xd9\xd9\x19\x05/\x8d\x0d\xaf\x9aG\xeaOU\xf3x6\x16\xfa\xbak\x0f?\xdc\xb7\xed\x8f\xd4Cgg\xd4\xcaQ\xdf\xc3\x0f\xe3\xeb\xefyUo\xda\x1f\xfe\xcb\xf8\xfe\x8f\x96\xeb\xaei\x1d\xc6%\xe4\xb2/\xfe\xec\xe9\x8b\xffV}\xac\x92:\x03\xfe\x91\xefkF\xcd\x91\xed\xae\xfb\x1f^\xb7\xed\xd9f_\xf5\xbd\xb5\xd9X\x95\xf1ql\x85\xf2\nU\xa2\xb5?\xfe\xc1\xd3\x1f\x97\x8f\xc3\xc3x\xd4&tb\x15^\xb7\xed\x0fgggT\x1a\xc7\xd4\x1b?X\xfe\xcaG\x08\xef\xa55\x9d4\xbex\x81}\xf4\xea\xfc\xfa\xe5\xd5\xc5\xe5\xcd\xbb\xab\x1fM\xbb\n\xa2\x10\x1cG\xb6b\xb0 K\xef\xfc\xdf\x9e\xde\xf9\xa5%\x03\xdc\xc6\x9ey\xfe\x8f\xf0_\x8ewg\xaf\xdb\xf6\xff;;;\xd3oG\xe7R5\x8f\xcf\xc6\x0d\xd4\xf8l\xd5<\x1e\xef\xce\xde\xb2O\xd6z\xd6\xf7\xfc\xd9\xff\xeb\x1f\xa1\xa9\xf7\xb6\xbb\xdf\xe9N3.gw=\xabU\x9e|U\xd4\x05\xeb}\xf6\xbe9T]\xffP\xedoZ\x1c\xf2)\x15\xd5~\xbd\xe1\xae\x9b\xcd\x87\xc9\x06\xca\xad1\xdc=\xce[\x10i\xa9\x11\xa7{\x94\xf0\xeb\xb8X\xeb\n\xffDl(~\x1eO\x7fg\xfc\x0f\xe3F\xecO\xe3\x8e}Z9\xc6Ue\xfc\xfe\xa6]\xc7\x11\xa1\x170\x19\xebf\xff(\xcf,\xc6\xf1r\xda\xf4Au?0\xdc\x95\xf0\x93\xed\x9f~\xfe\x93\xaeP\x1c\x9cde\xf0\xa4\xc4\xc4\x08\xfd\xfe\xbem\xcf\xee\xaa\x8e7\xe3\xf3\xcf\x8fg\xff\xe7{\xec\x05\xdc\xf3S\x87\x18^\xec\xf7\xe3\x93\xe3\x92\xa1\xfd\xf1\xbf]\xbf{k\xfc8~\x84\xf1\x0f\xf31\x1a\xb7<\xed8\x19\xc5\xfa\x8e\xc7\x85S\xcfdx\xc0\xee\xb4\xaf:]\x93\xa9\x00q\x8fy]~6G`\x88\x89\xf6L,\xf7\xc6\xe1[Y+\xefyk\xff\xfa\xff\x8e\xed\xfd\xab8/.\xdc\x7f\xb2\xf7\xce\xe4\xdc~N\xeei\xab\xcd\x87qj\xcf\xe7\xa4\xfbz\xcf(\x83*\x8d\xc0%\xeb\xfa\xb6\xb1\x8cr\xe1\xf2\xb8\xaf\xbb~\xb8\xe5\xddn\x8b\xd3\x90\x8f\xf2 1\xf1\xe4\x9f\x83\x0c\xf9(t\xe9\xdf\xf3\xde\xf8\xfe9|O\x0d\xf9e\x13\xcf\xb0\x1d\xdf?\xa35\xf1\x16\xbc\xad\x0e\xa3\xb6\xff\x07\xab\xfaO\x96G\xc7\x16hO\x864\xe3\xe2^\xec\xcc\x97\xdf\x1e\xbf[\xdd\xc3'\xb6\xdf\xff\xf4\xa1i?5|2>pO\xf0\xe6\xd4\x0f\xedA\x8c\xd9\xa5\xbe\xe5@{\x86\xfbBm\xf4\xcd!U\xa2\xd0q@5;\xc31\xc3\x07\x97^\xc0_\xf9\x80\x97c\xed\xa1\xddoq\xa0)u\xe2N\x1e1FA\xb8U\xc4\x10\xd5\xb5\xf1\"\xa6\xb1 ?\x8cS\\v\x81qj\x97\xae\xa5\x7f\xfb_\xff\xf6#9\x8c\xd3\xc6\xc3\xb2\x10\xdb\x90\xe0\xcd\x1f\x95\xfd\xfd\xd9\x9f\xff\xfe\xcf\xfd\xf7\xe4G\x9e\xff\x9d~\xaf\xa1t\xc6~\xa7=%\x9d\xf2\x1a\x94Z\x0d\x15\xe2\xa8Jt\xe1R\x87x\xff?\x161O\xba\x8b?\x84We\xaa\xc1\xd5\xe5K\xa1K\x0fq\xb2c =\x82\x15\xab!\x85\xa3\x82g\x91\xaf\xd0\xaf\xc1\x97\x03\x14\xc6N\x9a<\xf8\xfd\x84\xc0T\x1d\xc3\xc3\xa8\xa2\xa6c\xbb\xba\x1fX\xc7\xb6\xb7&T\xa2\x94\"\x80\x1d\x05R\xbe\x9a\xde\x94\x1d\xaa\x01^D\x03W\xb9\xe6\x0d P\xca@\x02\x82\xd3_\x97\xc0\xa0\xb7\x9aV\x88p\x94\xfb\x8e\xb1[\x93\xc1\xc4\xda)\x16\xec\xef\xdb\xe8\x8a\xb5\x18\xa9\x14\n+\x9d\x8a\xb0\xa2=\xe0D|\x002a\xa8Rt,u*$\x0d\xc6Y\x87\xb1\x12\nb\xc1VB\xd5\x12~\x05p\xc7\x85hf\x8e\xc4d\x95\x91+\xcd5a\xad\xbe\xfb\xce\xac\x03\x0ei\xa7!\xd7\xeckx\xf8\xeaR\x01\x19\xb8\xea\xb0\xea\xab\xed\xf9\xa4K7\xe9Aq\x1f\xbf\x13\x9a,\x1f\xa4lM\xd3\xcbV\xb7\x08h\xd9\xce\x8e\x95\x81\xb3+\x00b\xb68\x8e\xad\x06\xdc\x7f\xe9\xb1-\xf1\xdei\xa5B\xecTv\xc0\xd9\x079\xe7\x06\x9d3\xc3\xce\x1e\xe09\x19z\xce\x0b>\x87\xc0\xcf \x00t^\x08:\x08\x84\xce\x0bC\x07\x00\xd1\xd9\xa1h\x0f\x18\x1d\x07G\x93\x8a\x9c\x10u\x16\x90:\x10\xa6&\xdf\\\x05]'\x83\xd7\xb9\xe1k;\x80\x9d\x19\xc2~\n\x10;3\x8c\x1d\ndg\x86\xb2\xdd`vv8\xdb\x0eh\xaf\x80\xb4\xe3AmR\x19\x07\xba-\xb0v\x12\xb0m\x85\xb6\xbd[\n'\xbc\x1d\xb6\xe3\xc8\x07q\xbbAn\x7fm\xb2\x02\xddn\xa8;\x1b\xd8\x9d\nw\x1b\xea\xf8\x8e\x86\xdc<\xe4\x85\xbcm\xa0w:\xec\x1d\x80\xf5:\xa1\xef@\xf0\xdb\x8a\x81\xad\x04\xc0\xedz\x08\xac \x19\x06_\xd39!P\xb8\xbf\x17\x82\xe0\xf0\xd5\x80\xb8\xb3w\x12@\xf1\x00X\xdc\x07\x8c\xfb\xa1qg\xa7\xad\x81\xc7\xc3\x00r\x12\"O\x06\xc9\x83a\xf2\xb5@y Tn\xefD\x1a.w<\x1f\x02\x99\xe7\x00\xcd\x9dU6~O\x82\xce\x0dm\x04\x94\x9e\x15L\xb7\xc1\xe9\x89\x80\xbaYe\x13`\xcf\x0f\xb1{@v\x0b\xcc\x9e\x13h\xcf\x0c\xb5?\x05\xd8\xbe\x06n\x0f\x04\xdcWA\xee\xe1\xa0\xbb\x05v\xb7\x01\xad\xe1P\xab\x1fz_\x05\xbe\x07\xc3\xefd\x83rC\xf0yAx\x0b\x0c\x9f\x1b\x88\xcf\x0d\xc5\xa7\x8f\x91 8>\x0c\x90\xd7W\xb6<\xec\x9e\x060\x9f\x0e\xcd\x17\x06\xa0\xc2\x00T\x18\x80\xbe\x06\x03\x90\x05D\x0d\x82Ou\xe0te<\x8c\x1e!\x11\x01\xa1:\xa2HV\x18\x8f\xaf\x10\x1f\xc3iNultn\x8f\xa2\xf1\x89\x12]eI\x945\xef\x1f\xdanx\xa8\x9a\xed\xed\xa6\xdd\x92\xc9\xae\xf6\x18.q\x0f\xd0\xa4\x02F\x15\x14\x15\x03Q\xae\xe4\xdf\xb0\xe6\xd8\xda\x8b\xc5\xc0\x08\xbe\xdf\x98a/\xa1\x8fm\xc7\xf9\xdb\xc0\xa9G\xf2\x01\xaap\xca\xc0\x99#\xd4\xc1\xde\xe1\xeeQ\x01\xf6.\xdczS\x9c\x03\xd8g\xa3m\x8a\xac\x89j0\x1a\x11\x1a\xd9\xa0\xbf\x18\x13\xe3`L\xd0?R\xb8C\xdc\x84~\xe2\xf0\x02\xd70tO\xed\x90\x9d`\xca\xf4vN\xf0\x90\xc2S'\xb9m\x1f\x93q\xa2\xd3S]\x9b\xece\xb7[v\xbbe\xb7\xfb-\xecv\xadK\\\xca\x02\xdb\xfbW\xd8\xab\xc5v5`%\xcd\xc5\xe5\x95\x1a\xb4\xf7\x044]\xe1\xc1y\xd9x\xba\xca\x9a/\xd6\xdc\x18z\x1a\x1b5\x0dm\xbb!$6+\x9d\x8e\x86\xa2\xa2!g\x00x\x91\xffu\xf43\xcbwc\x99g\xa6\xf6\xa1B\xdd\xa8'\xf2\xcb\xe8\x01\x18\xa4=:\xb6\xdd\xc0\xad\xd1Z\xe33T\xcd\xb6\xea\xf8\xc4\xef\x9f<\xc4\xe9I\xa3\x87\xc6\xfa\xab\xd7\x01i\xdd\xa6\xbeGV\xc2\x15\xbes3\xfegY\x94uL\xaeVN\xa4\xe7*\xb7s\x9d\x7f\x1eX3\xee\xfd\x952\xb4F\xcb#\xfa\xa6\x1a\x0f\xa9\xb5\x99HT\x1d\x8f{\x8e\xb4\xaa!.t\xe9\xd7b@\\\xa1j\xdbFW<%k\xc0\xe7\x1bN\x8b\x85\xb6c\xbd\xf90N\x92F\x03o\x11\x1e\xe8\xda\x03l\xeb{~\x9d\xdd0}/\xc5\x90\x125|S\xe3E\xfa3n!F.\xaa\xc3\xd5\xaea\x9ffu\xbc^cE\xc66\xd4\xea \x93\xf9c\xcaOm\xc3\x16DM\xd4T=\xb4\xdb\xd3^\xccX6\x1a\x04r\"\xf2\x10\x8b\xaf@\x98g\x9d\xd0`\x99\xd4@Ml\xb0On\xf0\xb0\xf6\x98\x93\x1c<\x13\x1d<\x93\x1d\x12&<\xd8&=\xb8\xe7&\x84O~p\x1b\x00\x08.\xc8\xc2\x1a\x90`\x0cH}\xf5@\x1b\x04p\xd6$\xcd0\x18\xea\xee\x98\xd58@\xb0\x81\x00G\x8ds\x1a\n\xa0\x8d\x05\xa8\x06\x03\xd6\x1b\x8d\xe9\x05\xc2V\xd8\xa3\xb80vK\x94A\x87k-\x8d\x10~\xb1\xd5F\x08\xbb+\xce\x08}\xad\xac\x84\x1e\xc3\xaft\xce\xce'JD\x080@\x84\xe9\xb1\xf6A\x90\xb9\xb1\x1a\x1a\x9fZc\x82$\x98\x15s\x8fA\x18\x14Q\xae\xd5^\xc8+\xf5q\xb8bh\xe6\xd4Xub,\xc7\xafob\x88\xf2\xc2'\xc6\xfa\xe5\xf9\x8b\xec\x95\xbfr:\x80e&\x95=<\xad\xfc\xeb\xee\xe1\xe3\xe6X\x89\xe5/\xb1\xfc%\x96\xffk\xc4\xf2S\xabO\xd8\xba\x16\xba\xe3\x1b\xff?b]\x1b_\x8b2\x05_a\xc7\xc7D}gpj\xd3\xb1\xa0\xabV\x13k\x83\xc5*\xcf\x88\xfd\xc0m\xbdM?n\xaf]Fm\x8b\xa8X\xc7\xc9\x0eR\x10\x10\x98\xe7D`O\x89\x02\x95\xd5\xed7\x19\xfb\xc7o(_`kFG\x8d?\xb0\xb5w+,o\xe4\x96J\x94G\x87\xaa\xdb1\x9dq\xde\xe6\xbd\xb0\xfb.\x86r\xb5\xad!\xd9R#\xc0\xc70<\xc4\xa7H@\xc64 \xf0\xa6J@l\xba\x04\xa4\xa4LP=\xe6g\x15\x8eN\x9d ty\x19\x85SR(\x08u\xe5j\xdb\xb4\xb4\nHK\xad\xa0\xa7(Y\xc9l \x17\x90=\xe9\x02r&^@P\xf2\x05\xe4L\xc0\x80r\xb5-ULd\xe2\x06\x94\xabm\xe3\x12;4e\xe5j\xdbr\xb5m\x80\x8er\xb5\xedR\xca\xd5\xb6\xe5j\xdb\xc0g}i'\x90\x9cz\x02\xe5j\xdb!09\x052'\xa8\x80\x8fu\xb7\\m\xebO\\\x81\x90\xe4\x15\x08O`\x81\xc0$\x16(W\xdb\x06%\xb8@j\x92\x8b\xa6\xab\\mK(\x0b`\xd2].\x1d\x12\x0c\xe5\x1eS\xabG\x9b;\x8a\xeb\xb6\xb9\xddVC\xa8cX\x9e\x91\xc6W~\x1a\xea\x03\x05\xda\xc2M}\xe0K\xb6\xe1\xc4\xffT\xf5\x86\xff~B7\xf9\x13\x96\x88#\xbe?\xaf7j\x1b\x96(\x8b\n\x85\xf8A\x16^T8\xc6\x12\x13<\xc0\xdf\xfb\x83\x06\x0f\x84\x802\xf6\x18\x82\x0c\xb52\x86\xb2\x03\x9e\xb1\x034\x16\x88\xc6\x0d\xd2\xc4E;\xac\x00j,PMH|B\x14\\c\x03lB\n\xf4\x8364l\xe3\x00n\xdca\xa7C\xb9,\xb2\\\x16Y.\x8b\x8c\x01v\x02\xa0\x9d\xec\xe0N\xb9,\x12e\x15\x18\x94\x0c\x07\xe5\x06\x84\xcae\x91\xaa\x84AC\x99\xc1\xa1rYd\xb9,\xd2\x03\x1a\x95\xcb\"\xd7\x03H\x86\xba\xa1\\\x16\x19\x06'\xf9\xafI\x0c\x83\x94\xcae\x91\\VBL\xe5\xb2H\x94\x10\xc8\xa9\\\x16\x89R.\x8b\xd4\x7f\xcc\x08O\x95\xcb\"\xb3BW\x99\xc1\xab\xa7\x80\xaf\xd6\x00X\x81\x10\xd6*\x10+\x1c\xc6*\x97E\xc6\x80Zya\xadrYd\xfe\xcb\"Ca.'\xd0\x15\x04J\xd0`W\x1c\xdc\x15\x0fx\x95L\xbe\x92\xc9W2\xf9\xbeb&\xdf\x02\n\x0e\x03\x99\xbd\x99|W\n\xff\x821\x95\xbf\x1a\x8d\x9c5;<#\x11\xa4'\x0b\\\xcb\xff&\xdb\xe8\xcd\xf9&\xb3\xbd]\xaa\x16\x937-\xb7[\xe6r/\x0c\x8d:\xaab\xf2\xb9\xa9\x01t\x9c\xd29\xbf\x9d\x01\xe4\x8b\x10\xc8V\xfab}$c\x00\x86\xf0\xc8\x0b\x13\xf1_7\x9a\x03Q~\x03\xdfw\x8d\xc8\xd5\x98\xbe\x89\xe6\xbb\xd4\xbb\x11|\x1d\xbb_\xb1\xd9\x18\xcaMS\xe9(|\xb9i*\x0ca\xe7\xed-7MM\xae\x8b\xa8\xf4\xc8D\x8c<\x08\x1d\x0fG\xc2\x130\xf0\x04\xf4\x9b0\x18\x191\xee\xbc\xe8v6\\\xdb\x8fhg\xc3\xb2\xcbMS\xe5\xa6\xa9\x15\xa8r\xb9iJt\xb4\xaa1\x05!\x0e\xb9|\xa9\xdc4\xa5H\xb9i\xaa\xdc4\xb5\xe2R'\xff3>\xb45\x0dg-7M \xc9\x89\x89\x96\x9b\xa6\xb8\x84\xe1\x9d^\xa43\x10\xe3\x0cA7\xcbMS\xb3\xae$\xb4\xb2\xdc4\x15x\xd3T\x08\xe6hA\x1b\xc9\x1d\xbd\x1da\\\x8b-\xc6\xa1\x8a\xa6?y\xc9\x00\x1e\xecW.\xc0@>``*+\x8d\x8d}f_\x17\xea\x14\x0ev\x1f\xf3\xba\x18\x17\xe3\xf9g\xff8eC\xbe\xac\xbb\xcdi_\x0du\xb3[\x9d\x11\xb9\x99\xdf\xbdE\xb5\x8e\x8e\xd7;\xc2V\xba\x1d\x84\x1b\x7fE NyMh\xbb\xba|)\xfbAG\xe6\xb4\x06\xdf\xb4C\xb5_\xddT\x0e\xd1\x067\xd2,(\xa4U\xfc\x05\x15\\\xfc\xff\x03\x00\x00\xff\xffPK\x07\x08f\x87\xc3\x1c\xc7\xc8\x00\x00\xcb\x95\x0c\x00PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\x00\x00!(f\x87\xc3\x1c\xc7\xc8\x00\x00\xcb\x95\x0c\x00\x0c\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x00\x00\x00\x00swagger.yamlUT\x05\x00\x01\x80Cm8PK\x05\x06\x00\x00\x00\x00\x01\x00\x01\x00C\x00\x00\x00\n\xc9\x00\x00\x00\x00" + data := "PK\x03\x04\x14\x00\x08\x00\x08\x00\x00\x00!(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0c\x00 \x00swagger.yamlUT\x05\x00\x01\x80Cm8\xec\xfd]w\xdc8\xb2\xe7\x0b\xdf\xfbS\xc4S\x17S\xae\x19[\xae\xee\xea\xf5\\\xf8\x9c=\xeb\xb8mU\xb7f\xdc\xb6\xb6,\xf7\xac>\xb3\xf6RS\x99\xc8\x14\xc7\x99d6\x89\xb4\xad]\xbb\xbf\xfbYx#A&^\x02H\xa4\xa5]\x15qS.%\x19\x04\x82 \x08\xe2\xffC\xa0\xffR\xad\xd7\xac{ \xdf\xff\xfe\xec\xc7\xef\x9f\xd4\xcd\xaa}\xf9\x04\x80\xd7|\xc3^\xc2\x1b\xd6o\xdb\x1e\x9e\xc3\xd5\xf9\x87k\xa8\x9a%\xac\xaf._\xc3\x9f*\xce\xbeT\xf7\xb0l\x17\xfd\x13\x80%\xeb\x17]\xbd\xe3u\xdb\xbc\x84W\xea\xd8\xba\xe1\xac[U\x0b\x06\xab\xb6\x83\x9eW\x9c\xc1?\xf6\xac\xab\x998\xe33\xebzy\xf4Og?\x9e\xfd\xf8dW\xf1\xbb^\\\xf6\xc5R^\xf0\xc5\xaekW\xf5\x86\xf5/>\xff\xf4\xa2\xda\xed\x9eo\xea\xe6\x93<\x00`\xcd\xb8\xfa\x07@\xbf\xdfn\xab\xee\xfe%\xfc\xf7\xe7\xfa/\x00\xafv\xbbM\xbd\xa8DY\xde\x8a\x93\xccE\x81\xdf1\xa8\xc6\x1f{\x90>\xa1\xea\xfbvQW\x9c-\x81\xb7\xf2\xa0u\xfd\x995O\x06\x87\xfb\x9eu\xcf\xa0^\xc1\xaek?\xd7K\xb6<\x83\xf7\xfc\x8eu_\xea\x9e=\x83\x9a\x0f\x17\xa86\x9b\xf9E\xd45\x06W=o;\xb6<\xd3\xff\xdf\xeeX'\x8f\xbaX\xbe<(\xb6>\xa6c\xfd\xaemz\xd6\xbf\x1c\x9c|\xff\xfb\x1f\x7f\xfc~\xfc\xdf\x83\xe8\xf7\xfb\xc5\x82\xf5\xfdj\xbf\x19\xce>\xb3\x8e\xee\x17wl[\xd9\xe7\x03\xf0\xfb\x1d{ \xed\xed\xffa\x0b>\xf9a\xd7\x89B\xf2\xda\xbe\xbe2\xeb\x86\xd8\xa6\x83\xeb/5\xe7\xe2 \xfaS\xcd\xff\xbc\xbf}\x06\x8c/~\xf0:\x14\xf7R\x9c[\xaedV\xd7\xe0\xb2\x8f\xfa\x82\xd06\x07\x0f\xaf]~\xe0\xd5\xda\xd4!\xe8P\xf7\\\x81z\xca\xbe0\xd2b>\xc8\xfeR\xb6\x0e\x16o\x13\xc1X\xb0f\xbf\xf5\x87\xf39\xbc\xba\xbc|{\xf1\xfa\xd5\xf5\xc5\xfbw7o/\xde\xfd\xcf\x9b\x0f\xd7\xaf\xae\xcfo.\xde]\\_\xbcz{\xf1\xff\x9e\xbf\xb9\xf9\xf8\xee\xc3\xe5\xf9\xeb\x8b\x9f/\xce\xdf\xa4;\xfa\xeb\xf9\xd5\xc5\xcf\xe6\xef\x1f\xae_]]\x1f\xed\xe5\xfc\xea\xea\xfd\xd5\x91>>||\xfd\xfa\xfc\xc3\x87t/\xd7\x17\x7f9\x7fs\xf3\xfe\xe3\xb5\xe7\xd4%[U\xfb\x0d\x7fY&\xb0\x93\xce=\xd0\x96S\xef\xa3xS\x04\xda\x15\xc0]\xd5\xc3\xff\xd9\xf7\x1cn\x19k\xa0nj^W\x9b\xfa\xdf=\x9d\xa04d\xe0U\x130\x05\x18/\xd4\xf3\xaa\x13\xaf\xe1[V7k1B\xa8W\xf5\xf1\x97\x93mer1\xd6u\xe25\x0c\xcb\xbdxj\xe4\x13\xa6.\xa6\x1f\xfb]\xd7\x8a\x17\xe8\xb1\x17\xd6\x0dlr\xe9i\xd5\xacW\xf5\xe6\xf0u\x19\xbf\xdc\xd0\x12'\xd7\xe0\xf5\x96-\xa1\xdds\xf1*\xdb0\xf8R\xd5\\\\U\x0c\xc3\xe6uu^\xb4\xed\xaa\xc5\x86\xddt\xec\x1f{\xd6\xf3HG\x15h\x92\xef\xa5\x9f+\xe5\x06:\xb6\xebX\xcf\x1a\xae^\x80\xda;\xf0\xbb\x8a\xeb\xd0\xb0\x06\xb6\xd5\x92y\xfd\xe9\xe1\x99*\xdei\xdf\x91\xf5\xb2\xc0\x0bh\xd5v\xdb\x8a\xbf\x84}\xdd\xf0\xff\xff\x1f\xe2o\xaa\x8b7b\xb4!\xaax\xf1\xc6t\xfd:L\xde\x93\xf5\xbdR}\xc4\xcd\x83\x14[\xdd\xe6\x0f\xb2\x04\xaa\n\xaa\xf8U\xa3K\x07\xaat^O\x8bj\xb3\xb9 \x8d\xa2\x00\xd5\xdc\x84\xbd\xae6\x1b\xc7`K\xfce\xdf\xab\x11\xfe\x8eu\xa2\x86\xe2\x87\xa0+]\xf6\xd8\x0d@59@6;\xc0\x0f\xcf\x00\x7fC\x01\x1d>a\xf3\x91\x9c\xe86\xc61q\xfb\xa5a]\x7fW\xef\xa0\xbfk\xf7\x9b@\xef\xac\xed\x96!zrl#\x80SV\xfa\x8e}\x05\xd6,\xda%[\xca\xd2\xa8f#\xfb'UWQ\x17\xdd\x8a\xa2\x0ee\x9d\xef\xe7#\xca'\xd1\xf3\xaa\xc5\xa2\xdd7|\x8c\xb3\xff\xa9\xd9\xd4\xac)\xf4\xc8\xe3\x02\xf5Z^\xf1\xe2\xcd\xbc+\x1f{+U\xa6\xa1O\x8f\xdep\x11\xcb\xa1G\x0fu\x13\x1d\xeb\xc5\x90\xca\xe3P\x17\xff?\xfc\xc5\xd7}\xc2V\xbe\x07\xbbv\xab\xfbV\xe1\xd4\x94\xdd~-\x9ey\x1d\xbdo6\xf7P}\xae\xeaMu+\xde\xadwL}6\xa8\xf9\x8d\xba\x07\xf5f\x0e\x0f.\x11=\x06\xa6\xb7\xd0\xa3\x07D\xaf\xf9A\x1di\xdf\xb8\xca\x9e'\x88\x0e \xb4\xb7x\xb9\x01Yva\x9f\xab\xcd>\xf8\xa1\x07\xf8\x16\x0c\xe8V,\xec\xcf\xec\xebs\xf3\xa8\xcbR\xd8\xc3\x10\xe8\xebu#\x86\xa1\xf7\xd1w\x04\x8c\xdf{\xc1\xe3\x84\xc7\x8a\xef\xbb\x87\xaf\xedP\x92\xd9\xc0k\xd7\xb5\xcb\xfdB\xd6:\xeaO\xf8\x18\x06\xce\"z\xde3VU\xbda\xe1\x0eJ\xd5\xe2gy\xe0\xb4}\xaa\x93\x1f\xa8m\xcao\x84\xf2w\xeb\\\xb8U\xa1\x9fL,\xc1\x97\x9a\xab\x17\xac\xa8\xf5\xbes\x87t\xd11\x19\x86\x1b1\xc4?b\xc6\xcb\x8c\xf0\x96\x15g\xcf\x85\xafp\xbf\x1ahb\xafu\x89\xae\xeb-\x9b\xbf\x16\x84c\xa8\x9b\xf9\x84\xda\x97\xc0{AV\xd03P`_wu\xf7\xc8\xaa\x7f>\x94 \x1f\x00\xaf\xb3/\xf5f\xa3j\xe9*P\xb80\xb3\xd9c\xc7\xf0W\x0c\xc8\xd5\x0d\xe0-T\xb0`\x0d\xef\x02\xdf\xf3\xf6\xa0e\xfa\xcb\xaeZ\xd7\x8dgx\xaa\x0by9\x1c\x02K\xb6\xaa\x1b=\xf9>\x9e9LL\x1fz\x08=\xc6\xe1\x87\xb7a_\xf9\xcd'v\xefn\x19\xd1vaZ\xc5\xed=w7\x88\xc9L\x8cw\xacaJa>\xe5\xc4?y+^+\xbb\xaa\xd7\x9f \x97\xd5\xda|\x16\x9f\xa9\xdf=\xce\xfe\xb1g\x9d\x1aD\n\xb7\"\x80\x0c\xb6m\xcf\x81\xadV\xf5B\x8c\xb56\xf7gp\xc1U\xdb\xb9e\xc0\xb6;~\x0f\xf5\xca\xd7\xa2\xefX\xc7\xa0\xea\x184-l\xdb\xce\x8c\x81z\xd7\x80\x87\xb7\xbc\xda\x1c\x19\xcc\xc07d\xec\xe9\x92\x97\x97Q\x94\xffh\xf6\xdb[\xd6\x89f\xac\x8bl\x8d\xc2\xbc\xf5\xb5\x03-\xc7\xd57\xd2\x99o\x18\xfe\xa5\xea\xa1g\xfc\x19\xd4\xbc\xd7\xe3\x82\xba\x87}\xa3\x1a\xf1\x12Z#\xfb\x1c\x9c\x1f\x9f\xa5SEQ\xad^\xd5J\xdd\xaf[\xb6\x14\xef\xe5\xbaQ\xc2\x9ay0`\xcb\xfa\xbeZ\xb3^\x0c1\xdd\x1d\xc2\x1ds\xd5c\xd1v\xca\xc7R\xbc\xa2\xcd,\x8b\xf6&\xdf\xf7\xf2\x13\xc6\x8e\x8c3\x1c\xe6\x8c\x0f\xedv,\xf7/\xde\xceK\x8e\xd1w\xb2\xf7\x86?V\xddp\x93\xfe\x05~\xf7\x7f\x85N\x9a\x84E\xb6\xef\x7f\x81\xdf;\xcf\xf8\xe7\xe4\x8f\xbe\xd6\xf3\xaf\xe2\x89\x99ki\xc3\x05\x0e\xe6\xa0\xf4\xdf\xf5\xcc\x92|\xdcf\x0eE\xb4\xe6\x01\xe2-\xac\x19\x9f\x7f\xdci=Q|/W\xa3\x9e\xb3\xefY7\x9cn\xa6\x86-\x7fS\xf1\xae\x81}\xc3\xbe\xee\xd8B\xc4Q\x8eAN\xa9\xe1y\x069\x81\xa7[\x0c\"}'\xd4\x0dgk\xab\xb2\xc6L_P7\xfc\xa7\xdf\xcf~\xd5\xad,\xa9\x0cZ:\xf3\x9d\xf3m\xb5Gq\xfa\xcd\xbe\xf3\xf4\x93\x88\x9e\x12\xd3w({\x05\x1f\xaf\xde\xbe\xe8X\xdf\xee\xbb\x05S\n\x9b\x1cI\xee\x9b\xfa\x1f{\xb6\xb9\x87z\xc9\x1a^\xaf\x8c\xd8-\xae\x0d\xad\xafo\x04\xf5\xdd\xca:3\xad\xef=n\xd7\xb5\xbc]\xb4\x1b\xb8\xdd\xafV\xac37\xed\x0c\xae\xa5r)\xeb\x06\xdb}\xcf\xcd\xb0\x03*\xff\x10|\xc3\xaa\x9e\xfb\xaf\xd56\x0c\xbe{\xf1\x1d,\xee\xaa\xaeZp\xd6\x9d\xc9\xb9\x99M\xd5s\xe8\xd9z\xcb\x9a\xe1\x83\xfd\xe3\xd5\xdb\xef{\xd8U\xfc\xce\xebM\x16jx\xe8\xfdW\x95\x03\xef\xfdfs\x0f\xff\xd8W\x1b57\xafD\xc1\xd5\x18\xc9\xa7U\x0fu`\n\xe7\xef\xa2(/\xd6m\xbb\xde\xb03\x19\xb3\xdb\xfd\xea\xec\xcd^\x0d\x10\xff\xfe\x83\xaa\x89t;\xce'\xd5\xfeo\x9a\n\x16U\xd36\xf5\xa2\xda\xc8g\xc8\x7f\xe5\xa7\xecl}\xf6L\x84Vv\xfa\xdf\x9d}'\xde0M\xcb\xa1Z,\xd8\x8e\xb3\xe5\x0fgO\xfc\xa7_\x88\xcf\xbfj\xc1\xeb\x05{\x06\x9cU[\xf1\x8e\xd8W\"\x1c\xbb\x8e-\xda\xed\xae\x16/\xd9F\xf7\x92\xb7uS\x1dt\x93\xa3I\n\xe2~'\xdb`%;\xc9{\xff\xa5U_\x075\x17}\xea\xbe\x97\xc3e9\x91\xd46\\\x8cx\xda\x15\xbcj\xee\xcf\xe0\xcf\xed\x17\xf6\x99u\xcfD \xbc\xce>^\xbd\xed\xf5`[\xb8\xf2\xbc \x95\xc9\x1e\x94\xc1\xdf\xef8\xdf\xfd\xfd\x99\xfao\xff\xf7g\xd0vbh\xa4~}&[\xe3\xa2j\xa0\x95Og\x15Riz\xc6a\xbf\x83J\xd6=p]\xd6}f\xfa\x0bp[\xedz\xd5\xb4d\xc9y;\xbct\xe5\x80\xa3\xe6\x92R |.\xad\xda\xcd\xa6\xfd\xd2\xbf\x0c\xdc\xdb\xff\n\x17\xab\xb1F\xa2Y\x18\x8ae\xa8\xb4\xfe\x12\xddo\xd9\xd2=\x14\xd0\x8e^5\xf0\xe7\xeb\xebK\xf8\xd3\xf9\xb5\x11\xcb?^\xbdU\xcf\xd8}\xcd6K\xa8\xbcg\xff\xef\xf9cq}\xbfc\xff\xf6\xbf\xff\xcd{\x02\x98\xf1W\xa3\xdb\x9b~\x8d\xc8;\xa4'+\xa0j\xd4+\xcc?]\xf7_\xed/\xa3^\x8e|+\x1135\x0e_T\x0b\xd1\xb7\xb4\xed\xa7\xfdn\x18\xb1\xdcV}`\xaaZU6DG\xd1\xcc{)x\xaa\x95\\\xf5\xb5\xa7\x1em?R\xb3\xad\xd7w\x1cn\x03\x9d\x92\xac\xb4\x9c\x81\xaa\xb7\xbb\x0d\x13/Y5\xa2\x1dF\xb1=\xdbV\x0d\xaf\x17\xce\x0f\xc5\xc8L.b\x08\x14\xfd\xf6\xc6\x8f\x92\xfe\xa2\x90\x05\xa8D\xa1\xea\xa55\xc09\x18\xc7\xe8\x97{u\xdb~\xf6\xb7i\x1d\x02\xfd(\xb8\xaa\x8f)\xd9\xdf_5\xf7\x7f\x1fge\xaa\x06\xaa\xee\xb6\xe6\x9dx\x88\xfd%t\xba2\xef\x88j\xd3\xea\xa6\x07\x95\xfb\xd6\x8a\xdeY\xbehT o\xa7\xc3\xc2\xd9\xf0o\x18\xd5y\x9a\xe6\xa5yp6\xf5\xad,\xb6~\x8f\xf4\xd0\xefw\xbb\xb6\x93o\xf0]\xb5\xf8\xf4b\xdf\x88\xff\x88\xf7\xb6j\x17\xee'H\xbf\xe8\xfd\x03\x9bv\x05{\xae:6\xd3=\xf4\xa2c\xad\x96\xcbZ\xf5\x15\xb0f\x0d\xeb\xe4'\xe7\x96\xf1\xbbv\xa9q:\xf7\xcd\x14\xe5Q\xb7\xd0}\xbd\xf3\xaf\x95h\xfc\xf0\xbb\x97p)\xca/\xfa\x05]\x95j\x08z\xdd\xc0\xeb\xff\xf6\xdf\x02\xaf\xc9\x9f\xdb\x16Vm\x0b\xff\x02ggg\xfe/_Q\x98\xaa\xb9\xf7\x1fP5\xf7g\xa2\x18?w\xed\xf6\xe9\xaam\x7f\xf0\x1fzv\xe6\x7f\xff\xd5+x*\\}\x94\x15\xb9n\x9f\xfe\x17\xe1\xeb\x87\xe0\x87|\xc8\xdf?\xc3\xb1\xfb}$v\xff\xa3\xfa\\\x15\x0b\x1e\xfc\x8b\x1c\x1b\x8a\xab\x14\x88P\xdd?\xfd\xb9m\xcf\x16\x9b\xaa\xef#\x01RE\x14'\xa9:Z'\xfa\xcb\x10\x89\xdcO\x91\xc8]\xde\xf3\xbb\xb6 \xc4N\x15\xea\xe7\xb6}zvv\xe6\x7f\x19\x0cq{\x1a\\\xe0\xf6~\x1c\xc6\x99\xb7\x91\x9a\x00w\x8f\xa2\xf5\xac\x9b\x18\xe6\xb8/\xf5\xbdc\x88\xf6b\xb5\xdfl\xce\xe4\x0fb\xf8\xfb=T\xd6\xdbS\xbcYE\xdb\xf2\xbdkT\x9bs_lxU5\x9b{\xf3\x9dz0\xf90\x0c\xbb\xa1ZI\xf8\xd8s!9/\xf2\xfd\x8b\xef\xdd\x97\xd2\xefXSd\xf9\xf5\x0cL?#\xdf\xad\xda\xf6\xec\xb6\xeade\xbf\xbe\xb8?\xfb\xf7\xefT\x14\xe5\xb7\x9c\xd3\x9f\xff\xd3V\x16\xf5;\xe1C\xbc^\x9d\x87\xfc\x8f\x0f\xef\xdfy~\x12\xb7Z\xfc\x9dz\x02oUw=\xbf\x91722i\xafO\x10m\xcf\x1c\xef\x9e\xb2\x97\xe6y\xbc\x85\x85J\xf5\x9d\x8c\xe5w/\xe1;\xd7\xc39\x0d\xc3\x99\xaa\xe5w\xcfB\xfed\xfd\xdeU[\xe1\xf3\xffVU\xf8\xef\xc1\x13D\xfdf\xc7\xa7V\xf2b\xa5\xbf\xd3\xa6mM\xb5\x86\xba\x87/l\xb3y\xfe\xa9i\xbf4\xb2;\xb9\xabz\xa8`\xb1\xefy\xbb\x0d\xfd\xf8\x88\x1b\xd5\xb1~\xc2\xa3\xcc\xe7Y\xe5\xad\x9eF\xd5\x00\x0d\xd6lv\xcf\xaanq\xa7N\xb7{\xba\xbayy \xaeu\xec\x1f\xfb\xbac\xcb\x97\xb0\xaa6\x13I\xd59a`B\xe0\x06\x13\x90\x91\xb0&\x03\xe7Z\xe0\xc1\xe2%\xcf\xaa/\x03\xeaLc!\xe2p&\x02\xbdT\xef\xf5z%\xef\x95\x9cZ\xdd\xf4-\xf4\x8c\x9f(\x1ef\xc1\x142\x18\xc3r\xa7Y\xf5\x8d\x1b\xa8\x9b\xbe^\xb2\x83\x90\x1c\x1b\x0d\xdb\xd7\xe9\x832\x92&g\x9f\xd8\xbd/43\x86CC\x1b\x95\x1ejt\x8c\xef\xbbFI\xf3\xb6J}6\x10\x1er\xa6u=\x9b\x92\x9450t\\\x88\xda\x90$i\xdb\xc8\xa9\x98v\xb5\xea\x19\x87\xb6\x83iqa\xf2l\x95\x8e\x96g\xde\xcd\x11DU>d\x13\xd3\x95\x91\xa1l\xf6[\xd6\xd5\x0b\xf37\xf9VZT\xcd@RK~V\x07~\xdf\x0c\xf3\xbc\xb3\xcf\xbb\x0b\xe9m#\xba\xa8!\x84jft\xdf\x8bP\x7fb\x89\xf1\x9c\xba?qpg\x0c\x8c#\xbc\x9bz[c\xa3+\x8f5p\x91\x0f\x8dQ\x1a\x80\xdd\x82\xf9\xc0;O\xbc\xed\xd4\x8c\x9f\xfd\xa7\x8b\x15l\xd8\x8a\x1b\x94H\xb3E\xe6\x1bJ\xca\x17\x1a\x99mu\xe4\xc4\x07\x19\xab\x16w\xe2!\x7f\xc0(\xda\x80\xcfx~(\x96\xd6\x19\"\xa2\xb2\x85\xb6\xc0\xbb=\x93\x8cG\xdd,E\x97\xc5\x06!\xd3\x10\xe3\xe2@\xc7\xf2\x87\xbaYl\xf6\xcbY_X\x81\x06\xfaW\xce;&\xb9\x04K\xe0\x10C\x1c\x8b\x93\x9bu.\x1f/\xfa\xd9\xdd\x9aUAv\xb7\x1d\xeb5A\"\x1f\xaf\xf1y\x14\x8f\xdc\x99~\x9a\xeau\xd3v\xf3\xde\\?\x8d\xd3K\xa8\xc8\x1c{co\xdbv\xc3\xaa&t\x03;\xf6\x99u=\xf6M\xa6\x8f\x9e\xdf\xb8\xda\x02\xc4:\xe6~\x12&~\xc45\x98\xa2\xa5\xdan\xc9\xba\xf9\xfc\xf0\x87\xbaY\xb0\x97\xb0h\xc5\x90\xe9y\xbf\xfc\x04?\x9e\xfd\xe1\xa7\xa2\xd1\xe0\xd5z2\xd8\xfbW\xed-\x98\x0c\xe1\x85Zl\xd1\xbf\xf8eX \xf2O\xe5\xc4\x95 \xe1?\xbc \x12\xfex?\xac\xeb\x18\x12\x19\x80\xe8V7\x87t\x93\x86\x9bT\x82\x04\xe3O/\xfa\xa8Qy\x0d\xc6\xab\xe9\x83\x1fu\x82\x03\x1fc\x94\xc5\xa7\xfa\xd3\x14D\x15\xb2\xe3R\x14\xf8WU\x15LO\x10\x0c\x0cD\x83\x03\xd8\x95o\xd1X\x01\x14NJ\x10OI\x90R\xa6\xe0z\x8d\xc2\xc9\x08b\xa9\x08\x02\x89\x08\x92\xd2\x10D\xeb\x1fJA\x90\xbap=\xd5MB\xfa\x01\x9c\x8fP\xf2\x01\x9c\x87\xf0\xea\xb0\xf8ro\xe7\x89%\xd3\x0e`$\xed\xf4;\x17I9\x90\x9cp\x00\x19\xec2\xe9\x06p\x17+\x9el\x00w\xd9B\xa9\x06\xe2-\xafd\xa2\x01L\x9a\x81X\xa7\x99\x99b\xc0\xbf\xe2\x82\x87\x13\x0c\x14x\xcb\x85\x16\xecF;R\xc0\xad\xad\x008\"\xa9\x00>\xa5\xc0 \x8a{d2\x01\xc4*\xf2X\x93\x82\xe44\x02\xe1\x8c\x14\xa0?\x07BI\x04\xa2\xcd\nPM\x0b\xb0\x83(\xc0\xde<@\x06\x0c\x92\x13\x07\xc0mx\xc9,D{d\xdc\xed\x86SU\xb5`\xba\x80\xbcd\x01\xd8T\x01\x88D\x01\xa8\x00a\x82S2E@B\x82\x80Pz\x80Xr\x80B\xa9\x01\n$\x06\x88\xf6\x02\xf1\x1e \x9a\x12\xa0dB\x80hy\x01Uf\x88\x01\xa4\xcaPm\x14\x90\xed\x14\x8a&\x01\x88\xa7\x00@&\x008i\x1d\x8f_\xfa\x8f]\xf8\x1f[\xf6_h\xd1\x7f\xc1\xf6\x87X\xee\x9fzo\x8eY\xea\x8fX\xe8\x1f-\x0en\x95{\xac!\x15]\xe0\xef_\xde\x8fZ\xdc\xff\x8d\xaa\x9c\xb3\xa8_\x8a$\x1e\x7f\x9e%\xfd\xa1b\x14^\xce\xef[\xcc\x9f\xb2\x88v\x9c\xb8\x1dV\xd3\x1e\x96\xca\xcc\xb3\xcf\xfc\xe9Nt\xf6W\xf3y&\x17\xe4\xc8nE-\xab\xad\x9a\xc3yg\xa5\xf3U\xe3\\\xf3\xe0\x8b\x96\xd4\xce~\xa5%\xb5\xd8\xf9+ZRKKj}G\xd2\x92Zi\xb4\xa4\xf6\xd0hI--\xa9\xf5\x19-\xa9\xa5%\xb5\xd2hI--\xa9\xa5%\xb5\xb4\xa4V\x19-\xa9\xa5%\xb5\xb4\xa4\x96\x96\xd4\xd2\x92ZZR;5\xff\xa7--\xa9\xa5%\xb5\x1e\xa3%\xb5\xb4\xa4\x96\x96\xd4\x96YR;\xd01\x96\x97\xd0\xe7'\x9ep1\x9c\xbeZ\x14\x0b\xdcEPO\xe7^\xeb\xe6\xe5|\xf2}\\H\xc2\xbb}d\xb9T\xde2\x12\x85\x0f\xa9\xf3\xd2V\x8e\xbc\x97g\x0e\xabF\x0c\xf6\xa9\x1c\xca7\x8d=Q(\xaf6\xde\xd7q\xfeW\x07\xc8\x90\xa3V\xee\xdc\xc9\x02T1\xee\xd4x\xf0\xd1.2\xb1\x83o\x1b\x7f\x00\xdd\xed\xa8m4\x11\xd8a\xd4Gl\xa1E\xc4AR\x86|\xd9<\xde\xe8U.\xbe\xa5/f\x1dT\xac\xc6\xee\xaeQ\n\xd7\xf2\x06\x1f\xde^U\xd4Wj\xdd=\xeb\x87y\xb3\x83l\xd2\xad\xdd\x8c\x8dQ\n~J\xc1\x8f\x0e&\xa5\xe07F)\xf8\x9d\x96\x9b\x82?\x1cp\x17C\xa4\xde\xc9\x08~\xe8p\xda\x81[\xcb\x16f?\x1d\xf0CsxH\xf5\xa1\xe3\xf3E\xc8\xd0\xecWB\x86b\xady4B\x86\x08\x19r\x1b!C\xd2\x08\x19:4B\x86\x08\x19\xf2\x19!C\x84\x0cI#d\x88\x90!B\x86\x08\x19RF\xc8\x10!C\x84\x0c\x112D\xc8\x10!CS\xf3\x7f\xda\x122D\xc8\x90\xc7\x08\x19\"d\x88\x90\xa12\xc8P\xb1\x14\xf4J\x1e\xc7\x82\x82H\x16`\x8a\x16x\xca\xca\xe1Y\x80A\xb4\xe0\x08L\xcb\xebP\x1c\x18B\xb5\xa04\xae\x05Qd\x0br\xb1-\xaf7\xf5\xfd\x1b\x9e\n@\xe0[\x10F\xb8 \x0b\xe3\xf2\xba\n\xe2]\x90\x8bxy\xbd\xa9ad`\xd2\xad\x1c\xea\x05(\xdc\x0b2\x90/H\xc3\xbe \x07\xfd\x82d\xfc\x0b\xc2\xdd\x08D\x90\x1cH\xc0r\xb0(\x18\xe4\xe0`\x90\x8a\x84A\xb8\xe29h\x98\xd7\x99\x05^a\x1f\x19\x1c\"\x16| \xe4\xbe\x18\x01L\x0c\xca\xa2b\x10\xc3\xc5 \x8c\x8cy\xcf\xc9E\xc9\xa0`\xdbM@\xca +\x83\xc0\x08%\x96\x85\x03L\x9e\x18\xf760\xb2\xfd~\xe5\xac\x13\xdd\xa2\x92E\xb5b\xe6\xf5\xa7f\xfa\x16m\xd3H \xdf\x1f\xdba\xab\xa27R$\x86\xd0FW\xbb\xaemW^\x91.Z\xc7Kq\xfa\xb4\x86\xe3\x96\x81\xd2\xb7\xbb\xb2\xa1g#\x10\x84B\xaa\xe1n\x7f\xeb\xcfw\xa3\x0cq%@^\x0d\x90:%\xe0'\xc3 a\x0e\xc9XQ\xcd\x122uKH\xd1.\xa3\x9eFm\x13\xa3_Bi\x0d\x13rtL(\xa9eB\x92\x9e\x19ue\xa7VH\xd44\xa1\x8c\xae e\xb5M8B\xdf\x84\x0c\x8d3\xeaP\xbcRSuN(\xaauB\xb6\xde X\xcd3\xeae\xaa\x89buO(\xad}B\x11\xfd\x13\xf25P(\xa9\x83B\x92\x16\x1au5I\xe9\x80\xd3C\xe1t\x9a(\x9cX\x17\x85\xd3i\xa3\x90\xa1\x8fB\x8aF\x1a\xf5d\xa7\x80\x00\xbcN\n\xa9Zi\xd4\x9b\xec'R\xf4R\xc8\xd3L\xa1\xb4n\n\xc9\xda)\x94\xd2O\x01\xa3\xa1B\xda\xd0\x11\xa9\xa5B\xc6(3IS\x8dz\xe3&\xc5\x04RW\x85\xc4\x12'\xea\xabA_\xd3\xd1,Rc\x85T\x9d5\xe8 \xa1\xc1Bi\x1d\x16\x12\xb5X\xc8\xd4cc\x0e\xb1\x9a,\x14\xd5e!M>\x04\xac>\x0b\xe9\x1a-`D\x89#\xb4Z@\xfa\x8fLX\x16\xd4m!;\xf8i\xfa- k\x9e\xa9\xe3\xc21Z.\xe0#^D\xd3\x854]\x17\x12\xb4]H\xd2w\x01\x7fS\xf2t^H\xd6z!\xa6\xf7BI\xcd\x17rt_8B\xfb\x85t\xfd\x17\x907)\xa6\x03\x03\xd6O\x9a\x1e\x0c\x855a\xc0\x163\xf2\xc4\xa6\xeb\xc3Aw\xb7\xf78\x8d\x182u\xe2\xa0C\x9d\xea#\xaa\x15C\xa6^\x1ct\xc8\xcd\xdc^P3\x86\x0c\xdd8\xe8lL\x05\x82\x98VA\xea\xc7\x10\xd7\x90\xa1\xac\x8e\x0c\x18-\x19\x12\xf5\xe4\xc8\xfd\xb7\xd2\x89\x045e\xc8\xd0\x95\x83\xce>^\xbd=Cj\xcb\x90\xa9/C\xba\xc6\x0c\xb9:3di\xcd\x10\xef\x9a\x00\xa1\xdbA\x82v\x97\xa2;C\xae\xf6\x0c9\xfa3\xc4\x83QT\x87\x06\xac\x16\x0d\xa5\xf5hH\xd0\xa4!K\x97\x8ev\xd2Qm\x1a2\xf5i8R\xa3\x86\xc2\xed=Q\xab\x86d\xbd\x1a\"\xa3\xa9\xb8\xa6+\xecr\x7f\xfb?\xd9\xfd|\xb7\xa4\xdd\xfevS/dV\x06ke\xb0\x91\x9bc\xedK\x8a\xe1\xe2\x9e\xa9v\xc3#\x03\\1\xe6Q#\x80AQ\xf6\x1e\xdf\xd7\xeb\xa6\xe2\xfb\x0e\xb1\xd0\x80$\xdd\x80\x91\xa4K\x92\xee\xc4H\xd2\x8d:$I\x17H\xd2\x9d\x18I\xba$\xe9:\x8d$]e$\xe9\x92\xa4K\x92.I\xba\x11\x87$\xe9\"\xf5\x04\x92tI\xd2%I\x97$]\x92t\xa5\x91\xa4;1\x92tI\xd2\xb5\x8c$]\xb7\x91\xa4\x1b1\xac\xc4E\x92\xaem$\xe9\x86\x0e$I\xf7\x9bI\xba\x1f\x8cF:Wu\xef\xd8\xd7\xe7\xacY\xb4\xa2\xb9\x0fBjl*G\x9cx\xb9\xa9\xea\xe6\x9a}\xe5\xea\xf5\xe3=~'\x8e\xbb\xe1\xec+\x8f\xcb\xb3\xd1\xc9.\\e\xc7\xa2\x05*\xab^\x9a\xa2\xcar\x1e;\xe8P&\x00\x97\x93(z\x06?\xaa\xf1\x0c\xf1v\x1e%WA\xdf,\xdafU\xaf\xf3\x97_\xcbD\xd9\xaf\xa5\x93\xe9\xcbQ9\xd6Mr\xbe\x04\xdb\xeb.\xb44\x1b\xa1\x9ec\x94s\x99\xda\xfd\xb8V\x80\x9d\x0d\xf4\x06\xc7^\x83\xaf\x96\xde\xcb\xc1\x89\xec\xfb\xbc\xde\xe4\xb8\xb3n>\x89\x97\xc0\xb6Zz\xe6+\x17\x1d\x93!\xbf\xe1\xb5\xbf\x9e\x88:\x9a\xe9\xdce\xc5\xd9s\xe1+\xbf\x89\xe8\x12]\xd7\xdb\x83'_8\x16\xdd\xba\x062L\x0d\xef\x02yjo\x19kT-\x9do\x9fpy\x86\xbc\xee\x8e\xfb1\x14M\xbc\xb3X-\xa7\xf8\xab\x06\xea\x86\xb3\xee9xR\x07/\xba\xb6\xef\x9f\xebv\xeb<\xc2\x91\x9f|\xdcW\xc0\x91\xb8]\x95\xffr\xdcg\xc1\xce\x85nm\xbf`r\xca\x1fz\x08='\xe1'\xc4l\x1f\xe3n7\xd1V\x13\x95\x00B[\xdc\x8c6lb\xa3w\x12\x19\xf6\xb3\x81]\xd5\xf7JvT\xbb\xde\xfcc\xcfz~\xa6~\xf78\x93\xbb\x1fH7\xa1\x0do.\xb85\xb2\x91{\x8b\xf8^>\xa2Y0)\x826-l\xdb\xcel\xbc\xe1T[\xe4\xde\x17G\x06s\xb6\xb9\x88m\xb1go\xd8z\xc3\xb7\x17\x8b%\xe2\xf9\xeak\x07\xda\xde\xc5\xc4s\xf8\x97Jny\xf1\x0cj\xde\x1b\x19\xba\x87}\xa3\x1a\xf1R)g_jG\xb3\x8dw\xaa\xf6NG\xaaV\x93\xfd\xd0\xea\x06\xd6W\x97\xaf\x87\x07\xc3\x0c\xe3z\xf8\"\xee\x99\xeb\xf6\xb8\xdf\xa0\x8b\xb6S>\xe4\xe8\xb5S\x95\x1f\xc6\xe1b\xc0-E8;2\xcep\x983>\xb4\xdb\xb1\xdc\xc1q_\xc7v\xb2_\x83?V\xddp\x93b_f\x93\xb0\xc8\xf6\xed\xfb&\x9b\x0e\xe1\xc2\x0f\xa3\xdc\xe7c\xdc\x06c\x12w\xb5\xdb\x8c\xfa\x7f\xf9Y\xb2j]Y\xd3\xa4\x8b\x17\xd6&\x1f\xe2\xee\xa8\xe9\x98\xf1a\xd1\x93H\xf6C2\xddG\xa3\x81}\xa3\x90\x19\xb6T\xc8\xc2)\xb7\xd3\x90\x17p\xf4\xca\xfe\xa7U\x8c\xe4|'\x88w\xc7\xda1\x9dd\x9e\xed\xba\xe1?\xfd~\xf6\xabn5IeX2^\xd5\x9bG\xb2\x0d\x08\x8f`\x89\xd1\x9e\x0f\xd3\x17(K\xc5\x0f\x8d\xfe\xe9u\xc8\x91\xd8!\x1a7\xc4\xec~\x11\xc1\x0cS\xf1B\x89\x0fz\xbda\xb1B\xd7,i2N\x88\xc7\x08'\x98\xa0\xd7\x1f\x1e\x1f<\x12\x1bL\xc3\x0552\xe4/v\n&\x98\x8a\x07\x06w\xb5H\xc1\x02\x93p@\x0b\xf7\xf3;\xc4a\x80(\xfc\x0f\xbb\x8b\x05\x02\xfb+\x86\xfb\x1d\x87\xf9e\xe0}E\xb0><\xce7\xc5\xf5\x02\xfd\x93\xe3\xddo\xdb \xf0\xbdSa{'\xc0\xf5R0=4\x9e7\xc1\xef\x82}x\x1c\xcbK\xc2\xf1 \xb8\x1b\x05\x16\xc3sLg\x86z\xe3T\xec\xce`u\xfe\x97`\x14\xb7;\x1a\xb3\x0b\xe2u\x88!P\xf4[\x1a?JJ\xc2\xe7d\x14%\x1e\xe7\xef\xb0\xa3\xd8\x1c\xa6d\x89\x98\\hg <\x1e\x97\x84\xc5\xc5\xd0\xb7\x1c\xe4McmN\x7fQ\xd4-\x07q\x83\xc0\xc6!1\xb4\xad\x0c\xd2\x86\xa4\xa9\xa2\x08[\x02\xba\x16\xe2%rP\xb5\x90?\x8f\x9cW\x08IK\x0b\x1e\x1eA\xc3D(\x019\xcbB\xcd\"\x91;\x1a-C\"e\x18\x94\x0c\x87\x90E\x82\x9a\x8e\x8c\xe1Q1/\"V\x04\x0dKB\xc2rP\xb0\x04\x04,\xc8B\x05\x8a\x15<\x0f\x8fx\x95B\xbb\"\xd5p\xfe\x96\x8ep\xf9vm\x88\xa2[9\xc8\x96\xc1\xb2\x9c\x0eC\xa8V\x0e\xa2\xe5\xbdP\x18\xcdJE\xb2,\xec\xca\xe9\xcf\xffi\x8b@\xb0\x02\xe8U:r\x15\xc6\xaaRp\xaa)2\xe5t\xe7\xc3\xa8R\xf1)\xf0\xee\xb4\x10\xc7\xa6Rq\xa9\x04L*\x19\x8fJ\xc3\xa2\x02\x04P\xa8TX\x1c\x04\x8b?%cOI\xb8\x93\xa7\x929x\x93\x86\x80\x02\xcf\x90\xeb\x97\x1c\x9cI#K\xee\xb6\x1d\xc2\x98\xd2\xf1%o\x07\x16\xc4\x96\x02\xb8R6\x92T\xa2\xcd% Hx\xf4\xc8\xbc\x86wUWm\x19g\xddd'z r\xc8M\xc7-\x07\xa1/\xcf\xa7f\xce\xf2\x07\xb5\xc9\xf8\x8cE\xd0{\x15\x98<\x11\xba\x8b\x14\xfe\xc5\xdd:d3zVu\x8b\xd9$\xc7@0\xac\xa6Sp9\xfb\xf0\xcf\xa6\x07L\x85\x15\xb73[z\x8f\xac\xb6\xd4\xe2\xc4\x03<\xed\x89\xedy}\x85\xa3\x98\n\x9bJ\xda\xfe\x0e&\x91\x87\n\x8b\xb0.\xd5[\xbc^\xa9\xc8\xd5=T\x9b\xbe\x85\x9e\xf1\x13\xc5\x83W\xdd\x9a\xf1\xf4X\\\xcb\xf3\xa6\"\x0d\xb7\xb7\x89\xb0\xf6\x98W\xb1\x98\x17x\xbc\xdd\xd3x\x1c\x86B\x05U\x86\xf9\xf4\x01\x19\x19\x91\xb3O\xec\xde\x17\x98\x99\xe0\xabq\x8bJ\x0f*:\xc6\xf7\x9d\x82\xd2&\xfa\xf2\xd9\xc0f\xc89\xd5\xf5l\xf2Q\xd6@\xbc\x08c\xbc\xc5{\x11\x98\xb6\x91\xad\xae]\xadz\xc6\xa1\xed`Z\\;uD\xf9hyf\xd8\x1cAT\xe5C60]\x19\x19\xcaf\xbfe]\xbd0\x7f\x93\xef\x9fE\xd5\x88\xfa\xa8\xe9\xc5;\xd6\x98\xc0\xef\x9baFw\xf6!w!\xbdmDK\x1cB\xa8\xe6@\xf7\xbd\x08\xf5'\x96\x18\xcf\xa9\xfb\x13\x07wF\xaf8\xc2\xbb\xa9\xb756\xba\xf2X\x83 \xf8\xa0\x165\xdbo\xb7`\x0d,\xec73\n@\xcd\xed\xd9\x7f\xbaX\xc1\x86\xad\xb8\x81\x804\x15d\xbe\x96\xa4P\xa1\x1e\x10u\x11\x11\xe7\xdb{`\xd5\xe2\x0e\xaa\xdd\xee\x01\xa3h\xa39\xe3\xf9\xa1XZg\x88\x88\xca\x16\xda\x02\xef\xf6Ln\xf4S7\xcbzQq6H\x96:\x82\xf2@\xdd\x90lwu\xb3\xd8\xec\x97\xb37C\xa5\xae2h\xc6\xb3;& \x04K\xca\x10\x83\x19\x8bp\x9bu.\x1f/\xfa\xd9\xdd\x9aUA\xf6\xb6\x1d\xeb5+\"\x1f\xaf\xf1y\x14\x8f\xdc\x99~\x9a\xeau\xd3v3!\xc8<\x8d\xd3K\xa8\xc8\x1c{co\xdbv\xc3\xac\x1c*\x8e\x1b\xd8\xb1\xcf\xac\xeb\xb1\xeft}\xf4\xfc\xc6\xd5\x16\xda\xd51\xf7\x930\xf1#\xae\xc1\x14\xe7$\xf9\xe2\xf9L\xf0\x87\xbaY\x881G+\x86F\xcf\xfb\xe5'\xf8\xf1\xec\x0f?\x15\x8d\x06\xaf\xd6\x93a\xdd\xbfjo/\x96r<\xf6B\x7f\xd0\xf4/>\xff\xf4B\xbeG\x9f\x8b7n\xffB\xe5\xe4Rg\xae\xd9\x00\x10\xf5\xfb\xed\xb6\xea\xee'\x11\x1b\x10\xa4\xf7\xf2\x1cY\xe0\x9a\xf5\x06[\xd2\xe9\xbdD\x8bT/jy\x81g.\x89[\x0d\x87\xc4C:\xfcI8\xa9FY\xc8z\xd5\x8b\xef\x97\xf9hB\x9f\xd6\xee\x98\x1a)_,_\xce\x8b\xa7\x0f1\x90\x93\x15\x9c\xef\x7f\xff\xe3\x8f\xdf\xfbI)\xe8\xf7\x8b\x05\xeb\xfb\xd5~sJD\xca\x0e\xbcm\xfc\x01X#1\xc6\xcc\x16\xd9\xc6\x91t\xb6\x0b5\xf8\xcc<\x1d\x89*\xcbV\xf1F\x11^3lY\xff\xb1]\x89\x16X7\xeb\x0d\x0b\x10\xf4r\x98.o\xde\xe1\xadS%\xd1\xfb\xc5\xb1~\xfa1 \x1f\x07}\xdbg\xa7\x12\xc9L$3:\x98D2\x1b#\x92\xd9iEH\xe6\x83\x80OIf\xf5\x8e\x1d\xae\xe2Z\x06\xa2\x87K\xb7\xf7\x8e):\x1d\xc3y\x94$A%?|[1\x18\xb1:N\xddo\x12\xf0L\xc03\x01\xcf\xda\x08x&\xe0y4\x02\x9e9\x01\xcfn#\xe0\xd9\x18\x01\xcf\x04<\x13\xf0\x8c\x1c%\x11\xf0<\x18\x01\xcf\xb6\x11\xf0L\xc0\xb3\xc3\x08xv\x1dC\xc03\x01\xcf\x04<\x13\xf0<5\xff\xa7-\x01\xcf\x04<{\x8c\x80g\x02\x9e x.\x03<\xa7\xf3\xbf\xef\xa7\xfc\xafV\x0dZ\x0d\xb3\xd8*\x15\xb4\xab35Y\xc8\xc7\x8f\xdei\xd5\xaa\xcdlfE\xd1\x01=o;9\x81\xa0\x9a\x97r-'\xbbz\xce\xaa\xe5\xb1\x00U\x11\xf6w\x8c\xc3\xb9\x83\xf1\xd5\xd1\x90\xf0\xae\x145d]\xe4\x1b\xda\x00\x9b3i\xf9`ry\x8a\xf9\x8e\xb3\x06\x95z\xcaO\x14\x04\xe2}1\xd1\"\xdeW\xd9\x89\x83\x1b'U\x89\xf7-\x11E\xe2}\x89\xf7\xfd\xf5\xf3\xbe\xfaA|n(\xda\xe7\x95!\x14\xfd\xdc\xaf\xf5\xa2{\xa3N7o\xfb\x11o4\x00\xb0\xfa$T\x0f\xfb\xe0\xda\xdeYx6j]\xd7\x9fY\xa3\x166\x89\xb1\xfa\xd3Q\x13\xfe\xc1z\xf9\xeb\xc3'\x8c\xaf\xaf(\xfa\xd8G\x0b\xfb\xca\xd1\xdd\xe3\xc0l\x8eb}\x07\xc4P\xae\xfc\xb3A\xd4%\xeb\xb9\xe9\x81t\xdb\xb3\x87\x85\x8e\xf4\xbd\xca\xf41\xe1\x12\x1d\x9d\xad\x9a#\xf6xFT\x1e\x90\x1a\x95\xb1T\xce(\xe8\xcc-6\x05f_K\xf3F\x10g\x8e \x83;\nW u\x0f\xe7\"\xfc\x11d2HA\x87\xc9\xfb6\x1f\xc9\"A2\x8f\x14t\x95\xbbWsQ. \x12\xd9$H\xe5\x93\xc2-{xOa\x19%(\xcd)\x01\x8eU\x82\x92\xbc\x12\x1c\xcd,A\x1e\xb7\x04\xa5\xd8%\xc8\xe2\x97\xc2\x8f\x03~\xef\xe5\x13pLpB\x96 N\xc33A\"\xd3\x04y\\S\xac\x0b\xc6\xb1MP\x96o\x82\x04\xc6 \xd29'\xc8`\x9d\x10]&v?\xe5\xa3\x99'\x88qO\x80\x1f\x9e!\xf8'H\x1c\xc5%sPAo){&cKY\x90\x89\x82$.\nJ\xb3Q\x90\xc9G\x85\xdb\x15r\xff\xe3LN\xca\xeb\x8f#\xf7=.\xc3K\x01\x1e\xfb\x01\x0c7\x05i\xec\x14\xc4\xe0\x84L\x86\n\x10~\x03\xc2h!\x9e\n\xb2\x82\x8b\xe7\xaa\x00Q\xcb\x0c\xbe\nr\x19+\xc0E\xf5h\xd6\n\xf0\xbc\x15 \x99+@sW\x80\x0bz:\x7f\x05I\x0c\x16\xc4\xf6&.\xc2bA*\x8f\x05\x99L\x16\xa4qY\x80\xb8 \xb1=\x88\xa3\xe7\xe39-(\xc8j\x01\xa6h\x81\xa7\xac\x1c\xb7\x05\x18v\x0b\x8e\xe0\xb7\xbc\x0e9b\x7f\xe1\xa2\x1c\x17DY.\xc8\xe5\xb9\xbc\xde0\xfb #\xb8.\x88\xef#\x9c\xcewy]E\xf7\x0f\xceb\xbf\xbc\xde\xa2\xfb\x06\x97c\xc0\x00\xc5\x81A\x06\x0b\x06i<\x18\xe40a\x90\xcc\x85A|;\xdcX)\xb1\xbc\x0e\x96\x11\x83\x1cN\x0cRY1\x08W<\x87\x19\xf3:C\xed\xff\x9b\xc3\x8e\x05\x1f\x08\xcc\xbe\xbf\x05\x192\x88qd\x10f\xc9\xbc\xe7\xe42fP\xb0\xed&\xb0f\x90\xc4\x9bA`\x84\x12K\xc9\x01&]\x8c\x7fk\xd3!\xf9\x91\xd2F\xa7)\x90\x0eM\xcd\xf4-\xda\xa6\x91\x82\xbe?\xb6\xb2G\xe6c\xcaN\xfdx;\x8f\xdfum\xbb\xf2\x8at\xd1:^\x8a\xd3\xa75T\xa8\xdc]\xbdS\xbe\xdd\x95\x0d=\x1b\x81 \x14R\x0dw\xfb[\x7f\xf2\x1be\x88+\x01\xf2j\x80\xd4)\x01?\x19\x06 sH\xc6\x8aj\x96\x90\xa9[B\x8av\x19\xf54j\x9b\x18\xfd\x12Jk\x98\x90\xa3cBI-\x13\x92\xf4\xcc\xa8+;\xe7B\xa2\xa6 etM(\xabm\xc2\x11\xfa&dh\x9cQ\x87\xe2\x95\x9a\xaasBQ\xad\x13\xb2\xf5N\xc0j\x9eQ/SM\x14\xab{Bi\xed\x13\x8a\xe8\x9f\x90\xaf\x81BI\x1d\x14\x92\xb4\xd0\xa8\xabI\xae\x07\x9c\x1e\n\xa7\xd3D\xe1\xc4\xba(\x9cN\x1b\x85\x0c}\x14R4\xd2\xa8';7\x04\xe0uRH\xd5J\xa3\xded?\x91\xa2\x97B\x9ef\n\xa5uSH\xd6N\xa1\x94~\n\x18\x0d\x15\xd2\x86\x8eH-\x152F\x99I\x9aj\xd4\x1b7\xb9'\x90\xba*$\x968Q_\x0d\xfa\x9a\x8ef\x91\x1a+\xa4\xea\xacAO\x08\x0d\x16J\xeb\xb0\x90\xa8\xc5B\xa6\x1e\x1bs\x88\xd5d\xa1\xa8.\x0bi\xf2!`\xf5YH\xd7h\x01#J\x1c\xa1\xd5\x02\xd2\x7fd\xc2\xb2\xa0n\x0b\xd9\xc1O\xd3o\x01Y\xf3L\x1d\x17\x8e\xd1r\x01\x1f\xf1\"\x9a.\xa4\xe9\xba\x90\xa0\xedB\x92\xbe\x0b\xf8\x9b\x92\xa7\xf3B\xb2\xd6\x0b1\xbd\x17Jj\xbe\x90\xa3\xfb\xc2\x11\xda/\xa4\xeb\xbf\x80\xbcI1\x1d\x18\xb0~\xd2\xf4`(\xac \x03\xb6\x98\x91'6]\x1f\x0e\xba\xbb\xbd\xc7i\xc4\x90\xa9\x13\x07\x1d\xea\x1c Q\xad\x182\xf5\xe2\xa0Cn\xe6\xf6\x82\x9a1d\xe8\xc6Agc\x8e\x10\xc4\xb4\nR?\x86\xb8\x86\x0ceud\xc0h\xc9\x90\xa8'G\xee\xbf\x95g$\xa8)C\x86\xae\x1ct\xf6\xf1\xea\xed\x19R[\x86L}\x19\xd25f\xc8\xd5\x99!Kk\x86x\xd7\x04\x08\xdd\x0e\x12\xb4\xbb\x14\xdd\x19r\xb5g\xc8\xd1\x9f!\x1e\x8c\xa2:4`\xb5h(\xadGC\x82&\x0dY\xbat\xb4\x93\x8ej\xd3\x90\xa9O\xc3\x91\x1a5\x14n\xef\x89Z5$\xeb\xd5\x10\x19M\xc55]a\x97\xfb\xdb\xff\xc9\xee\xe7[@\xee\xf6\xb7\x9bz!s4X\x8b\x80\x8d\xdc\x1ck_R\x0c\x17\xf7L\xb5\x1b\x1e\x19\xe0\x8a1\x8f\x1a\x01\x0c\x8a\xb2\xf7\xf8\xbe^7\x15\xdfw\x88\x85\x06$\xe9\x06\x8c$]\x92t'F\x92n\xd4!I\xba@\x92\xee\xc4H\xd2%I\xd7i$\xe9*#I\x97$]\x92tI\xd2\x8d8$I\x17\xa9'\x90\xa4K\x92.I\xba$\xe9\x92\xa4+\x8d$\xdd\x89\x91\xa4K\x92\xaee$\xe9\xba\x8d$\xdd\x88a%.\x92tm#I7t I\xba\xdfL\xd2\xfd`4\xd2\xb9\xaa{\xc7\xbe>g\xcd\xa2\x15\xcd}\x10RcS9\xe2\xc4\xcbMU7\xd7\xec+W\xaf\x1f\xef\xf1;q\xdc\x0dg_y\\\x9e\x8dNv\xe1*;\x16-PY\xf5\xd2\x14U\x96\xf3\xd8A\x872\x1d\xb8\x9cD\xd13\xf8Q\x8dg\x88\xb7\xf3(\xb5M\xc9\xa2mV\xf5:\x7f\xf9\xb5\xdc\xb0\xe4\xb5t2}9*\xc7\xbaI\xce\x97`{\xdd\x85\x96f#\xd4s\x8cr.\x13\xbd\x1f\xd7\n\xb0\xb3\x81\xde\xe0\xd8k\xf0\xd5\xd2{98\x91}\x9f\xd7\x9b\x1cw\xd6\xcd'\xf1\x12\xd8VK\xcf|\xe5\xa2c2\xe47\xbc\xf6\xd7\x13QG3\x9d\xbb\xac8{.|\xe57\x11]\xa2\xebz{\xf0\xe4\x0b\xc7\xa2[\xd7@\x86\xa9\xe1] O\xed-c\x8d\xaa\xa5\xf3\xed\x13.\x8f\xbc#o\xc5%\x0e\xef\xc7P4\xf1\xceb\xb5\x9c\xe2\xaf\x1a\xa8\x1b\xce\xba\xe7\xe0I\x1d\xbc\xe8\xda\xbe\x7f\xae\xdb\xad\xf3\x08g~\xf2P)\xdf\xd6\xbd\x14\x81\x0f\xf2\xde?S\xfbZ\xb4\x8d\x15F\xf5\xf9\xe6\x1eq[\x84\x8c\xb7|\x8e\xd2\x8d{ \xf8\xd2\xca{\x9e\xc1\xf0\xd3g6\xaaq\xb7\xc9h\x8b\x8c\xca\x0b\xa1\xcdtF\x1b\xb6\xcb\xd1{\x96\x0c;\xe7\xc0\xae\xea{%i\xaa\xfdu\xfe\xb1g=?S\xbf{\x9c\xc9}\x16\xa4\x9b\xd0\xd6:\x17\xdc\x1a5\xc9]L|/6\xd1\xe4\x98\x14X\x9b\x16\xb6mg\xb6\xf8p*9r\x97\x8d#\x839\xdb\xc6\xc4\xb6\xd8s=l\xf2\xe1\xdb\xf5\xc5\x12\x08}\xf5\xb5\x03m\xef\x97\xe29\xfcK%7\xd7x\x065\xef\x8d\xc4\xdd\xc3\xbeQ\x9b\x05,\x95*\xf7\xa5\xee\x0f\xdbG\xbc\xc3\xb6\xf7TR\xb5\x9al\xc2V7\xb0\xbe\xba|=l\xe4`\x86\x88=|\x11\xf7\xccu{\xdco\xe7E\xdb)\x1frd\xdc\xa9\xca\x0fc|1\x98\x97\x02\x9f\x1d\x19g8\xcc\x19\x1f\xda\xedX\xee\xe0\x98\xb2c;\xd9g\xc2\x1f\xabn\xb8I\xb1\xaf\xbeIXd\xfb\xf6}\xefM\x87\x87\xba\xf5\x1c<\x86r/\x11\xdfV\x1b\x93\xf8\xab\xfdm\xd4\xff\xcbO\x9f\xc3\xe4\xed\xd2\xd9\x0b\xef\x1e\"\xe2~\xa9\xc9\x9f\xe1<\xdd\xa5\xdaO\xcdt\xd3\x8e\x06\xf6\x8d\xe2s\xd8R\xf1\x11\xa7\xdc\xbbC^\xc0\xd7\xc9:\x1f_1l\xf4\x9d ^Tk\xc7\xdc\x95y\xd8\xeb\x86\xff\xf4\xfb\xd9\xaf\xba\x19%\x95a\xc9xUo\x1e\xc9\x9e#<\xc2@F\xbbBL\xe7\xa0,\x95u4b\xab\xd7!G2\x8eh\xb6\x11\xb3\xd5F\x84iLe\x19%\xab\xe8\xf5\x86e\x18]S\xb2\xc9\xec\"\x9eY\x9c0\x89^\x7fxV\xf1HF1\x8dM\xd4|\x92\xbf\xd8)Lb*\x8b\x18\xdcB#\x85ALb\x0f-\xb6\xd0\xef\x10\xc7\x1c\xa2XC\xec\x96\x19\x08\xc6\xb0\x18[x\x1cS\x98\xc1\x12\x16a\x08\xf1\xec\xe0\x94\x0d\x0c\xf4O\x9e\x8f\x1dc'`\x05O\xc5\x08\x9e\x80\x0dLa\x02\xd1,\xe0\x84\xf5\x0b\xf6\xe1q\x060\x89\xfd\x83\xe0\xd6\x17X\xe6\xcf1w\x1a\xea\x8dS\x19?\xc3\xf0\xf9_\x82Q\xb6\xefh\xa6/\xc8\xf2!\x86@\xd1\x8fk\xfc()\x89\xd5\x93Q\x94,\x9e\xbf\xc3\x8e2z\x98\x92%2y\xa1m,\xf0,^\x12\x83\x17\xe3\xecr\xf8:\xcd\xd09\xfdE\xb9\xba\x1c\x9e\x0e\x02\xbb\x94\xc48\xba2\xfc\x1c\x12\xdd\x8a\xf2r \x9c\\\x08\xce\xc8\xe1\xe2B\xfe<\xdaa!\xfe--xx\xde\x0d\x13\xa1\x04\xbe-\x8bk\x8bD\xeeh\x8e\x0d\xc9\xafa\xb85\x1c\xaf\x16 j:\x9f\x86\xe7\xd2\xbc\x8f\xe2\x91;\xd3OS\xbdn\xdan&)\x98\xa7qz \x15\x99co\xecm\xdbn\x98\x95\xfa\xc3q\x03;\xf6\x99u\xbd\xf7\x0d3\xbby\xfa\xe8\xf9\x8d\xab-j\xa8c\xee'a\xe2G\\\x83)\x84Fb\xb1\xf39\xc5\x0fu\xb3\x10o\xc0\xb6\xdf\xb6\xfd\xf3~\xf9 ~<\xfb\xc3OE\xa3\xc1\xab\xf5d\x80\xf0\xaf\xda\xdb\x8b\xa5\xdc\xf2\xe8\x85\x1e\x1a\xf7/>\xff\xf4b\xc9\xab\xf5s\xdeUM\xbfb\xdds\x0d\xfd\xe8\xb3\xd7l\xc0Q\xfa\xfdv[u\xf7\x93\xa8]4\x8bv[7\xeb7\xd7\xd5\xfaZ{\xd0`P/kP\xb3^I\xbew\x0c\xc4A`\xae\xd3\x1b\xbah\x9c\xff\x15\xcf\xc4\x18(\xa9\x90I\x9ar[-E\xd4\xbfT\x9d\x1eH\xee{\xd6\x8d\x9b8\xad\xeb\xcfl\xbe9T\xbbcj\xf4u\xb1|\x19,\xa4>\xdeP4V\xcc\xbe\xff\xfd\x8f?~\xefGq\xa0\xdf/\x16\xac\xefW\xfb\xcd)\x19\x9c\xe9\xdd\xb0\x8d?\x00\xce\"Z\xca\x0dooxW\xb9@\x1fe\x08A'F\xef\x81l+\xd7\xed\xb5\xb8\xce\xf4KY\xbd(t\xd7\xa7Z\x94\xe8J\x1d}\xa7m\xb7lhx\x1d[\xc2\xaak\x03\xbc\x84\xea\x96\x17\xac\xfe<\xaa@\x06\x85\xd3\x90C\xcf\x9a\xa5G\x80Q?\x9d48\x1f\xe4%\xe6\xb0\xb2\x19\x03\x1b\xddj\xa1\xde\x12*<\xac\xf137V\xfd\x9c\xc7\x98X\x9c\xb4NW&\xe0\xb3Zyo\xc4]\xc5\x9f\xf9\xd9M\x18\xd8\x96gj\xb1\xa8\xf78\xd1}Lo\xab\xf8g\xdd\xc9\xc6\xe5z\x84\x82Uq\xf41c\x8d\xa0\x9a\xf6\x81\xc1\xa8\xdf2\xfeE\xf4~\xfc\x8bD_\xbaC\x9d,T\x92\xa1\x13\x1e/\xce%\xbe\xae\xe0mg\x97|\xd8#\x8ff\xf7\xc1\xaeX\x9any\xf6\x13\xc1\xda\x04k\xc7\x1e\x19\x82\xb5 \xd6\x9e\xda\xa1\xe4\xa4[\xd0\xe5\xf8\x19\xa3n\x94N\xbb:\xfe\xd9\x04u\xe2!|\xcb\xe4\xd084FL\x05\xbf\x1d\xb7K\xb1\xe0\xc1\xd1\xf2\xc8\x83\x8fO(\x01\xe1\xb3_ \x08\x8f\xb5\xe6\xd1\x08\x08' \xdcm\x04\x84K# \xfc\xd0\x08\x08' \xdcg\x04\x84\x13\x10.\x8d\x80p\x02\xc2 \x08' \\\x19\x01\xe1\x04\x84\x13\x10N@8\x01\xe1\x04\x84O\xcd\xffiK@8\x01\xe1\x1e# \x9c\x80p\x02\xc2\xcb\x00\xe1\x06\x9e\xb0\x9c\x84\xbe>\x9f\xb6\x03p\xed\xc31f\x90\x89$\xb1x\xebH\x0d8\xe8\xd9\xd3\xd0\xd6Z\x02\x1bX\x03B\xb6\xd1\x88\xf1\xa9\xa9bB\xb6O\x18\xdc8lL\xc8v\x89(\x12\xb2M\xc8\xf6\xaf\x1f\xd9\x96/\xfd\x00\xa2})\x7f\x1f\x08l \xc9\xe8\xd3a\xdb.\xf7\x1b\xa6\xc6\x0dN^\xfaR\x1fyi\x1f\xf1h i;\x14\xb6y]A\x14\xd3h\xea\xc5\xa7\xc6\x9b\x879\xe8\x18\xa2\xceAJ,\xcd\xcd\x865k~\xe7\x9f\xe0B\xc8 (!d[}\xfdF\xd7\x8aa~\xeftXu\xe3\x9c\x12\\f\x10\x0b\x1d\xdb\xc8)\xfa\xe0V\xb7Cc6\xb7\xca%\x1a,y\xe5I\x1d^\xe0\x16vl}\xc3\xbe\x1e\x15\xd2_u+xs]\xad\xd17Z\xdfNy\x92\xebN\xde\xd6\xed\xc9n\xe47\x8f\x8c\xf7\xf9\xf8c\xdd\xa6F\xcc\xe3\xe9\xb6n\xd7]\xb5\xbbs\xcdo\xb6]\xb5\xd8\x9c\xaekSo\x80\x9bzY(\x9a\x01\xac\x18\x101\x05\xa9\x90\x8b\"]\xbc\x99\x7f\xcb^\xbc1\xe31\x15\x13]v5Z\x08\xf8[T\x9b\x8d\xba\x0b\x9fYW\xaf\x1c_\xb9S[V\xdcG\xbaT\xfd\xa7\x1b9x{<\xd1z\xd5\x7fz-\xc7\xaa\xb3h\x8d\xa3U\x15\xad~\xf8\xee\x17\xb5\x088\x9c\xc4)\x14\x8c\xad\xdc\xf0\xe1Q\x05\xe3/u\xe3\x0c\xc6\xb6n\xea\xed~;\x8e\xea\x87\x98\xdc\x05X\xc6\xe1C~\xd1nw\x1b\xc6\xa3\x9bd\xc8\xb8i\x1a\xc9\x1aNy\xb1\xb2]\xc7vU\xc7n\xd6U`\x87\x89o\x1d\xc3KU\xa8?U\xfd\xc1d\xd2\xd6\x84o]\x99\xcf\xd5}\x88\xa6\x02X\xee;3\xad\xa2*+c\x13\x8aa\xcf\xab5s>\xe8\x9e\x93\xd8W\xb6\xd8\xf3G\x16\xc4sU\xa8\xe2AT\x95U\xaaG(\x8a\xd8\xe0\xad\x18\xbbQ%\x8a\xc5\xce\xcd]\x1b\xf3\xf2\xd7\xc6\xa2\xaf*e\xf1\x17\x96\xb2%k\xdam\xf8\x10\xe4M\x17\x16\x8b\x802\xa4;\x0c/d\xecu[\x8fK#*\xe0\xed'\xa67o\xa9T\x15\xcd\x94B\xd5,\xa1\n\xef\xe8\xa3*\x11\xdbW\xf8\xdd\xfb\xeb\xf3\x97R\x91\xd3\x0dQI[\xb5\x84\x96.\x1a\xae_\x11\x03(\x16\xde\xd4\xd8R\x05tn\xfc\xe0\xe1\xc3nL\xfd\xf0\xad\x0d\xb7\xf7\xb0n\xd7\xad\x9cv\xf7\xab\xc8\x98g\xeeg\xc6^m]\xbd\xff\xf8\xc8\xad\x18\x1b\x08\xca\xea>\xb6K\xd2\xb0G\x92\xeebb\xdd\x7f\xfc\x81\xf3md`\xec\xbd\xf4\x80\x1eU\x8eO\xb9\xc7\x9f\x9c\x033\xba\xd0\xbe\x9f\x8f\x82T\x06\x9a\xfe\xae\xdeI-\x16\x16\xac\xe1]p\x13\xefj\xc4m\x87\x15\xab\xb7\xf7P\xc1\x1b9\xe9\x11\x18\xe7V\xbb\xdd\xcd\xa6n>\x05\x16Z\x1c9\x94\x95@`\xcd\xefo\x96Z\xb9\x89ui\x91G\x19\xd3\xe6\xf4v\x11\xc3\xb5\xc1\\\x1bn%\xca+Q@+f\xce\xed{Fc_wu\xe7!\xeab\xc5y\xb5\xdb\xbd\x15\xf1\x9d\xb4\x9eH\xe3\xa9v;\x8f7y\xab\x0e~\x1b\xd6u\xc9KL\x14p\xeb\"+\xcd\xaf\xce\xa6\xb0&\xde\x10k\xbc\xd4U\xa2\xab\xb9\xe4_\xd5\x82-]\xae\xab\xcb\xd73\x7f\xb4P\x8b\x16jE\x9fx\xec\x8b\x9b\x16j\xd1B-\xb7\xd1B-i\xb4P\xeb\xd0h\xa1\x16-\xd4\xf2\x19-\xd4\xa2\x85Z\xd2h\xa1\x16-\xd4\xa2\x85Z\xb4PK\x19-\xd4\xa2\x85Z\xb4P\x8b\x16j\xd1B-Z\xa855\xff\xa7--\xd4\xa2\x85Z\x1e\xa3\x85Z\xb4P\x8b\x16j\xe1\x17j%\xf1\xdd\xe6\xdf\xbf\xec{\xd6\xfdS\x9d\x16\xc9\xc5\xad\xb1m\x17\xf4\xad\xd4\xd8\xe1\xa3_\xae\xdaRi\xb3\xc7T\xb7`M\xc0\xeaU^\xd6`L7x\xe5{\xa9<,[\xa6\xe6V\xe4\x94Xe.\xf6L\xf7\xe3\x1a\xb6\x1f\xf4\xb5i\x1a\xdeAQ\x80f\xbf\xd9\x98sM/\xea\xe2\xd1\xf5O\x8f\x17DW\xc5\xf4\xc9WY$zX\x85\x8aN\xc0`f0\x8a\xebO8\xf5)G{\nkLY\n\x93\xbc\x84\xc7aT_*\xa0.ejK\xde\x19y\x9c\xb2t\x94\xae\x94\xa5*A\xb5\xd9\xf8\xa2\x88\xd3\x94r\x14\xa5\xd0\x87VH\xa99N\xab\xc9Pk\x8a\xe85\xc5\x15\x9b\xa8fs\x02\xd5\xe6T\xba\xcd \x94\x9b\x14\xed&W\xbd \xf6\xe11\xfd\xa6\xa0\x82\x83\xd5p\x12U\x9c\xe2:N\\\xc99Z\xcb\xa1\xf5>\xd1\x92\xe5i;NW\xb4\xde'G\xe5\x89\xe9\xb4\xdb\xb1\xdc\xc1i\x9d\x8e\xed\x98\x9c~\xffc\xd5\x0d7)\xf2\xf18\x0d\x8bl\xdf\xbe\xcf\xc7\x00\xbbu\xf00\xca\xf1\xa6\x1a\xa5\xa5\xa0[zhI\x99\x9a\x89\xdcr\xfd\x1e\xec\xf1N z\x86\xbe\xfd\xaca\x91\xaf\x11\x0e\x03\x91\xc9\xf7\xde\xf8\xadd7\xc4\x9c\x8d\x07\x0f\xaa\x13\xd9_S\x7f\x03\xf8\x8a;\x8c!\x9dc\xdf\xee\x1b\xd5bZXolg]|\xb8\xecK\xc7g\xb7\xfcEv?O\x0f\xf6Y\x91s\xc1\xf5l'\x15;\x14\x16\xb7\xf3\xc3\x89\xeaO\xdb\x1ec\xa2\xe5\x195\xd2\xb6\xc7e\x83\x1b\xdf\xb0\x97\xb6=.\x11E\xda\xf6\x98\xb6=\xfeun{|0\xe1<\xf9\x83\x7f\xde\xd9\x8a\xd8\x95}\xc6d\xd2x\xe2\x0b\xf4\xdc\x8a\x9e\xfe\xb12f\x0d\x9e\xcc\xc0L\xffa2\xb5<\xb9\x8a>\xe0\xd1\xce0;\x82h\xdbC\x8c\xe3\x17\x1d\xab\xb8\xebcH\x19b \xae\xe7%^+G\xf3\xc92\xed\xdftFv\x04\xdc\xe5\x11\xbd\x0b\xebvU\xc7=\x13S)\x85\nLM\xbe\xb6.t0=+\xe7\xb2\xe5 \xb4n>\xb7\x9b\xcf\xee\xe7\xd8\xb6h\xc5\xfe\x93\xcc\xcb\xd6\xcb\x83yY\xf1\x82\x90\x93\xaf^w\xf3;\x0bu\xef\x9f\x98\x95`\xa9\xe3\xd7\xf8\x94\xd0\xb4O1#\x92\x9ew\xfb\x85|\xdbU\x93Bx \xa7\x0bK\xd8U-\xb4m\x16l'\x1d|\xa7\x96\x04|'C\xd0U\x03\x9f\xd0\xb7\x12\x8bv\xb9k\x18\xff\xd2v\x9f\x0e&\x04i\xce\x96\xe6l\xe3O\"\xcd\xd9\xd2\x9c\xadm\xc9s\xb6\x93\xe1\x0fj\xea\xd6\xe5\xe5\xc5t\xacFko\xb5\xd1\x0c\xee\xafa\x06w\xfa\xb9Q~\n4:c\x10\xe2\x8e|3\xa1r\xf09\x8c\xbc\x02\x15*\\\x19Sf{\x1c\xee+;rR\xd7v\xe5\xfa\x0e\xe8\xd5\x94\xae\x9cI\x988\xacW\x87/\x005(\xa7\xf9\\\x9a\xcf\xa5\xf9\\\x9a\xcf-\x1cE\x9a\xcf\xa5\xf9\xdc_\xe7|\xae\x19\x19\xc9}\x0e\x86\xff\xf1\xcf\xe3\x9a \xa2\xfe\x90\xf6\x1d~\xd1\x13\xb6j\xcfx\xed`27;8yb\xaa\xf4H\xe7eg\x01\xb1\xed!F\xe6\xdfl\x86\xf0\xa3L}\x03\xf5R\xf5O\xb3\x048\xb3i\xf7\xa9\xc9G/\xbf\x94\xba\x00\x7f\xdeo\xab\xe6y\xc7\xaa\xa5\xec\xba\xec\xa41\xc1\xab\xdb\xad\xe4\xe8B\xbc7\xe3V\xcb\xab*\x85\xe8\x18B\xc5\xe0\x1d\xab\xfa}w\xda\x89\xea\xab\xe9\x04\xad\xb9&T\x0b\xf5ZP\xb7N&!i\x17\xb5\x9c\x9c\xf0\xae\xc5\x02\x80xp\xdb/M \xf2\xfc\x95\xe3\x83F\x96\xb5\xfd\xd2 \x1aX1abV\x8e\xe1\x1bQ_\xc0\x7f\xf1\xbamnx}T37\x0f\xe3\xb2\xe2\xec\xb9\xf0\x15.\xea \x98\xc8e?5\xf2a\x18\x17\xd2\xdd\xac\x18\xbb\xe1\xed'\xd6xz\x96p\x7f\xa6\xcc\xdb\xab)\x8b\xf4m\xcab=\x9c\xb2%k\xdam\xe8\x00T\x8c\x85U[\xf1(\x14p\x15\x9f\xe34\xf6\xba\xad\x1b\x95iH\xbc\x1cAF]\xe7\x93P\x153\x03\xb0\xaaYB\xe5\x07\xfaM\xe1CIM\x00\xde\xbd\xbf>\x7f)Wz\xaa\xa3\xf5\x92\xc9Z&\xc3\xb8h\xb8\x9e&\x18\x12\x90\xf4\x8e\xa9>\xdb\xf4Z35\xcb\x17\xbap_\xaf\x9b\x8a\xef;\xd6\x0f#\x121X_\xb7\xebV.\xe5\xf2\xadL\x8e\xf7ko\xeb^\x8eiW\x8c\xe9\xe8\xc9\xb0\xf5*\x88\xe6ka[7\xf5v\xbf\x85u%\xbe\xf9\xeb\x85'\x1f\x06\xa8\xd4Y25\x91\x1e\x97\x84\x13X\xf9\x1f(]\xf2\x0fC?1\xa4\x1d\xd1#\xa0e\xc5+%7\xa9\xa1\x8f\xcf\x19I@$\x01\xc5\x1f\x04\x92\x80H\x02\xb2m*\x01\xf9Z\x8f\xfc\xbe\x1b\xbe\xaf\xf2\x85\x9f\xf1;\xef\xea\xf2\xf5<@\xfa\xed`\xfe\x97$\xa0\x83\xf8\xfc\xd6% L\x8f\xa0\x8c\xd2\xafR\xfaU\xb7Q\xfaUi\x94~\xf5\xd0(\xfd*\xa5_\xf5\x19\xa5_\xa5\xf4\xab\xd2(\xfd\xaa\xbfMS\xfaUe\x94~\x95\xd2\xafF\x93\x88R\xfa\xd5\xdc\xc8Q\xfaUJ\xbf\xea0J\xbfJ\xe9W)\xfd*\xa5_\xa5\xf4\xab\x94~\x95\xd2\xaf\xfe\xe6\xd3\xaf\x12R\x9f\xc6+\x13R\x7f\xc2\xe0\xc6apB\xeaKD\x91\x90zB\xea\x7fKH\xfd\x8b_\xacu\x8a\xffT\xe7G\x12\xa5\x0c\xa4\xd9\x1c\xb5\xaf\x1b\xf5\x9cI\x8a\xf0\xb6\xdd\xab\xe6>\x00\xacr\xf6\x94\x9b\xb4\xb2\x83\xbbay\xa4\x93\xc5\xd7\xbf=z\x14\xbf(2\xe7\x03\xea\xa3\x93\xfbx\xbe+\x1b\xa5\xf7\x83\xf4\xd1\xd2\x1d\x05\xd1G\x11z\xec\xe5s\xf1\xf90<\x8f\xbd\xbaWL)\x8b\xcdG\x82\x19@\xe6\xb1\x159\n\x97\x0f\xc2\xf2\x99%@\x80\xf2\x08L>zq\x1c\"\x7f\x04 \x9f\x80\xc7\xf3\x08\x1c\x1fD\xe3\x83\xfd\x93\xb2\x18\x8f\x05\x18(>\x1aQ@\x01\xf1\x087\x18m\x10\xd2Qx\x04\xf0^\x16wG\xc2\xeey\xa8{\xac\x1f*\x8c\xb9\xe3!w\xef#Q\x08pG\xa1\xa9(2u\xc6\xa2\xce\xfc\x11\x85J\x14j\xa9\x9e\x8a(T\xa2P\xddF\x14\xaa4\xa2P\x0f\x8d(T\xa2P}F\x14*Q\xa8\xd2\x88B%\n\x95(T\xa2P\x95\x11\x85J\x14*Q\xa8D\xa1\x12\x85J\x14\xea\xd4\xfc\x9f\xb6D\xa1\x12\x85\xea1\xa2P\x89B%\n\xb5\x0c\x85\x8aH#~q\xb8\x07\x8a\xc9\xbfm\x9dr\xe4\x96\xff\xe0\xc3KJpG/\xe4\x0c]\xd5\x88\x1f\xd6]\xbb\x0fm\xd9\xf4'\xf1\xfb\xab\xe1x\x8de\x8dj\xe0\xba\xab\x1a.\xf3\xa6\x83re\xfa\xdf _4\xf3\xf2\xc4\x04\xe4\x91bF\xaaR\x8fC\xff\xb2n\\\x81\xf9\x1fL\xde\xcf\xc0\xdc\x8f\xa3\xedk\xa9y\xb6\xff\xfa\x97\xaaWQd\xfe1\x1c\x18\xc1Z\xb4 \xe7\x11\xcaC\xf9,\x8f#>c\x95\x11U\x96\xc8\x1c\xdc\xd1|\x07\x8f\xa8\x9d\x80\xab6 g\xcd\x8c\xa5*\x9fAg\xee\xe9\xaf\xc0\xf7`i\x05\x14\xe2*(d(\xa1\xe1\nT\xfc\x0e\xad\x86B)E\x142U\xd1\xa0C\x11\\\xb42\n\xc7\xab\xa3\x90\xac\x90\x06]i\xe5&I%\x85\xd2J)$\xaa\xa5\x90\xaa\x98\x86[\xf6\xa0\xa6bUS(\xad\x9c\x02N=\x85\x92\n*\x1c\xad\xa2B\x9e\x92\n\xa5\xd4T\xc8RT\xc3\x8fC\xa5vO\x89>7'QV\xe1\x84\xea*\x9cFa\x85D\x95\x15\xf2\x94\xd6X\x17\x8cS[\xa1\xac\xe2\n \xaa+\xa4+\xaf\x90\xa1\xbe\"\xba\xcc\x1f\x10\n,\x94Pa!\xa6\xc4\x02~x\x86Pd!q\x14\x97\xac\xcc\x06\xbdI\xd5\x16\xa1\xceBB)\x0b\xaa\xb4\x90\xa4\xd4Bi\xb5\x162\x15\xdbp\xbb\xea\xe3\xaa-\xe4+\xb7^\x7f\xe2\x8a1\xf5\x16\x8a)\xb8\x80\x17\"\x01\xa3\xe4B\x9a\x9a\x0b1\xb9$S\xd5\x05\x84\xdf\xc0Tm!\x85\x17\xb2\x82\x8bWz\x01Q\xcb\x0c\xc5\x17rU_\xc0E\xf5h\xf5\x17\xf0\n0 U`@+\xc1\x80\x0bz\xba\"\x0cI\xaa0\x84\x94a(\xa5\x0eC\xaaB\x0c\x99*1\xa4)\xc5\x80\xb8 !\xc5\x180\xe7\xe3\x95c(\xa8\x1e\x03\xa6h\x81\xa7\xac\x9c\x92\x0c\x185\x19\x8eP\x94\xbd\x0e\xe5\xbc`@U\x86\xd2\xca2D\xd5e\xc8U\x98\xbd\xde\xd4\xf7ox*\x00\xa14CXm\x86,\xc5\xd9\xeb*\xa8DC\xae\x1a\xed\xf5\xa6\x86\x91\x81I\xb7r\xaa4\xa0\x94i\xc8P\xa7!M\xa1\x86\x1c\x95\x1a\x92\x95j\x08w#\x10Q\x0f!AA\xc4\xaa\xd6\x90\xa3\\C\xaaz\x0d\xe1\x8a\xe7\xa8\xd8^g\x96F\x8c}dpjv\xf0\x81h\xd6aE\x1b\xca\xaa\xda\x10S\xb6!\xacn{\xcf\xc9U\xbd\xa1`\xdbMP\xbf!I\x01\x87\xc0\x08E+e\xd7U\xb7V\xa99FEo\x10\xc6d\xcb\xbbe\xac1\xba\x99\xd3\xd7p8ie\xd1I\x16\xd2\xcaH+#\xad\x8c\xb42\xd2\xcaH+\x03\xd2\xcaH+\x9b\x18ie\xcaH+#\xad\xcc6\xd2\xca(\xe1\xf41\x88G\n\xde\x91\x81vP\xc2iJ8M \xa7\xb1hFQ,#\x07\xc9\xa0\x84\xd3\xbe\xc3\xa2\xe8E\x02v\x81I\xa7\x9c\x82[P\xc2iJ8\x8d@'(\xe14d\xe2\x11 h\x04%\x9c.\x80>D\xb1\x87\\\xe4\xc1\xfb\xae\xa1\x84\xd3\x87F \xa7\xfd\xb8B\x1cUH\xc5\x14\x12\x10\x85d^\xe3\xf3(\x1e\xb93\xfd4\xd5\xeb\xa6\xedf:\x85y\x1a\xa7\x97P\x919\xf6\xc6\xde\xb6\xed\x86Y\xcb\xbc\x1d7\xb0c\x9fY795t\xf3\xf4\xd1\xf3\x1bW[\x14S\xc7\xdcO\xc2\xc4\x8f\xb8\x06SHO\xdb-Y7\x9f\xa8\xfcP7\x0b\xf6\x12\x16m\xbfm\xfb\xe7\xfd\xf2\x13\xfcx\xf6\x87\x9f\x8aF\xa3\xf4~\x11\xe25\x1d\xd8.\xe2c\xcf:\xdcn\x11\xd2\x91\xb9\xf3\x93\xcd\"\xa6>\x9e\x98Z\xd3^\x11Qt\x85\xf6\x8a\xa0\xbd\"\x0e\x8fA,\xb0\xc6\x08^\xc6R\xa1\xa5\xa03\xb7r\x15\x98\xca-\x0d/A\x1c`\x82\x0c\x88)\\\x01\xca\x7f\x93\x0b6A2\xdc\x14tE\xf9o(\xffM.\x00\x05y\x10\x14\x94\x02\xa1 \x0b\x86\n?\x0e\x94\xff&\x0d\x8e\x82D@\n\xf2 \xa9X\x17\xccQ\xa0\x14\x94\x85\xa5 \x01\x98\x82th\n2\xc0)D\x97I\xf9o\x94%CUAo\x94\xff\x86\xf2\xdf\xcc\xac\x0c|\x05x\x86\x080\x10\x16\xa4\x81X\x10#\x1d2\x81,@\xf8Edj9\x12\xce\x82\xac\xe0\xe2!-@\xd42\x03\xd6\x82\\`\x0bpQ=\x1a\xdc\x02<\xbc\x05H\x80\x0b\xd0\x10\x17\xe0\x82\x9e\x0esA\x12\xd0\x05\x94\xff&\x9e$&\xf8s\xf4|<\xf4\x05\x05\xc1/\xc0\x14\x8d\xf2\xdf\x94\x85\xc2 \n\x86A.\x1c\xe6\xf5F\xf9o(\xff\x8d\xcf\x92\x013H\x86\xcc\x80\xf2\xdf8-\x07@\xf3:\xa3\xfc7\xc6(\xff\x8d\xc3h\xaf\x08\x87a\xe7/\x80\xb42\xd2\xcal#\xad\x8c\xb42\xd2\xcaH+#\xad\x8c\xb42\xd2\xca\xe6FZ\x99\xc3\xb0\xa5$\xad,\xdc\xaeH+;4\xd2\xcaH+\xcb\x9e~#\xad\x8c\xb4\xb2\x90\x91Vf,Z4\xd2\xcaH+\xb3\x8c\xb42\xd2\xcaH+#\xad\x8c\xb4\xb2\xc1J\xb5\xdd\x87\xd4\xcah\xaf\x88\xc1=\xed\x15a\x19\xed\x15A{E\xd0^\x11\xcaN\xbbW\xc4\xc1=\x93K\xe1\xa7\x8b\xcd\xf3\xb7\x8a\x98-Z\x9f\x1dC\x1bG(\xa3\x8d#h\xe3\x88\xd1h\xe3\x08\xda8b\xb4\xa2\x9cH\n#\x92\xc4\x87\xd0\xc6\x11\xc7\xb2 \x19\x1cH\x11\x06$\x9d\xff\xa0\x8d#\x8e\xe1=RX\x8f\x0c\xce\x836\x8e\xa0\x8d#h\xe3\x08,\xa7Q\x94\xd1\xc8\xe13h\xe3\x08\xdfaQ\x0e#\x81\xc1\xc0l\x8b\x90\xc2^\xd0\xc6\x11\xb4q\x04\x82\xa3\xa0\x8d# \x93\x95H\xe0$h\xe3\x88\x02\x1cD\x94\x81\xc8\xe5\x1f\xbc\xef\x1a\xda8\xe2\xd0h\xe3\x08?\xbb\x10\xe7\x16R\x99\x85\x04^!\x99UH\xe3\x14h\xe3\x884\x16\x816\x8e\x18\x8c6\x8e\xd0\xf6\xeb\xd98B\xe6\xc8\xf5\x95\xfd\xe9\xfb\xe0F\x11\x07[D\x88\xcfh#\xbf\x9d\xcd*\x92\x9aA{V\x15\xda\xf9!%Z\xb4\xf3\x83\xb2\x13\x077\xbeg\x01\xed\xfcP\"\x8a\xb4\xf3\x03\xed\xfc\xf0\x1b\xde\xf9A\xc2}\x81\xfd\x1e\xac\xf0}\xecY\xf7'y\xb8,x\xcd\xecm\x1f\xe4\x9fe\x8b\x17\xf1\xd3CQ\xb3\x1f\x80=B\x19\xdcM\x85\x14\xe9\xa5\xfe\xcc\x1a\x18\x86;\x07{F\xa8\x8b\xeb_\x1f\xf1~\x11cDm\xe3\x0f@\xac|\xfb\xfd\".\xde\x1c\x0cIg\x9bB\xd4\xbd\xde\x05\x8c}\xad{\xcf\x1a\xfc\x9eI\x0d Zl\x1f\x86\xa4\xcc\xbd\xcf\xd7\xd4b\x08\xe3dG3k\xbc\xad\n\xe8\xad[\xed\x97\x12\xa5T\xe5\xfc\xf5\x9b\xd5\xf6\xa3\x84\x88\xa0^\xaa'v\x86\x12\xb9x_e\xb2\xef\xcdoG\xfa\xea\x7f\xdeo\xab\xe6y\xc7\xaa\xa5|w\xd9\xec\xcd\xb8G\x9c\xd3\x85\xfd<\x1f]\x0c\xf3\xfda{U\xe50w\xd1y\xfe\x8eu\xdb\xba\xef\xeb\xb6\xf1f#\n=\xe9\xca\xbc\xcf\xbb2|%\x02\xed\xf6r,\xa8\xfe\x9a\xd2S\x02\xc36'\xed\xd0\x7f\xcb\xbdz\xc4\xd7\xa8\x9f\xe5\x8aE\xc64-\xd3O\xcf\xc1r\xf1\xa7v\xa5\xae4;\x9d`r\x82\xc9\xe3-\x9a`r\x82\xc9m\x9bJYQ\x06\\\x0d\x1e\x8f\xe3\xbf\xf5\xe8\xf7\xea\xf2\xf5\x9b\xb7\x99\x01\xbb'<\xb8\x96\x1c\x06\x873@\xdcM\x7f\xeb\x1f\x1f7\xfc]\x94b\x8c\"\xdcQ\xd9\x05\xcf\xde\x95\x80\xb7c\xe8\xb6o\\6Z\x1cd\x8e\xa1\x82e\x91m\x1f\xb0\xfd\x0dj\x98\x07j\xfb1\xedh[9\x12\xd1\x8e\x02\xda\xd8\x02d\xc1\xd9Q4\x9bG\xc0\xec \x96\x8d-\xba\xb7U\xe6\x01\xd9~\xb0+\x10\x8bl\x18\x1b\x87Q\x16\xa0( \xa2$\x88\xd2\xf9;A\x94\x96\x11DI\x10\xe5h\x04Qr\x82(\xddF\x10\xa51\x82( \xa2$\x88\x129J\"\x88r0\x82(m#\x88\x92 J\x87\x11D\xe9:\x86 J\x82( \xa2$\x88rj\xfeO[\x82( \xa2\xf4\x18A\x94\x04Q\x12D\xf9\xa0\x10\xa5$\xcd\xec\xdeh.\xb1\x9d\x1e\xa24$F\xbc\xd8J\xca3\xf0\xe4Q\x85\xc4\xa1\x92\xa7!N^l\xc5c\xd6\x05\xf2\x10\x0e\xc2\xe1_\xd4\x91\x07)\x08\xb5\x07\xf9\x1a\xd4\xc0\xc9\x81T\xedfJ\xb4\xc7'&J\x8f\x14-\x99\x84\xc86\x9e\xaf\xe49\xe7\x99(\x1d\x17\xa5\xe3\x8a\xd3\x0c\x94\x8e\x8b\xd2q\xd9\xe6L\xc7u\xf0\x18N9\x12\xdd\xf3\x16\xc0I\xcc[\x81\xf6aVF\x18 a$\xa3\x11FB\x18\xc9h\x84\x91p\xc2H\xdcF\x18\x891\xc2H\x08#!\x8c\x049J\"\x8cd0\xc2Hl#\x8c\x840\x12\x87\x11F\xe2:\x860\x12\xc2H\x08#!\x8cdj\xfeO[\xc2H\x08#\xf1\x18a$\x84\x91\x10FB\x18 \x16#\xb1\xd2vL\x12q\x19\xa8\xe2\xd8,b8\xb6\x84\xd2p\xe5\xe68\xa24\\'\x0cn<\x81\x14\xa5\xe1*\x11EJ\xc3Ei\xb8~\xc3i\xb8\xac\xec5/~\x11/\xe4@\x1e\xae\x8f=\xeb\xect2v\n.\xcb\x8fag,\x1eR{: !-oOL\x08\x1e)\x08\x19L\xf3\xc3\xf3y\x94\xc7\x0f\xbeDs\x81% ?\xa8\xed\x9c\x0fG\xb6\xa2MY\xc9\xb3\xc6\xbb!\x9ed\xff\xe6\xc6\xb1\xbc`1\xa2IY1Qx\xa4\x14\xd44:\xb6\xf1\x07P\x1a\x1f\x05\x994\xdb\xd9o|\x0c\xbc\x9b\x15\xfa7\xf1\x8b\xe9\xc6\xca0\xb8\x84\x0f\x950\x85\x13#;=\x16\x9e\xb5\xcb\xa9\xed\xaa\x8e5<\x1a\xe0b\x05vn\xa2\xa8\na\xca\xeet\xd0xw\x1fD\xb5\x01}\xf5w\x96\xc0\x99\x1a)\xfby<\xba V\x18\xde\x8c~gEs=P\xeat\xb3\xc5\xf9\x14\x0b\x19p\x90\xben\xd6\x1b\xab \xbb\xfdQFF\xca\xc8H\x19\x19)##\x1c\x9f\x91\xd1\xbd\xb3\xa7\x19\xf4\xc431*\x92l\x18x]]\xbe\x9e\xf9#\xa8\x8c\xa0\xb2\xd8\xab5\xfe\xf0+#\xa8\x8c\xa02\xb7\x11T&\x8d\xa0\xb2C#\xa8\x8c\xa02\x9f\x11TFP\x994\x82\xca\x08*#\xa8\x8c\xa02e\x04\x95\x11TFP\x19Ae\x04\x95\x11T65\xff\xa7-Ae\x04\x95y\x8c\xa02\x82\xca\x08*{4P\xd9\x00\x01\x15\x06\xb3\xa2D\x19e1LK\x11GY\x0cO\x18\xdcx\x1b\xa5,\x86%\xa2HY\x0c)\x8b\xe1o \x8b\xa1\x1b\xd5}\xf1\xcbH)\x07\xd2\x17\x1a(n\xbe\x87s\xdd\xa8\xe7L\xfcV\xdd\xb6{n\xbf\xbf\xd5\xc4/\x1f\xb2\x19\x0e\x03\x02\x17\xbe\xfb\xc4\x04\xe0q\xd3\xbbEq\xbe(\x83\x1b\x95%\xf0\x10Z\x11\xfa6\\\xce\x10\xc8\x1a\xc7X\xcbP\xb7\x11\xe6\xb6`A\xf3h[?k\x1b\xbd\xd7Gs\xb6Q\xca\x16[\x84<\xc2\xb6\x1c_\x8b!\xe3\x12\xc18\xe2\xe2\x88\x8bs\xfdN\\\x9ce\xc4\xc5\x11\x177\x1aqq\x9c\xb88\xb7\x11\x17g\x8c\xb88\xe2\xe2\x88\x8bC\x8e\x92\x88\x8b\x1b\x8c\xb88\xdb\x88\x8b#.\xcea\xc4\xc5\xb9\x8e!.\x8e\xb88\xe2\xe2\x88\x8b\x9b\x9a\xff\xd3\x96\xb88\xe2\xe2m\x1a\xb5\xd6\xf1\xc6\xd0\xac\xa6\xf3\x899{\xb0\xcc\xc2B{\x87\xa5D\xcb3\x1bD{\x87\x95\x0dn|\xd7+\xda;\xacD\x14i\xef0\xda;\xec\xd7\xb9w\x18\x8a\x18\x0f\xa0\xe1\x1f\xf4\xb123\x96\x93\xfd\xeeMr\xb3J#\xdb\xb3\xad\x8b\xa6\xbb\x84\xd9\xee\x9e\x98\n?R>\xdb\n\x8dm\xfc\x01\x08\x96o\x0fg\x07\xd4\x9bh~;\xc3\xbd\x8aO\xa5[\xc6\xfcr\xe0\xa2\x93d\x9a\xbb\xcaC\xae\xbap\x8dC\xa9\xc80\xc9\xc8\\8\xba\xdeL*\\\xab`\xe9c\xa5.v\x9f\x0e6Z\x13et\x9e\xc2\xber\xd65\xd5&\x1aQ\x0c\x0dn\x8d\xfa\xcf\xb5_Q\x06\x85\xe3\xd5\xbd\xbf\x14\x9c}\xe5E/\x7f\xad\x11\x94p\xdd\x1b^\xfb\x9f.g\xad\xf4\x19\xb0h\x9bF\xbd\x12\xe5\x17r\xa8n\xd1\xc7\x1c\x10\x8f\xba\xb0\xbb\xaa\xbf\x9b\xf6\xec\x87\x16\xea\x86F\xf3vH\xa3!\xca\xac\x0cSre=\xaf:\xef]\x1e\x0dq\xbfGC=\x14\xa3\xc5\xbb\xb1\xd1.\x9a%\xfbj\xda\xd0\x00\xb5\x99\xc7_\x8e\xbdD#\x0b\x00s\xa3\x8d\x9d\x05\xaf\xd6*\x10~:A\x19k\xbc\x0f\xe4h\xbf\xfeX\xb1f\x19\x8b\x14\xaf\xd6\x85#\x95R\xf5\xebj\x0d\x1d[\xb1\x8e5\x0b\x06O\xe54\x86\x9e\xdaxf\x1eY\xf5\x81\x13\x9al2\xc6\xf8\"$\x9f\x0dE\x13\xfd\x9b\xba\xb2\xb5\xb4\xe2g\xb4\x9c\xda\xdb\x1bg\xabk\xe9y\xed\xb1\xae\x98\xee\xf3c\xb7\x99m\x9f\xad\x16MI\xa4Bq\x93\xf5\"\xe2L\xbbz[7\x9f2\xfa\xcd\xd07f\xbc\xbf\x8c\xf4\x95\x88\xc8\x9a\xf7\x88\x1a\x8fn\xaa\xf9W\xf63\xd1PV{\xb9\xb4\x06\x16\x15g\xeb\xb6\xab\xff]\xce&:=V{~\xe7Z,\xa7\x0c_\xa0W\xd2OtVa\xd16\x9fY\xd7W\xa8y\xaab3>\xce\x1d\xeb\xdb\xae^\xd7M\xb5\xd1\x0b\xceuwc\x95\xcf\xe9s\x182,o<\x93\x9d\xca\n\xb5\x85\xc8;\x13\xf7\xbe\x94\xae0\x8f\xd7\xb5F\xa8\x87J\x86O\x8a\xdf$e\xac\xd9oc\xdd\xcas\xb8|\xff\xe1\xfa\xe6\xea\xfc\xe7\xf3\xab\xf3w\xaf\xcfo\xae\xffvy~\xf3\xf1\xdd\x87\xcb\xf3\xd7\x17?_\x9c\xbf\xc9:\xff\xea\xfc\xf2\xed\xdf\xb2\xce\xfc\xd7\x8f\xef\xaf\xcf\xb3\xce\xbc:\x17\x7f\x0d\x9ej\xd6\xcb\x1eUg\x0c\x9f?Z4\xbe/\xe1]\x8b\xbc\xf1\xd6\xea\x81X\xff\x1f\xb8-/\xd5:\xcbq\x0c>\xcbf\xb1\xdb\xdc\x9bt\x13\xe3b\x85\xc0Db\xe4\x9a\xf2\x86\x86\xaf\xf9\x8f}\xcb\xc7%\x04\x05\xae\xa9\x9aB\xb4\xa2V\xff\x83\xbej$\x85\x8b2\xf4\x13\x8a\xeaL\x95\x1dL\xfd\x8f=\"\xa2\xcc\x12\x9cz\xb0BG\x9f\x92K]\xc2\x83\xba\xcd\x07\x08\xdf\xf7r\x88\x10\xc0\x7f\xa5\xa9\x95\xc4\x03U\")\x8c\xb6\xd9\x04V\x8e*\x1bR:\x89`\x18\xc5\x15\xd1/\x99\xac%m\xcf\xaf\x86\xa2\xfb\x07L\xb2\xe5\xc5\x9e\xf9x\xec^\xa9\x1c.\xc3\x18\xc4j\xeb=\xfa\x85#\xf1q\xb6\xac9[~\xe3rZ_9o\xab\x9e\x83*\x04\x88\x13\xa3\xa5\x96\xf9\xb6\x8e(\xaa.\x82L\x19\x13\xb9\x98\xf5\x8e\xb2V\x8ej<\xa6nT\xa5E\xb8\xab\xdbv\xcf\xa1\x82\xben\xd6\x1b\xa7\xbb`\x02\xaf\xd0\xf7\x13\xa5\xdf\xa2\xf4[\x94~K\xdbo;\xfd\x96\xaf\xf5H,p\x02\xdf\xa1\xb68tyy1e\xf8f\x87\x8c \xb5\x86\x1f(\x9f\xd6\xecW\xca\xa7\x85\xe9\x19\x94Q>-\xca\xa7\xe56\xca\xa7%\x8d\xf2i\x1d\x1a\xe5\xd3\xa2|Z>\xa3|Z\x94OK\x1a\xe5\xd3\xa2|Z\x94O\x8b\xf2i)\xa3|Z\x94O\x8b\xf2iQ>-\xca\xa7E\xf9\xb4\xa6\xe6\xff\xb4\xa5|Z\x94O\xcbc\x94O\x8b\xf2iQ>\xad\x87\xcc\xa7\xc5[K&V\x1c\xd7t\x1a\xf5\xf4\x89\xb4(\x95TZ\x9e\x1eJ%u\xc2\xe0\xc6\xdb(\xa5\x92*\x11EJ%E\xa9\xa4~\xcb\xa9\xa4^\xfc\xa2a\xfe\x7f*_\xae\xa4R\x92\x963\xb9\xa4D[\x9b`q)\xf9\xa4.G\x8c\xeeQ\xa7\x91*J\xf4E\x93AE\xc5\x07<\x87\x96\x9c\xeb)\x90\x15)\x96\xd1\x89\x07\x89\x1a@es:,\xf6\xb1\xb9\x9c\xbeA\x90\xb19\x9c\xa2\x19\x9c\xa2e:\x84kS\xb27\xf9s7e\\\x18\x91\xb7)\x9c\xb5\xc9Q\x97\x8c\x9cM\xc1\xe7\x10\xa2\xcf\"\xa0\xb25\xf1\x00\xa4e,\x9ay ZRe\xf1\xf2*C\xe5\x1c\x88\xde\xd7\xd1\x10\xcd}\xb4\x18\xe5:\x1az\xfd\xbc#\x9d\xb0\xcb8>\xfd \"\xcf\xc0\xaf7>\xd1\xec\x02\x88\x84' \xd1\x19W\x82c\xf3\x98\xc4\xb2\x94\x14\xcdQ\xa2\x9d\x1d\x97<)\x9e:\x89\xfa\x89\x99=\xfcs@\xfd\x84\xdb\xa8\x9f\x088;&\x93Q8\x8f\x11\xf5\x103{\xd8'\x00\x99\xb3\xe87\xdbC\xa0\xf2\x14!\xf2\xf4$D\x07_\xe1r\xf9\x89\xf0\xd9\x89\x12r\x13\xa5\xd7\xf9\xb8\xbcD\xe6c\xf4\xe8\xacD\xdaQVN\"\xffwT\xac\xe7\x0b\xf6z\xd1X\x8e\xef\x95\x12\x99\x88By\x88\xb0EA\xe5 Be \x8a^\x11\xd1\xa1\x1c\xb6\xb0\xe3r\x0f\xe12\x0f\x15\xb8\xe7G\xe7b\x96n\xe2\x8fMJ\xb6\xa1\xe8\x0dQ\x16\xcf4\x14\xcd\x83\x93qv<\xcbPn\x8e\xa1\xcc\x0cC\x05\xf2\x0bahec\xd1\x98&\xe4\x16Bdn\x80\x07\xc9+\xf4\xed\xb3\n}\xe3\x9cB\xbbxF!\xe4S\x88\xe8\x1c\x95\x1dL=cs a2 \x9d\xa8\xb0\x91g\xa1l\x06\xa1\xbc\xfcAy\xd9\x83\xac\xbc\x0c\x85r\x07\xc5\"\x96\x997\x08\xbck\xfb\xbcY\x8309\x83tiS3\x06E\x9bY\xe8\x9d\x94\x9e+(1SPj\x9e\xa0\xa4,AI9\x8223\x04\xe1re\x14\xce\x0et\xd2\xdc@\xdf>3\xd0\x03\xe4\x05\xfafY\x81\x109\x81\xa2O(.\xcf\x8e\xee\x1fR\xb2\x01\xe1r\x01\x95-_~\x16\xa0@\x0e\xa0h\x11\xf5\xc5\xe3\xf9\x7f\xac\xb7\xccq\xd9\x7f|/\x17\xc9`\xa8\x97\x18\"]\x87N\xd0!\x8bsu\xf9z\xe6\x8b\xd2rPZ\x8e\xd8\x18\x12\xfb\xa1Di9(-\x87\xdb(-\x874J\xcbqh\x94\x96\x83\xd2r\xf8\x8c\xd2rPZ\x0ei\x94\x96\x83\xd2rPZ\x0eJ\xcb\xa1\x8c\xd2rPZ\x0eJ\xcbAi9(-\x07\xa5\xe5\x98\x9a\xff\xd3\x96\xd2rPZ\x0e\x8fQZ\x0eJ\xcbAi9\x1e2-\x87{\x19\xe6\xa6\x9e|\x99}\x83\xd4\x1c\n\x0f\x8a\x17\\\xb1\xaa&\x97\xc8\xb7\xc9 Rz!\xf6\x8b\x8a\xf3jq\xb7e\x8d\xe1,}\x8b\xb2_\x8d\x07\x0e\xeb\xb3\xe5\xb4\x84\xf5w;0w\xd5g\x93dD\xad\xd5\x1eBz\xb0J\xdbr\xfd\xc4\xc4\xea\x91.\xd8>\x08\x97m\xfc\x01\x84\xbd\xe8\x82\xef\xa4\x89-\xcc\x1e\xa3\x81I-\xf4C\xcd\xdb\xe1/\xb5\x7f\xe6r\x0c\xb6\xc5\xdb{\x8f\x1e\x17\xf6z\\F\xb8\xbf\x87\x08\xd3a0\xdc\x95\xf6y\x1a\xea\xec<\"V\xd7\xd0rz\xcc\x82\xfa\x91k\\\x0d\xf8\xd8X|\xe7)R0k\xbc+\x82\"\x0f\x03 \x1e\x08@\xa8\xdd\x80\xbb\xdd\x80\x9c55\x96\xaa|\x07\x9d\xb9\xa7?\x03\xf3\x01\xa5\x15p\x88\xab\xe0\x90\xa1\x84\x87+P\xf1;\xb4\x1a\x0e\xa5\x14q\xc8T\xc5\x83\x0eEp\xd1\xca8\x1c\xaf\x8eC\xb2B\x1et\xa5\x95\xbb$\x95\x1cJ+\xe5\x90\xa8\x96C\xaab\x1en\xd9\x83\x9a\x8eU\xcd\xa1\xb4r\x0e8\xf5\x1cJ*\xe8p\xb4\x8a\x0eyJ:\x94R\xd3!KQ\x0f?\x0e\x95\"\xd2\xa3\xcf\xcdI\x94u8\xa1\xba\x0e\xa7Q\xd8!Qe\x87<\xa5=\xd6\x05\xe3\xd4v(\xab\xb8C\x82\xea\x0e\xe9\xca;d\xa8\xef\x88.\xf3\x07\x84\x02\x0f%Tx\x88)\xf1\x80\x1f\x9e!\x14yH\x1c\xc5%+\xf3AoR\xb5G\xa8\xf3\x90P\xca\x82*=$)\xf5PZ\xad\x87L\xc5>\xdc\xae\xfa\xb8j\x0f\xf9\xca\xbd\xd7\x9f\xb8bL\xbd\x87b\n>\xe0\x85h\xc0(\xf9\x90\xa6\xe6CL.\xcbT\xf5\x01\xe170U_H\xe1\x87\xac\xe0\xe2\x95~@\xd42C\xf1\x87\\\xd5\x1fpQ=Z\xfd\x07<\x01\x00H\n\x00\xd0$\x00\xe0\x82\x9eN\x04@\x12\x15\x00!2\x00J\xd1\x01\x90J\x08@&%\x00i\xa4\x00 nB\x88\x18\x00\xcc\xf9xr\x00\n\xd2\x03\x80)Z\xe0)+G\x12\x00\x86&\x80#\x88\x02\xafCq`\x88*\x80\xd2d\x01D\xe9\x02\xc8%\x0c\xbc\xde\xd4\xf7ox*\x00A\x1a@\x986\x80,\xe2\xc0\xeb*H\"@.\x8d\xe0\xf5\xa6\x86\x91\x81I\xb7rT\x02\xa0\xc8\x04\xc8\xa0\x13 \x8dP\x80\x1cJ\x01\x92I\x05\x08w#\x10Q\x8f!AA\xc6R\x0b\x90C.@*\xbd\x00\xe1\x8a\xe7P\x0c^g\x16#\x80}dp4C\xf0\x81h\xd6a\xa2\x01\xcaR\x0d\x10#\x1b L7x\xcf\xc9\xa5\x1e\xa0`\xdbM\xa0\x1f \x89\x80\x80\xc0\x08\xc5\xac\x9dV2\xd7\x80\xee\x87D1\x93\xd3i\xd4\xfd\xa6\xb9(*^\xa9D\x14v\x1et\xaf\xc71[\xbdO\x9f\xce\xca+n\xb6\x14\xf1\xaf.E-\xec\xf6N\xd3\xe0\xb2\x1f\x0c\x1b\x9b\xe8\x95\xce\xc3\x1e'\xb0\xab\xfa^M\xed\xaa\x9dP\xfe\xb1g=?S\xbf{\x9c\x8d[\xc0\x846A\xb9\xe0\xd6\x13,\xf7\x9b\xf0M\x00p\x99!\xae\xea\x184-l\xdb\xcel\xc6\xe0\x9c\x05\x93\xfb!\x1c\x19\xccxJ.\xef\x1c\xd2\xb0\x1d\x83o\x7f\x0ek)\x93\xaf\xbev\xa0\xed\x9d-<\x87\x7f\xa9\xe46\x08\xcf\xa0\xe6\xbd\x99\xe6\xefa\xdfH%\x84-\xd5L\xe6\x97\xba?l\x1f\xf1i1{\xf7\x1bU\xab ?V7\xb0\xbe\xba|=.\x8c\xd7\xddW\xaf\xb2\xfa\xb9n\x8f[eZ\xb4\x9d\xf2!{\xeaNU~x\xcf\x88\x17\x8a\x9c\x1c\xb5#\xe3\x0c\x879\xe3C\xbb\x1d\xcb\x1d\xec\xf7:\xb6\x93I\xe8\xe1\x8fU7\xdc\xa4\xd8\xc8b\x12\x16\xd9\xbe}\xe3\x8aiw\xa6[\xcf\xc1c8d\x1c\xb0\x80\x1dT\xf2\x01\x97\x9f\x17s\xa8H\xdc!\xcaC@y\x08b\xd3\xfe\xf1\xee@Y*\x8da\xa6\xb0\xbd\x0e\xb1$FQ\n\x83\xf2\x10P\x1e\x82\xd1\x8a\xd2\x15)dE\x12UAy\x08\x8e%(2\xe8\x89\"\xe4D:5Ay\x08\x8e\xa1$R\x08\x89\x0c:\x82\xf2\x10P\x1e\x02\xcaC\x80\xa5\x1b\x8a\x92\x0d9T\x03\xe5!\xf0\x1d\x16\xa5\x17\x12\xc8\x05\xcc*\xfb\x14b\x81\xf2\x10P\x1e\x02\x04}@y\x08 \x930H\xa0\x0b(\x0fA\x01z J\x0e\xe4R\x03\xdew\x0d\xe5!84\xcaC@y\x08fVbM8V\xd1OV\xf3\x93\x94|\xcaC\x90\xa9\xd8S\x1e\x02c\xa7\xcbC0n\xf5%\xa5v9g?\xdb\x89\xfeT\xcb\xfb\x8f\xceB\xc0g+\xf2\xbfMV\x02pm\x96\xff\x89\xdd\xfbJ?S\x16\xb5\xa2_\xe9\x97\x96\xbd\x17\xbe-a\x9e\x0d\xf2\xbf\x9c\xb3[\xcf&\xb7d\x00L\xca\x81\x90\xa4/\x13\xf3\xb7\x8d\xfc\xa8oW\xab\x9eq\xf1\x9d<-.X\x9aC\xcf&\x9b\x97\xe4\xec\xa6\xef\x0d\xe3d\x06\xc7\x11DU>_\x1cg\xb3'\xba22\x94\xcd~+7c\xd3\x7f\x93\xfd\xdb\xa2j\x86\xcdU\xbe\xdc\xb1\xc6\x04~\xdf\x0c3\x86\xb3\x0f\x85\x0b\xe9m\xc3\xfa~\x0c\xa1\x9ac\xdb\xf7\"\xd4\x9fXb<\xa7\xeeO\x1c\xdcx\x1b\xdd\xd4\xdb\x1a\x1b]y\xac\x91\xb9}\xdc\x84\x9aM\xb6[\xb0\x16\xc5\xf7\x9b\x99\xca\xac\xe6\x8e\xec?]\xac`\xc3V\xdcp&\x1a<1\xa3q9\x11\xae\x1e\x10u\x11\x11\xe7\xdb{`\xd5\xe2\x0e\xaa\xdd\xee\x01\xa3h\xd3\x1f\xe3\xf9\xa1XZg\xc8\xfeU\xed\xdc#z \x10\xff\xa8\x9be\xbd\xa88\x1b$1\x1dAy\xa0nH\xb6\xbb\xbaYl\xf6\xcb\xd9X\xbbRW\x194\xc9\xd9\x1d\x93\n\xb75U.^\x96c\x9d\xe63\xe7\x1f/\xfa\xd9\xdd\x9aUA~\x9et\xac\xd7,\x82|\xbc\xc6\xe7QV\xeab\xf7\xe9\xa3\x84\xae\xa0\x9e|\xb78Oa_9\xeb\x9a*\xce\xd1c\x88\xec\xa7\xed0\x92?\xd7~E\x19\x14\xa2X\xf7\xfeRp\xf65\xb2'l\xe2\xe5\xaf5\x9f\x13\xae{\xc3\xeb\xd0F\xb2\x8eZ\xe93\xac\xcd\x86\xcdZ\x05\xefU\xa2\x8f9 \x1euawU\x7f7\xed\xec\x0f-\xd4\x0d\x8d\x16Y;\x00\xb82+\xc3\x94\\Y\xcf\xab\xce{\x97GC\xdc\xef\xd1P\x0f\xc5h\xf1nl4\xb9\xe0\xc1\xb4\xa1\x81\xf8\xb3\x17\xb4\x1cj\xb4\x9c\xda[\x9f\x89o\xd4\xb5\xf4T\xf7XWL\xf7\xf9\xb1\xdb\xcc6\x80R+\xca$o\xa2\xa0\xd2z\x11q\xa6]\xbd\xad\x9bO\x19\xfdf\xe8\x1b3\xde_\xa2\xd6\xa5c\xbe\xe6\xaf\xd5xt\x92\xe3@\x96\xfc\x99h(\xab\xbd\\w\x04\x8b\x8a\xb3u\xdb\xd5\xff^Y\x93\x8bS\xab\xf6\xfc\xce\xb5\x92P\x19\xbe@\xaf\xa4\x9f\xe8\xac\xc2\xa2m>\xb3\xae\xafP\xf3T\xc5f|\xac\xd67NY\xb5]\xbd\xae\x9bj\xa3n\xb8\xe9n\xac\xf29}\x0eC\x86\xe5\x8dg\xb2SY\xa1\xb6\x10yg\xe2\xde\x97\xd2\x15\xe6\xf1\xba\xd6|\xf9P\xc9\xf0I\xf1\x9b\xa4\x8c5\xfbm\xac[y\x0e\x97\xef?\\\xdf\\\x9d\xff|~u\xfe\xee\xf5\xf9\xcd\xf5\xdf.\xcfo>\xbe\xfbpy\xfe\xfa\xe2\xe7\x8b\xf37Y\xe7_\x9d_\xbe\xfd[\xd6\x99\xff\xfa\xf1\xfd\xf5y\xd6\x99W\xe7\xe2\xaf\xc1S\xcdb\xe2\xa3\xea\x8cY\xbc0Z4\xbe/\xe1]\x8b\xbc\xf1\xd6\xd2\x8aX\xff\x1f\xb8-/\xd5\"\xd4q\x0c>\x19\x13wl\xb7\xb9\xd7\xf8\x91\xb5\x92#0\x91\x18\xb9\xa6\xbc\xa1\xe1k\xfec\xdf\xf2q}E\x81k\xaa\xa6\x10\xad\xa8\xd5\xff\xa0\xaf\x1a\xc9F\xa3\x0c\xfd\x84\xa2:Se\x07S\xffc\x8f\x88(\xb3\xa4\xca\x1e\xac\xd0\xd1\xa7\xe4R\x97\xf0\xa0n\xf3\x01\xc2\xf7\xbd\x1c\"\x04\xd8hij\x99\xf5\x00\x9aH0\xa3m6\x81e\xb5\xca\xe4\xda n\xe0S-\xc2\"\xfa%]\xcf\xcb\xb6\xe7WC\xd1\xfd\x03&\x9d))\xfc\xcc\xc7c\xf7\n6\xb5$\xbf\xf4\x18\xc4j\xeb=\xa3Tc\x94jL\x1a\xa5\x1a\xa3Tc\x94j\x8cR\x8d)\xa3Tc\x94j\x8cR\x8dQ\xaa1J5F\xa9\xc6\xa6\xe6\xff\xb4\xa5Tc\x94j\xccc\x94j\x8cR\x8dQ\xaa\xb1\x87L56\xc9$\xa5(\xaec\xf3`\x1d|\xcdG2\xce\x8c\xf9\x0b\x10\xe5\xd6 \x07NP\xec\xd4\xf4]\x94\x12+-\xdf\x10\xa5\xc4:ap\xe3\xc9\x9c(%V\x89(RJ,J\x89\xf5\xebL\x89\xd5\xb1J\xa7\xbc\xfa\xfc;\xff\xd6\xceb\xfc\x11\xc8\x80ue\x9c\\\xca\x03\x95\x9e\xd6\xc3,]\xa5:F\x0df4\x92n\xae\xa2\x1dN2a\xcd\x9c>1\xb5\x7f\xac\xc9\xb0\xac\x18\xd9\xe6u\x05Q\x94$\x9a\xd4**\xa3\xe0y:\xc7\x18Q\xf4\x17\xc3\x8aZ\x89Y\xa9\x9b\xdb1\xa5\xa38\xdcul]\xf7\x9culyc\xee\xb7\xa7\xe4\x1a\x0bU.\xad\xa5\x8dW\x83\x07s\xff\xff\xaa\x87L\xba5\x04\x02\x11X>\x17cv\x00X#:\xc9\xc0\x12\x1bw_spTt\xfd\x04\xc0\xff\xbacR\xc8\x8b\xd6\x15\xb5\x02X\x17\xdcq\xc4\xaac\xec\xc6\x9fO\xca{\x0f~\xee\x18\xbbf_\xf9\x7f\xca\xc8\x9b\xe0z*a\x8dz\xfd\x81\x13\xb6\xad\xbe\xdelX\xb3\xe6w\xb1\x82\x95\xd8Y\x1a\xd7p\xae\xef\x98(\x17\xa8r\xa9\xb1C\xb8\x9e\x01gw\x95W\xe2\xec\xd8\xfa\x86}\x8d\xd5;\xb2h\x0b\xa3\x81*\xbbb\xeb\xf3\xaf\xaa6r\xac7\xad\x92\xbeaz\xe4\x11\x90;\xf4\x02,5\x18\x11\xbd=o\xf5\x90\xf6\x8b\xfc60\xf8X?\xf9L\x08\xb04 \xd70\xa9\x80\x1eN\xd2\x85n\x98\xd9\xb1~\xfeb\x9c\xcc\xff\xed\x0e\x1e<\x17,\xa3y\xf8\xe1M\xe9\xecu]O\xa8.\xdf\x01q.G\x00\xb3\x82\xe5\xd3\xaeSGpu\xf9\x9a\x00W\x02\\\xa3\xdd\x03\xb6s \xc0\x95\x00W\xb7\x11\xe0*\x8d\x00\xd7C#\xc0\x95\x00W\x9f\x11\xe0J\x80\xab4\x02\\ p%\xc0\x95\x00We\x04\xb8\x12\xe0J\x80+\x01\xae\x04\xb8\x12\xe0:5\xff\xa7-\x01\xae\x04\xb8z\x8c\x00W\x02\\ p}H\xc0\xd5\x82\x17&\xcc\xa8\xcd\x92@\x160\x8a\xc3\xc8\xcap7r\xbf\xba_t\xf6\xcf\x7f\x8e'!P\x9c \x84#\xb1\xd9a;:+\xd7\x96\x9b\xc0yb\x02\xf3H\xd9\x9bY\\l\xe3\x0f\xa0\x8fE\xb9\x9d\xa4\xf9!L\xca\xeb#7\xa3\x1b\xd8\xac\xe8\x86t\xbb\xbd\x87\xf2\x08'\xa8-\\\xdd\xf9&\xd4\xad\xab.j\x86\xbf]\xd4\xd9{\xd0\x9d`\xe7\xbc\xa1t\xb3\x1d@\x9c\xe7#f\x18\x8f\xdeI\x8dG\xb4\\\xc0\xdd=@\xce \x1aK\xd5u\x83\xce\xdc\x93{\x81\xaf\xdd\xd2\xfa.\xc45^\xc8\xd0y\xc3\x15\xa8\xf8\x1dZ\xeb\x85Rz/dj\xbeA\x87\"\xb8h\xdd\x17\x8e\xd7~!Y\xff\x0d\xba\xd2\xbaT\x92\x06\x0c\xa5u`H\xd4\x82!U\x0f\x0e\xb7\xecA+\xc6j\xc2PZ\x17\x06\x9c6\x0c%\xf5a8Z#\x86<\x9d\x18Ji\xc5\x90\xa5\x17\x87\x1f\x87J\xe5=\x8f>7'\xd1\x8d\xe1\x84\xda1\x9cF?\x86D\x0d\x19\xf2t\xe4X\x17\x8c\xd3\x92\xa1\xac\x9e\x0c \x9a2\xa4\xeb\xca\x90\xa1-#\xba\xcc\x1f\x10\xfa2\x94\xd0\x98!6\n\x04\xfc\xf0\x0c\xa17C\xe2(.Yw\x0ez\x93\x9a4B{\x86\x84R\x16\xd4\xa0!I\x87\x86\xd2Z4d\xea\xd1\xe1v\xd5\xc75i\xc8\xd7\xa5\xbd\xfe\xc4\x15c\xda4\x14\xd3\xa7\x01/\xb3\x02F\xa7\x864\xad\x1abbP\xa6f\x0d\x08\xbf\x81\x89\xe8B\xfa5d\x05\x17\xafc\x03\xa2\x96\x19z6\xe4j\xda\x80\x8b\xea\xd1\xda6\xe0\xf5m@j\xdc\x80\xd6\xb9\x01\x17\xf4t\xbd\x1b\x924o\x08\xe9\xdePJ\xfb\x86T\xfd\x1b25pH\xd3\xc1\x01q\x13Bz8`\xce\xc7\xeb\xe2PP\x1b\x07L\xd1\x02OY9\x9d\x1c0Z9\x1c\xa1\x97{\x1d\x8a\x03C\x9a9\x94\xd6\xcd!\xaa\x9dC\xae~\xee\xf5\xa6\xbe\x7f\xc3S\x01\x08\x1d\x1d\xc2Z:d\xe9\xe9^WA\x9d\x1dr\xb5v\xaf75\x8c\x0cL\xba\x95\xd3\xdc\x01\xa5\xbbC\x86\xf6\x0ei\xfa;\xe4h\xf0\x90\xac\xc3C\xb8\x1b\x81\x886\n \xfa(V\x93\x87\x1c]\x1eR\xb5y\x08WxG(\xa7\xd9\x89\xd8\xc8k\x8es\x86-\x02\xb5\x007\xdd'\xb1\xe2\x95\xceH1n?\xe5\xf3F\xfbP\xd1>Tq\xe5\x9d\xf6\xa1\xeai\x1f*\xcb\x12\xf6\xa1\x1a\xb8\x9b\x02\xcb\xf2i\x07*Z\xa0\xef\xfc\x9d\x16\xe8[F\x0b\xf4i\x81\xfehE\xc1\x8c\x14(# \xc8\xa0\x05\xfa\xc7\xc2\x17\x19\xe0E\x11\xe8\"\x1d\xb8\xa0\x05\xfa\xc7\x00\x16)pE\x06XA\x0b\xf4i\x81>-\xd0\xc7\x82\x11E\xa1\x88\x1c \x82\x16\xe8\xfb\x0e\x8b\x82\x0f \xd0\x03f\xf9y\n\xec@\x0b\xf4i\x81>\x02\\\xa0\x05\xfa\x90 '$\x80 \xb4@\xbf\x00x\x10\x85\x0er\x81\x03\xef\xbb\x86\x16\xe8\x1f\x1a-\xd0\xa7\x05\xfa3+\xb1X\x1a\x0b\x03$\x83\x00I\x10\x00-\xd0\xcf\x14\xfbi\x81\xbe\xb1\xd3-\xd0W\xfb\xf5L\xf2a\xeb\xb5\xbc\x9e\xe5\xea\x96\xefS-\xda\xb7\xb6\x0eQ\xeb\x99}\xf5\xb9\x14E\xad\x97\x8f\xa5\xb4\xfb~\xf2Y\x1eR\xfa\x9f\x9aY\xe3\x1f\xe0c/\xde\xe1\xde\x1aL_\n&\xb5\xfa\xba\x95\x1bP\xb5C\xfet9b\x10Cku\xff\xea\xa5\xdc5e\x98\x9f\xa8T\x7fr6\x8bG\xea\xa6&\xb3\x88\xd0f\\)\xd1\xf2Le\xd1f\\e\x83\x1b\xdfF\x8a6\xe3*\x11E\xda\x8c\x8b6\xe3\xfa-o\xc6\xe5K\n\xf4\xe2\x17\xf3O\xf1wu\x9dP\x8a\xa0\xf06]r\x0e_\xfcE\xe5\x08\x1a\xc6B\xce\x0cAOL4\x1ey\x82\xa0\xa2\xc0f4\xcdOTc\xc2c\x86YY|<\xd9z\x82\xb9zNR\xe6#\xb2\xf4\x84\xcb\x19\xca\xd0\x13\xcf\xcfsLv\x9e\x80\xb8\x18lR\x10mV\x80\x00\xb8\x10\xf7 \x90\"\xa0\xb2,\x8c+\xe0/)\x1bOQ\x94+\ns\x95\xc6\xb9\xf0@W!\xa4+\x0f\xea\n\xb8K\xcc\xbfs$\xd8U\x1a\xedJ\x84\xbb\n\xe3]i\x80W\"\xe2\x15j\xc3\x19\x19w\x8ab^(\xd0\xab \xeau,\xec\x95\x85{\x15\x02\xber\x90\xaf\x803t\x86\x9d\x13`_\xa7\x03\xbfN\x82~\xa5\xc1_\xc5\xf1/,\x00V\x14\x01\xc3C`\xc9\x18X:\x08\x16\xed\nq\xb9t\x8e\x86\xc1\xa2ytP\x03*\x04\x12\x962\xeaJ\xc6\xc2B/At\xf6\x1c\\\xf9\n\xc2a)xXa@,\x0f\x11\x0b\xb5 T\xc6\x9cLL\xcc\xe3\x8d\xa3\xb2\xe5\x94A\xc5\xd0\xbc\x13\x02\x17K\x02\xc6b !r\xa0\xb1\x98O\xaf\n\\\x08\x1dK\x0f&\x1e\x1f\x8b\xd5-\x03!\xcb\x84\xc8\x10q<\x1a$C\xa3d8\x98\x0c\x8b\x93!\x82\x9c\x8e\x94\xa5@e\xc1\xfc7E\xc0\xb2D\xb4,\x0f.K\xc2\xcbbA\x0f\xe7\xbc\x89\x9c\x8b\xc7\xcc\xca\x81f\xd1By\x9f\x9fr\xb8\x19\x028\xcbG\xce<\xeex4\xc3MQ\xec,\x06\x9ee\xa2g\x1e_\xf1\xcc6\x08\xfc,\x92\xd5\xa64\x82V\x1cB\xf3ch%A4\x0c\x8a\x96\x0e\xa3%\xe1h\x19@Z*\x92\x16\xc9T\x13.\x1d\x16\x12\xc2\x82i\x19hZ\"\x9c\x16\xa8n\x0e\xa0\xe6q\x85\xc8M\x93\x03\xa9\x05\x9a|\x1f\x8e\xf7\xaf\x83\xb5\xe6<\xae\x86\x13\xc7\xc4\xf9\xee\xd5\xb1\xe6\xb81H\xe2m?82\xc5\xd1\x7f\x98-\x96=\xb8\x88>\xec\x11\xaf\x9b5E\xbe\x99\x05\xd46\xfe\x00\x02ft\xf1m\xd2\x04^`1k|\xa7\x0fpu^\xa2\xcf7\xcb]\xeb\xfepm\xae\xd7\xd7\x18r\xe7!\xb1\xea\x86V\xc4b\xd6\xc4:W\xc5\x1e4z\xf7-\xb9k;~W5\xcb\x1b\xb7\xdc\xae\x0cqWt >J}xt+U|k\xb5\xb0z?[\xc1u\xba[\xd6\xfdnS\xdd\xdf\x1c;\xd7\xab\x0b\xf5W\x95\x12C\xbc\x9aF5T_\xc3$bP\xc9JbE\x0b7\xab\xc3\xceb\xc6\x91(\x9a@\xa1$\x9163_\xd6\xec\x99w\x9d\xf5]\xc6h\xbb#\xda\xee(\xd6Zi\xbb#5\xbc\xa7\xed\x8e\x8c9\xb7;:x\x0c5\xcav0.BQm._/\\#9q\xa7\x88h#\xa2-\xf6\x8a\x8fw\x0b\xca\x88h#\xa2\xcdmD\xb4I#\xa2\xed\xd0\x88h#\xa2\xcdgD\xb4\x11\xd1&\x8d\x886\"\xda\x88h#\xa2M\x19\x11mD\xb4\x11\xd1FD\x1b\x11mD\xb4M\xcd\xffiKD\x1b\x11m\x1e#\xa2\x8d\x886\"\xda\x1e\x94h\x8b\xb0D\xdf\x9e\x0b\xa3\x0dt\xd2v'\xa1\x0dtN\x18\xdcx\x1b\xa5\x0dtJD\x916\xd0\xa1\x0dt~\xc3\x1b\xe8\xb8(a\xfc\xde9\x07X^\n'\x9c\xc8\x07?11\xfa\xcf\x83\x07\x17e\x04\xa3\x90oT\xd1(@\xb6\x95\x83{\x83\x98\xe67\xde\xe8\x06\x83\xf4b\x80\xde\xe8\x1d(\x08\xf3\"P^lqJa\xbc\xa1\xc6S\x0e\xe1E\x01\xbcN|7\x11\xbc+\xc9\xdd\x11v\xa7\x8d\xb0;\xc2\xeeF#\xec\x8e\xb0\xbb\xd1\x08\xbb\xe3\x84\xdd\xb9\x8d\xb0;c\x84\xdd\x11vG\xd8\x1dr\x94D\xd8\xdd`\x84\xdd\xd9F\xd8\x1daw\x0e#\xec\xceu\x0caw\x84\xdd\x11vG\xd8\xdd\xd4\xfc\x9f\xb6\x84\xdd\x11v\xe71\xc2\xee\x08\xbb#\xec\x8e\xb0;\xc8O\xc7v\x08\x13\x0cU:\xb6\xe4\xa5\xb2\xb3\x89/`I]\xc8\xdb\x17\xc8\xbav)\x7fwR\x13\xdbv\xb9\xdf0\xab\x01\xe8sg\x94\x84\xbc\x94r\xf3\xc4\xd4\xf1\x91\x02\x12v0l\xf3\xba\x82\xa8\xe4\xd6\xf3\xaaYV\x9d$.zg:6\x88H\x81\x10\x92\x03!V:e1Y\x10\x82\xa9\xca \xaa\x99\x8e\x16\xa7\x1b\x949\x18\x07\x11\x1f\xa8\x9b\xbe^\xb2I\x87\xe0\xf5\xa2|D\x0b\x1d\x9c\xca\x83\xb1,\xd7\xe2?\xd3\xe2xO\xb2\x9bg\xb1\x02\x047\x9f\x07xjd\x9d\x1f\xe0\xfc+g\x8dx%Z\xe5\x98\x05\xd2\xbf\xcf\xab2\xf9\x02\xac\xc4\xf8\xb4\xe6P\xedv\x1b)\xc3\xfare\xc5K\xf8A7\xf4+uy\xdf.z\xfa\xa8X|m\xa0vW/>\x89\xb7\x7f\x13\xd0|\xd5\xce\xab\xc5\x9d\xd2*\xac\xc2yn\x81d\x90\x1dr\xbe2|A^-\x97\x1d\xeb\xfb\xe9m\xf7\x84\\\xf5I\xe1k\x1e\xbd\xc9\x1f\x8fh\xec\x80\xab\x1e \xe7j\x8d\xa5\xea\xedAg\xeeI\xd7\xc0,Di\xdd\x1d\xe2\xda;d\xe8\xef\xe1\nT\xfc\x0e\xad\xc1C)\x1d\x1e2\xb5\xf8\xa0C\x11\\\xb4\x1e\x0f\xc7k\xf2\x90\xac\xcb\x07]i\xbd0I\x9b\x87\xd2\xfa<$j\xf4\x90\xaa\xd3\x87[\xf6\xa0\xe1c\xb5z(\xad\xd7\x03N\xb3\x87\x92\xba=\x1c\xad\xddC\x9e~\x0f\xa54|\xc8\xd2\xf1\xc3\x8fC\xd5\xb3e\\\xcb\x87\xd3\xe8\xf9pBM\x1fN\xa3\xebC\xa2\xb6\x0fy\xfa~\xac\x0b\xc6i\xfcPV\xe7\x87\x04\xad\x1f\xd2\xf5~\xc8\xd0\xfc\x11]\xe6\x0f\x08\xdd\x1fJh\xff\x10\xd3\xff\x01?\x01\x107!\xc4)\x00\xe6|<\xaf\x00\x05\x99\x05\xc0\x14-\xf0\x94\x95\xe3\x17\x00\xc30\xc0\x11\x1c\x83\xd7\xa180\xc42@i\x9e\x01\xa2L\x03\xe4r\x0d^o\xea\xfb7<\x15\x80\xe0\x1b \xcc8@\x16\xe7\xe0u\x15\xe4\x1f \x97\x81\xf0zS\xc3\xc8\xc0\xa4[9\x16\x02P<\x04d0\x11\x90\xc6E@\x0e\x1b\x01\xc9|\x04\x84\xbb\x11\x88h\xd6\x90\xa0[cY \xc8\xe1% \x95\x99\x80p\xc5s\xd8 \xaf3\x8bL\xc0>28\x86\"\xf8@4\xeb0G\x01eY\n\x88\xf1\x14\x10f*\xbc\xe7\xe4\xb2\x16P\xb0\xed&0\x17\x90\xc4]@`\x84b\x96YK\x95\x0b\xa1\x83J\xb1\xb0n\x9b\x9be\xc5\x8f\x91\x04\xcd<\x88p\xf3\x9c\xd7[\xdf\xad\x19\x96\x81o\xe5\x10\xf2@J\xfeR\xf5\x01\x15yXE-\x8f=\\E-^K\xea\x9b\xb9^\xb8kM\xbb\x06\xd1\xaeA\xf1\xec\x00\xb4kPO\xbb\x06Y\x96\xb4k\x90D\x86\xf0y\x18\x149E\x89\x18(\x11\x83\xe3wJ\xc4`\x19%b\xa0D\x0c\xa3\x15\x05=R \x8f$\xc0\x83\x121\x1c\x0bsd\x80\x1cE \x8et\x80\x83\x121\x1c\x03l\xa4\xc0\x1a\x19\xa0\x06%b\xa0D\x0c\x94\x88\x01\x0bZ\x14\x85,r\x00\x0bJ\xc4\xe0;,\nR$@\x14\x984\x03)\xf0\x04%b\xa0D\x0c\x08\x10\x82\x121@&\xec\x90\x00:P\"\x86\x02 C\x14b\xc8\x05\x18\xbc\xef\x1aJ\xc4ph\x94\x88\x81\x121\xcc\xac\xc4\xa2x,\\\x90\x0c\x16$A\x05\x94\x88!\x13\x1e\xa0D\x0c\xc6N\x98\x88\xc1\xb3\xca\xdfr\x91\x9e\xd3 5\xfd\x82Z\xb2{f\xf4\x12_\xf1g\xdf\xcf\xb9\x9a\xc7A{\xf3\xe9\x1c9\xda\x86K\xc3\xc8\xd2-\x82\xfaD\xb6&\x91\xa9C\xd8z\xc3\xc4\xdf\xe1'z\x86\xde\x90\xa51\xcc\xb4\x84yxf\xbaB\x8e\x960\xd3\x0c\xe6W\x98^ W3\x18\xb4\x81\xa9\xfb\x83\xc1T\x8e6\xe0\xd3\x00\x8e\x9a\xf7G\xcd\xf5c\xe7\xf4\xb3\xe7\xf1s\xe7\xee\xdds\xf4\x85\xe6\xe5K\xce\xc5\x17\x9a\x7f\x8f\xcd\xb9\xe7\xcd\xb3\x07\xe6\xd3\xd3\xe7\xd0\x83s\xe5\x88\xf9\xf1\xdc9q\xcf\xdcw\xe6|w\xce\xbeC\xb3\xd7\xe4\xecm(\x9f\x0d\xeb\x9c\xd0\xab0sb{\x9c\xc0>\x0cz\xd9\xbay\xa6\xf1\xc7\xfcK\x07 =B@\x9c\x95\x97\xe4cozE\xedc\xa9^\x80*\x86\x93\xb3\xe4[\xbb\xeea\xdd\xca\xdd\x94\xdaa\xdf;\xf9\xb5]\xaf\xac\x13e\xf7\xb7\xe9\xdb1@\x85\xe3A{#\xa6D+\xd2zho\xc42\xc1\x8d\xef\xeaG{#\x96\x88\"\xed\x8dH{#\xfe\x86\xf7FT\x87\xfc\xa2\xfe\x11\xdb\x1bQ\xaa\xc7\xfe\x8c\x84\xf8\xbd\x11\xad\xa5\x02\x8f<\x1ba\xd1u\x0b\xd1\x9c\x82\x9e\xdel4rjyj\xd9\x13\xcdSK\x9fv\x0e8Cg\xfc+4==\xb5\x92\x93\xd5S+4u=\xb5\xd8D\xf6\xd4\xf2\xa6\xb5#=~\x1c \xcf\x99\xfe\x0e5\x10$D\x8e\x9a&\x9fZ\xea\xa4y\xb4+\xc4\xe5\xf6\xcb\x9c\\\xb7-\x92\xd7\x0f5\xa0B \xe5)\xa3\xae\xe4\xd9\xf7\xd0K\x10\x9d\xcd\x0fW\xbe\x82py\n^^\x180\xcfC\xccC-\x08\x95\xc1/\x133\xf7x\xe3\xa8\xec}ePs4/\x8d\xc0\xcd\x93\x80\xf3X\x82\xaa\x1c\xe8<\xe6\xd3K\x91\x15B\xcf\xd3\x83\x89\xc7\xcfcu\xcb@\xd03!tD\x1c\x8f\x06\xd1\xd1(:\x0eF\xc7\xe2\xe8\x88 \xa7#\xe9)Pz0\x1f_\x110=\x11M\xcf\x83\xd3\x93\xf0\xf4X\xd0\xc39\xf8\"\xe7\xe21\xf5r\xa0z\xb4P\xde\xe7\xa7\x1c\xae\x8e\x00\xd6\xf3\x91u\x8f;\x1e\xcd\xb8W\x14[\x8f\x81\xeb\x99\xe8\xba\xc7W<\xd3\x1e\x02_\x8fd\xd9+\x8d\xb0\x17\x87\xd8\xfd\x18{I\x90\x1d\x83\xb2\xa7\xc3\xecI8{\x06\xd0\x9e\x8a\xb4G2\xe7\x85K\x87\x85\x8c\xb1`{\x06\xda\x9e\x08\xb7\x07\xaa\x9b\x03\xb8{\\!r\xe5\xe5@\xee\x81&\x1f\xcf\x93W\x10t\x8f\xe6\xc8;\x05\xec^\xaa-&\x00\xef)\xc8\xbbo|\x90\x96\xff\x0e\x91\xfd.:c\x80\xcb|wL\xde\xbbc\xb3\xde!\xf2U\xa5\xa5\xab\xa2lU\x94\xad\xca\xf5;e\xab\xb2\x8c\xb2UQ\xb6\xaa\xd1\x8a\xca\x91)bd\x92\x14I\xd9\xaa\x8e\x15 3\xe4\xc7\"\xe2c\xba\xf4H\xd9\xaa\x8e\x91\x1cS\x04\xc7\xc2r#Nl,(5b\x85F\xc7\x87\x00e\xab\x9a\x1aBZ\xc4\x8e\x92\x92eE\xcaV\x85\x12\x13s\xa4D\xcaV\xe5;,*\x1f&\x88\x87\x98\\L)\xc2!e\xab\xa2lU\x08y\x90\xb2UA\xa6 \x98 \x07R\xb6\xaa\x02\xf2_T\xfc\xcb\x95\xfe\xbc\xef\x1a\xcaVuh\x94\xad\x8a\xb2U\xcd\xacD\xe6 \xac\xa8\x97,\xe9% z\x94\xad*S\xc4\xa3lU\xc6N\x98\xadJ\xb4\x85\xf1.iimX\x17\xfa\xad\xf3V\x0dKX\xe3Ux\x98\xa2\xc6\xd6\xeb\x8a\x0f\xde\xcd\xfd\x8b\xcf\xbf{\xb1\xa8\xbb\xc5~S\xf1\xbaY\xbf\xf8e\xc9\x9av\x1bX\x96kM\x0d\xbc\x1e\xcf\x9353\x8aM\xb5\x1d\x16\x93\xb7\x9fX\xd3\x83u\x01\xf36\xdfV\xdd'\xa9\xe1\x0e\xde&\x13\xddj=\xaf,\x8b\xfe\xdbdI\xafue\xfd\xf3\xa3]\xd7k\xd5\xfdF\x85\x08@\xb6\xab\x1aqS\xae\x14\x19\xf8 \x10\x00\xe2\x89x\xc0\xfe\xd0\xcf\x1d9\x0fM\xd9U\x8b\x05\x07K\x16\x7f\xf9fW\x1c\xb5+UYT\xe6\xb8\xec\xc4\x81;\xbde\xe3\xe5\xfa\x8b\x1dd\xba\x0e\x9dF\xc9m\x92\xf8\xf4\xbd\x9d\x02}\xef\x993\xce7\x89\xab\xc7A\x06\xe3\xab%\n\xaf\xab\xfd\xcfA\xf6\x0f\xc4\xd9:QM\x08\xd6?\xcaK4\x91rf\xf0a/\xb0zl\x8ed\x80\xab\x9a-\x8f\x06\xe0\x95s\x85\x85\xbc}ws\xfe\x9c{\xca\x85\x93\x00]\xce5\x0f&\xb8h\x06\xe1\x8c\x9b\x028z\xab\xcb\x0d\xe6\xd4\x00\xb1\xef\xb0>\xd6\xd7\xbb\xa6\x1aN\x1d\xeb'\x9b\x04w\x8f\xb0kw-w\x83\xa5\xe4X\xbf\x1a\xbb\xe1\xa5\x18\x80\xaf\x19[\xcc\x81{&\xb9\xdd6\x0fU\xb7\xf31>\xc8q\x8c1\xdf\x0d\xfbdk\x12\xef{\x0c\xc4\x1c\x8b\xa8{\xd8v\xd5\xa7\x06\xee\xbbq1[8\xcd:V\xf5\xdd\xc9\x16\x97Um85\x1f\x0f\x1f\xb2\x15v\xc7I\xe9\x96}\xe4\xee\x1bn\xa2\xd1\xba\xad\xd9V\nKl\xdbW\xce5(\x1bK\xa3\x83\xca\xc62\xfb\xc62j\xe3ac>\xe43\xd6\xb1!QX~\xaf\xc5{\xdc\xb2\xb87&\xe3\xfc\xb9g\xc3\xe6\x81\xa7,)y\x8e\xaaq\x9eROF\x9bW)\xc1p\xa2\x1cro\xb2\xac\x84x\xe2\x9b\xdd\xa3\xa8\xbd\xabJ\xc2P&F\xcb\xd6A\xcb,\x8c\xde\xb2\xdb&\xe3\xa7\xae \x93\x05\xec\x87\xee\xb4\x19W%\x8b\x7fV\x1b\x07\xf3\xd7/\x86\xb0\x18\xc2/i\x08\xd7Cy\xc9'\xe4UgA%\xcd`\xfc#r\xe0\x9e\xddU=;\xc3\xf9\"\x8c\xf3\x19\x12\xa4\xff\xfb\x89\xf5b\xca\x18\x1f\xcb\xfc<\x1f\x98\xe2g#\xebJF\xfd\xdamE\x0e\x02\xf7\xac\xf4\xed$y;>\x1c\xd8r\x0d!\xb5\xb7=\x0b\xe9\xfa\xac.\x8dq\xdd$\xc7^v\x01\xe70\xcf\xd0\x03\x8b\xedqNbt\x83\x16=\x0f)\xbaB\xd6\xad\xb7^\xa7\xc7\xb6\xb73+i9AY\x9eJXn\x90\x94\xa7R\x94\xf3G\x96\xd3\\U\xbf\xa4'\x17\xac\xe0\xf1\xdd\x9b@+\xce\xb5\"\x95\xb8:3MRq\x07\xa58=\xc3eL\xcbu{\x90f\xd6\x8cSy\xdd\xb6\xd0\xb7\x07v;\xad*d\x9c\x96b\xaa\xd5\x0f\xa7\x86ha\xa4\x89@6\xa6J\xa8/\xd6r*M\xa1Bu\x83\xfb\xa8N}!\xc3\xa7\x8a\xcf\xacgP\x0f\xbd\xcc\xe1\x1b\xd7!\xdc\xc9o1\xad\xe9S-\xbc\xda\xf4\xc7P\xc7\x84s,\x8aG\xa6\xc1\xf8\x89w\xde|\"\xd8\xb4\x1d>\xc4\xf3b\xb5\xb1\xcb\xc3\xed\xf8\x8a\xa9\xb6j\x9a\xc8\xcbI)J2fe\xc7\x8exD\xfcs\xd5M]f\x9f\x97B\x0d\x1f\x19\xfa\x94T\xe7\x88\x9c\x1d/\xdb\xba \x9e\x15\x9a\x9f\x94\x18\x19\xba\x0f\xd4x\x84\xfe\x1e\xd1\xdeL|=\xcau\xa9\xb9(QS\x88?\x12\x9d\x0c24\xb4?\xfb\xf8\xf7g/\x8e\xc77u\xf3\xa1\xbfT<\xf2\x01\xfd\xc9\x13\xc8\xea\xe1\xf1v+\"\xfd<\xb3NL\xafWb\xdb _\x07\xf9:\xdc\xf1\xecM\xdeCsV*\xec\xeb\xe6\x03\xb0\xcf\xc7\xba\x13\xa9R\x92\x90}Qk\xd1\xff:B\xd0\xb1=\x1f~\x02o\xaa\x8eG\xae\xaf\xb7v\x84,vT\x1d\xdc\x13\xa7^e\x97w5\x1eo\x96j\x15&\x0f\xdeP\xeb\x9a\x06\xae^\x02\xfb\xda\xb6\xbc\x82\xa8\xfd\xd4\xb0\xae\x7f\xa8\x8f\x8a\xcf\x8b\x9a\xe4\xf6N\x82\xc0z\x90p\xf1X\xb9\x07\xf6\x19X\xb3i\xc7\x03\xc0X\x06\xf6,\x1f\xe3s\x9ddG\xf3\xba=Z\x00c\xa5\x99\x14r+\x90\xdd\xb9\xcd\xea\x08\xd8\x8f\x87\xb8\xf0ahk\xd4K\xae\xe7\xe2\x95>u\xe7\x99\x80%\xcdsxl2\xa3\x12\x0e\xa9\xc1\x8a\xe7\x10\xc3j,\xce}b\xa8\x1e\xb8!\x92\xe8\xb7\xf0%\x89:\xa8vI\xf5\x1er\xc7\xe0|,\xe4.\x1e\x8e\x9d\xf3\x0dE\xdd\x03\x1aC}E]af\x84\xe1%\xe7\xd95\xfeM\xed\xbaJE\xcb\x08k\xea(\x1f\x9c\xd3\xca\x82 \x84\x0c\xe4_\xd8\xe7\x9f\xe4x\x15\xbe\xc3\xd9\x1e\xf3\x83\x0c\x9e]\xf8~\x1e\xf7l\x9a\xaa\xe9\xb0\x13W\x01r&\xa9\xb5\x9a\xf4k+\x85`\xd7\xe1\xb5\x1b\x9f\x11\xcb.\xa1M\xbfl\xf7\xbe\xaa\xf7L\x9f\x1bX\x9b\xd7\xfcO\xcb\x8f\x86\x8fg\xfd`\xeb\x81\xb4\xa9\x86\xe7\x1c\xe4\xe3]\xb18\xad\xe0Aw\xfcLc}O\xdd\xe4[\x90\xb1S\xe3\xf2\xee9\x1c\xd9\xc9\x10\xe5\xe2!\x94q\"D\xcd(\x0c\x069\"\xdfY\x98\xd4\x88\xfc\x0c\x99\xafN\xe7\x93\xba5\xb5\xaa\xf7{q\x98\xfdN\xd1\xa5\x1d\x99\x84\x15\x13y*\xf1\x7f\xf9\xb4\x13\x89\xbe\x83\xa0f\xdc\xe4!\xe4\xec\x1f\xa6\x8b\xabVn\x0f\xd9\xef\xdbO\xb31\xe2\x1b\x87\xfe9\x88\x0f\xf8\x0cxg\x8f\xff\x10\xdd\xf1\xfa\xfd\x9bg\xa0\x0eb\xc2\x08\xfc\xb9nW\xfa\xf7\x0e\xd5\xe7\xdb=kv\xc3C\xa0\xa9\x9cp\x04\xd1\x1dS\x91\xb6\xf8]\xc5;'\xaa\nwu\xbb\xeb\xaa\xe3\xc3#\xdd\x8a\x97\x0fU\xdd\xbcl\x9b\xfbz\x17\xdc\x8e\xa5g\xc9\xed\xd3U\xf4\xd3F\x98o>\xc7\x87p\xdd3\xfdx\xe3A\xd2\xe2g\xe5\xca\x9f\xd2\xb1\xa8v\xf3\x96\xf5\x83\xf4;\xcb\xce\xad\xc4\x1d\x96C\xab:\xb4\xc4\xafz9A;\xd1\x81\x0c+\xb1\xee'\xdc\xe1\x9d\xb1\x0c\xae\xc4\xf6\xcb\xce\xdb\x1a\xc3\xd6J\xb3\xb2Fq\xb1r\xd5\x9a\"+\x03\xeb\x10\xcf\xbb\x1a\xc9\xb6jpT\xba9V\xa3\x98U\xa3\xf8Tg\xdeT\xa3\x8f,,\xaa1\xdc\xa9\nG\xaa\xa6\xcd\xc2\x98\x1a\xcb\x93:\xf1\xa1\xea\xad!(db8Q\xed\xdc\xa7\x89\x8c\xa7A<\xa7\xe1|\xa6 ,\xa6\xb1\xdc\xa5\xb6P\xf9l\xcc\xa4y\xf9H\xb3\xb1\x90\xfa\xb9G\xe3\x18G)\xa7\x8b\x85gt=\xbb\xa8\x87Et\x08\xe1\x0e\x8de\x0c\xb52\x83F\xf2\x81\x12\xde\x12\xaf\x83\xd6`\xfct\xaf\xa0\x91\xec\x9e3\x8b'\xd5\xbf\xdf\xf9\xcb\x8e\xe3\xef\\ru*\xeaL\xd6\xce\x0c\\\x9d \x0c\x9d\xe6(\xd7\x17\xc3\x046N\x0b\xf3f\n\xdf\xa6\x93(\xd2\xc2\xad\xe9e\xd44I\xea\xc2\xd93\xcdw\xffF\xb55\x8a\x1f3\xa4\xb1>.L{\xdb\xbc\xbc\x97+\xd8.\xc96G2[:\xf9,\xed,\x96.\xeeJ\xb2\x13By*}\xec\x94\x1a'e\x02\x13e\x00\xffd8\xeb\xa4\x97k\x92\xa0f4\x8a#\x9e\xf1qH\xa61G\x92\x95R~\x89\xe2\x86\xb4\xf1@\xa6\xb0?\x12L\x8f\xb1\xfc\x8e$\x97c\x02\x83\xa3\xb1\xd5\xb6r4\x1a\xcc\x8cy\xf8\x18\xe3Y\x185\xc6\xc5(\x9eE+\xa7b\x18\x93\xa2\x97?Q\x1c\xa4}\xac\x89\xe21'W\xa2A\x1eh\x96\x16\xcaL\xe7fC\x0c\xe4@\x0c`>\\T9\x81\xe5\xd0`4L\xe01\xa48\x0b\xe3\x98\n)V\xc2|\\\x84\xf1_\xd7\xcb;\xe8c\x1b\x9c\xcd4\x05\x12\xbe\x10\xde3\xab_\x90}\x1eX7NCt\x10*\xde\xb6;u\xef\xb8i\x9b\x86G\xff\xab-\x9fP\xb4W\xdco\xa8a\x9e\xc7\xaem\xef\x0d\xc0\xfar\xfcuY\x9d9\x12\x81\xbf\xe2\xae\xd9\xac/\xdc\xe1w<\xdd-#\xcb\xad\xef\xdbu\x80\xd5q\x08>0\xd2\x9f;\x9f\xd1\x89\x08NG\"du&BN\x87\"\xb8\x9c\x8a\x90\xe6X\x84\x8c\xceE\xf0:\x18!\xd6\xc9\x08)\x8eF\xaa\xc7\xfcW6E;\x1c ]\xdek\x9aR\x1c\x8f\x84:\xe7\xd5Ly\x1d\x90\x90\xee\x84\x84\xfc\x8eHHsFB\x9aC\x92\x9e\xa2d%\xb3\xb9)!\xbb\xab\x12r\xba+!\xc8e 9\xdd\x96\xe0p]B\xa2\xfb\x92\x9a\xe3\x96k\x91\x82\x9c\x9a\x90\xec\xd8$\x14\xd2\x97 E\xba;!2@\xccy\xd9\x91\x7f\xfd\x8ft\x81Rf\xcfq\xb5\x91\xbb\x1ei\xeePM\x99\xeb\"\xa3\x0cnQ\xc8\xed\x1a\x05\xc2=\n\xe9.RM\x9b\xe90\x85D\xa7)\xf8|\x89\xe0\xbe\x98\xc8\xeb@\x05\xebM\x1f\xe1\x8eT\xbb\x0e\xe3\x94\x9c\xe4T\x85\x15\x9d\xe1s\xae\x82\xb7\xdd^'+\xacs\xb4\x82\xab?\"\x1d\xae\xe0s\xba\x82\xf7\xfa \xdf\xc5A\xd6N\nu\xc2B\x80#\x16\xe8\x0b\x82\x12\x1c\xb2\x10\xe6\x94\x85U\x8eY\x08q\xce\x82\xfd\xee\x1c\xb2x\xcb\xb3>g-$;l\xc1UQ\xed\xd7\xac\xce[Ht\xe0j\xaa\xe8\x8b{\xb2\xbat!\xb3[\x17|\xd7\xef\x90\x17\xef\xe4q\xf1BN7/dw\xf5B\xb0\xbb\x17B\\\xbe\x10\xee\xf6\x85@\xd7/\xd8\xee\x8e\xa1K\x0fu\x14\xfa/\xc5 t\x05C\x98;\x18\xa8f\xe4t\x0bC\xaakX\xd3E^n\x93\xcfY\x0cY\x1d\xc6\x90<\x1e\xbc\x8ec\x08p\x1e\x83\xb1\xea\xd82M.Ow\xff\xc4\x1e\xf5\x8c\x81\xe3\xe9n_o8\xab\x06\x95]!\xbd\xc9\xe6\x0d\xdf\"\x06\xd5X\x98\xc7u\x03m1\x95\xabeI\x9f)\xae\xdc\xe2\xca-\xae\xdc\xe2\xca-\xae\xdc\xe2\xca-\xae\xdc\xe2\xca\x9d\xa4\xb8r\x8b+WJq\xe5z]\x9a\xc5\x95[\\\xb9\x86\x14Wn\x9c\x874\xfc\xd9\xe2\xca-\xae\\\xe2#\x14W\xeeB\x8a+\xb7\xb8r\x8b+7\x87+\xf7z\" \xd2\xbc\xb9\x0f$\x93\x900\x19\x97\xfb\xaann\xd8g\xfd\xe0\xa6\x13\x06\x1d\xc7\xe7n\x07\xf6y\x08L\x1b\xb4z\x9ce\x81\xaej\xa2\x11\x14\xd4Ku\x83\xd4\xdd\xfa\xc5~0\xf9O\x08o\xd6\xd4\x1b\xe2w\x1em|\xbbQ\xe8\x1a`\xae\xa4\x95j\x01\x9f\x97\xa4\xb0d\x04\xf3\xac+\xa5\xb3\x0f\x0e\xa2\xc6\xdd\xc2\xdfx\xdf\xb5\x0b\xff\x02\xee\xbf6\xac\xfe8\xbbu&\xca\xceV\xf8A\x9a\xedt\x7f\x0f\xfeOXC\xae\xf9\xb3\xfa\xb4\x90\xc8\x9a\xf4! \x82C\xac=\xb2\x0c\xeaD\x94\xb2\x82a\xc5.\xfa\xefJ\xb6\xcd\xa0%\xb5\xb4\xf9\xa1\x1a\x9e\xf1\x93\xa3@H\xd4%m\xdc\x04\xa8\x9d\xb7\xab?\xb2e/\x8d\xff\xac;\xfe=\xf4\x11\xa9\x8d\xa0\xb9BP\x89\xef'\x1e\x98\xear\xc7\x86O\xa3\xa1\x18>qT\xa4\xb3\x0d\xcf\x89\xde2`<\x92\xd4\x9c\xae\xde\x8c\xa3\x996)\xa6]ed\xa2\x96\xd6\x8d\xa8\x85\xffT\x81{\xb9\xcb\x7fr\xc6\x8e\x95\xe6\xe7\x14\xf1>w\xaa\xd5\x9bu\xecoo\xeb\xcd\x87\xb1-+m\xeaW5\x98\xcb:\x07\x18\xcda\xa6\x89\xec\xa1\x11o[\x86'R\xdb\xae\xec\x0e\x82a\xd7\xd9\"\xfaj\x89\x85%\x98\xc8u\xad,\xa7\x0b\xf2R\x81\xd9H\xa6S\xc9\xe2\xaa(\xd4vd\xe3\xd8\x92\x93\xac\xffp\xbb\xf1\xdcm\x00\xebj\xff\xa2\xff\xf0\x92\xdbI\xad\xf6\xf3\x0d\x19X{\x0e\x0c\xe1\x8e\xa3\xea?\xcc\xf5\x86\xa5KB\xa9\xec\x81\xef\x19\xb3V\xf6\xd7q\xe3FT\xf6P7\xf5\xe1t\x98\xef\xfc\x99\xea\xac,]\x9bv<\xd6,\x10\x0c\xad\xa7\x17\xbcv\x04\xff\xdc\xb1c\xc7\xaac\xb7\xbb\xca`\xd9\x8ao\xd3%*\xfdK\xd5\x1b\x0b\xdaA6gWI\xa8\x8f#?3\x15\x9f\xa2\x07+\x87\x06D\xf9\xb9\x1f\xc6\xe3\x1b5\x10\xc5C\xec3\xdb\x9c\x86\xcc\x8d:G\xa5\xc9\x8d\xc2\xca\xe1\xf9A\xdf]P\x8d\xb9g\xec\x96\xbe\xfdcyM\x9fq=\x1fy\x00\xb1G\xcb\x90w5[\x8fs\xf4\x9d\xcc\x96\xc7]\xb7H&\xdeP\x82\x92\xef\x9e\x12\x94\x90\xdbJP\xa8\x91\xf2\x9a\xb1\x17\x07jN\xcf\x03\xe5\x9e\xb1 \xe9\xae\x1e\xad\x87Z1\x90\xf5Im\x0e\x13}9W\x17\x92\xc05jA-\xcf\x8d\x8c\xf4\xe3\x98\xdc\xdcJ2/g\x7fUV}\xa1@\xdd\x96\xc8m+\xbf\x8b\xd5H\"\xb6.\x83k\x8f\x0f\x89\x0b\xa0\x9f\xd5\xde\xceh\x1fQ\xdcJ\x16{\x82\x9c]\x1e\xab\xb3\xb0\xd7\xaf\xf0Vd\xbb\x85%\x8a\xa9\xdeF\xe5\xef)\xdb\xf0;\xe5c\xa6w\xb0\xd2\xdb\x18\xe9 6\xfa\xe0SZ\n\x03\xbd~\x7f\x04\xf8m\x08qUE5\xed\xf6\x97\x83Iv\x95x?\xc8\\P\x86\"\xc0(\x9c\xc9Q\x1fl\x1d\x92\x0fs\xabG+5eC?r\x9e\xd1i\x19\x99\xf4\xa84\xdcjv\xbb\x82\xae\x07~\x1e\xac\x9b\xdd^7*\xc4b\xb6~,\x04/\x16+OK\xf2\x04\xa6\x7f\x94 \xd3G\x9d<\xc1e},aF\xd4)t\xbd\x1ej\xe0$\x1dO\x15=\xeaA\x15\x84o.\xaa\xcbt\x07(\xd8\x9b\xf9M\xf6n\x92\x83t\x94\xbb\xba\x8d\xea\xb8\xac\xadH\xe5\xbb\x86i\xfb\x13\xd5\x96\xfc\x97\x00\x99pW\x9a\xcbB\xd3\xa6\x98S\xed/\x8a7\x00h\xf7\x05dnY\xaa;CS'\xad\xb86\xf1\x9e\xb8\x11)n\x0eM\x95tzP_\xc7\xe7\xee\x00\x9b\xcb\x032\xb77\x97\x0b\x04\xecn\x10\x08q\x85\x80\xcd\x1d\x02\x99\x1b\x9c\xcb=\x02\x0e\x17 \x80\xddM\x02\x16W \x00\xed.\x01\xcae\x026\xb3\x86bO4\xb2\xb8O\xc0\xd5\xc9`u\xa3x^\xf3\x85'G\xbbT\x0cM)~\x15C\x99\xf0\xb3\x18\xbf\x87;[\xc01\xfe\xf29]\xc0\xeex\x01\xcb\xb5]\xe6\xee\x1928a\xb8\xdeTG\x0c\xacr\xc6\x88\xa7o\xf9M\xb4QK\xbd\xe3\xea]p\x0dk\xb9\xddJ\xbd\x82W\xd1\x95z\x0d\xef\xa4H(X\x1c\x84\x14\x15\xf2\xee\x95 \xe59\xb4\xdb\x93\xf5\xb82\xf3\xe5\x05\x9cV\x0cN\xbb\x15_b(\x17`\xa4'9Z\x13\x1c\x87\xf8\xe4\xc6\\\x89\x8d\xe5\x02\x0c\x94r\x01\x86|=k\xb2bB\xa2bB\x92\"a02\xa6#\xe6ME\xcc\x96\x86\xe8OA\xcc\x96~X.\xc0(\x17`\xacH\x13,\x17`\x88\x8eV5\xa6$\x00\x86\xdc Q.\xc0P\xa4\\\x80Q.\xc0Xq\xd7\x84\xff\x19_\"^Z\x12^\xb9\x00CH\xce\xf4:kj]\xb9\x00\xa3\\\x80\xb1x\xcc\x9f&W.\xc0\x88O\x82\x8b\xff\xba\xde\xe47_\xe2\x9b\xfb\x02\x8cT\xde2\xc3\xaf\xb0\xe4,\xb3\xf3\x95\x11\\e\xc5EW\\tR\x8a\x8b\x0e\xa5\xb8\xe8\xe4\xeb\xc5EW\\t\xc5EW\\t\xc5E\xa7\xfc\x7fq\xd1\x15\x17]q\xd1\x15\x17\x9d\x94\xe2\xa2+.\xba\xe2\xa2+.:(.\xba\xdf\xb2\x8b.\x91\x82jA:E\x11N\x91\xfb\x7f\xd2=\x98B2%\x8f\xd2\x8a>\xcd\x95\xb1$\x97\xd2CA\xb5\xbbp\xb9'F\xcf\xd0\x14\x11\x9d\x95\xd2\x1b\x9f\x1e\x18\x867\xf2\xc1'\xc9\x89&\n\x98\xf18\xed\xcc\x8b\xfa\x1f'\xd6=*g\xfc7u\xf3\xe1\xcf\x8f2{\xf0\x8a\xf5\xc7\xb6\xe9Yp$\xe2X\x93(\x1f\xe7\xa9W\xc9h \x06\xf4}\x8f\xfdn\xb0T)^\\\xe5=\"\x19T\xc4\x92\x9a\xd9kl\xa8\xea\xbd8:\xd4\xfd|\xe2\x14\x9cO\x8a\n[\x14\xb8=\x06\xdc\x9a\x17\x0b\xae6\x03X3\x0e\xc3\xe8c\xa4\x9842\x93\xfa\x80\xb2I\x96\xeb$\xae\x19B\x9fV\xeb~\xa8\x06\xfdD/\x0c\xc7\xf8\x17i\x0f,\xdf\x86h\x0fkNF\x08\xfeO\xf0\xe2\xf2\xf2\xcd\xc5\xcb\x177\x17\xef\xde\xde\xbe\xb9x\xfbO\xb7\xd77/n\xceo/\xde^\xdc\\\xbcxs\xf1\xbf\xce_\xdd\xbe\x7f{}y\xfe\xf2\xe2\xf5\xc5\xf9\xab\xd0\xd7\xff\xf9\xfc\xea\xe2\xb5\xfc\xfd\xfa\xe6\xc5\xd5M\xe4\xbb\xe7WW\xef\xae\xa2\xde\xbc~\xff\xf2\xe5\xf9\xf5u\xe8\xbb7\x17\xbf\x9e\xbf\xba}\xf7\xfef\xf1\x82\xd8\xb6>O\xe9&\xb7We\xed\x17x\x0e/f\xf6\xb7\x7f3\xfd\xfd\x9c\x10\x8e;k\x8d@wwy\xd4'3\n\x1bGe7\x8c{}6\x1a^\"\x03}E!\xfc\xdb.\x8a\xe0\xbe\xd8E\xee\xcb2g\xe9\xd8\xb5\x1b\xf5\xfe\xf3U\xc5\x89\x01\xb1(p\xd9\x0c[N\x94\xbb\x90i\xe4,4\x0f\xf5\x81m\xa1=\xf1,\x90=\x83OU\xcdi\xf6d8\xbc\xda.\xa5(\xc1\xa2\xd0\xa9\xec\x0eRl\xc6\xc8\x9a\x8a>htd3c\xe0\xa1\xdaJ\xbe1M\x99\x91c\x11e\xed\xf5\\F\xf0\x19ZGN\x15\xccM\xf7\xb3PH\xb1\xb3QL*\xd3\xab\xb3\x92\xa5B\x8a\x85\xa4AQ\x9c\x87\xb5bRj\xcf\xd9rgmyVm\xf0\xf5\"\xd8W\xef\xd5|\x01\xaa8:\x10V\xd4\x89\\\xd5!\x9e_\xc0\xa2M\xdb\x1b\x18>'!66\x0c)\x04+\x86\x94\xe8-L\n[\x06\xa1\xce6\xe8\x11\"#\x8d\xd9\x7f\xe8\xd5\x12\xc3\xfe\xc0me\xd7\x1e\xc4\x1c\x1f\x15\xc8:\xa9\xa6S\xf7U\xbdk\x16\x08\x12?&\x8c\xef\xf0\xdd\xd48C\xd1fS\x9b\x83\x083'\xd6\x0b\xeb<\xbe\xc6\xbf/\xe9A\xe6E\xc6\xb6\x08\x08\x1d\xf1\xd3\xd6r\xe7\x0b\xf8\xc6\n\xccU\xff\xc58\xfb)+\x88<\x07\xdea\x9a\xdd2CN\x15\xcbeuSY\x81\x95\xb1\xce\xd4_\xc8\xa3\xf2r\xad\x13\x07T^\xdb\xf1\x19[Y8Su*\xe7Q\xee\xabz\xcf\xa8y\x87\xb5{\xcd\xff\xbc\xfc\xc8\xf8\xca\x93}`\xbeQJ\xeb\xd3\xf3Q\x05v\xd5\xe2\xec8G\x00\x8dm\x989\xa1\xc1\xcex\x0c\xaeb\xef\xad\xcc\xc7\xa0,x\xeb\xd9\x8f?\x8d\xd6H!>F\xe1\xc9\x8eOS\xc7\xf3I\xf5\x9aZ\xd6\xfb\xbd\xc8\xc0\xfcN\xd3\xb7de\\\xba\"h\x9e\xea\nur\xef\x867\x97\xf5; \xacl\x98\xdb\x83\xa4\x8a\x1eN\xdd<\xe5\x85:\xb9\xb9\xe4\xb1\x11|\xc7\xde\xc2\x8e\x0dd\x1a\xea\xa9G?\xa1XQ\xeam\xb8c\xe6\x1d_\x12W;ep%\xd5\xdd2yy\x01M\xff\x8dc\x989vS\xd6wl\x8e\x0b\xcb\x0b\xb4\xc1\xa4\xfa\xf3\x95\xf0\xf6\xd8\\@\x92\xbe\xc8\xd6\x82\xe5>\x86\x7fb\xde\xe1\xfa0\x7f\x81q\x84l\xe6i\xd6FF/>\x94x\xf1X\xedD\x06\xfes]\xd5\xe5\xf4'-a|\xfa\xb9\x13cD\xfb\xe6A\xae\xb8\x86}\x1e\x96\xe9\xc4\x10b3\xdcQ\x14\xc6\xfeF\x96\"\x0f2\xe3?e\xd6}/\xb6\x93\x97\xd5n\xa2\xf2\xc2\xbfkJ\xfe}\x9c$\xfc\xf5Q\xdd\xd8\x01\x0c\x0em?\x00\xe3\xc11<\x8e\xe6\x0c.\x06\xc5]\x7f\x1c\x1e\xa1\xbe\xd7\x07\xd1\x03\xeb\x18\x8fnjZ8\xb4\x9d\xdci-BK\x86v\xa8Bc0#\xa81\xb8z\xde\x1b\xfc\x1f3o\x8b\x0c\xacR\xe2\x81\xf4\xfa\xab\x1d\xc5w\xcf\xb7\\\x89\xbe\xc5\x1e\x97\x8a\x9e\x0d\xcf\xa0\x1ez\x19\x15\xd6\xc3\xa9\xc1A\xb4\xc5\xe0\x9dO\xb52l\xec\xdf\x10\x8b\x14v\xb2\x96!V\x13\x1cR7\xb0\xbb\xba|9\x0dD\x89S\xf4\xe3V\xb4c\xda\xc6y\xd3v\xf8 \xc7P\xa45\x95\xd0\xc6\xb8\x83\xe1'\x0c\xb5\x99\x8b\xb6\xc9'\xaf\xdb\xc3\\)\xf2\x1e\x8e\x8e\x1d\xf9R \x7f\xae\xba\xa9gm\xf7\xc2,\xda\xc8\x07\x97\x8e\x9c!\x98A{\xb6\xfc\x16|\xed\xfa\"\xdbl,3\xfa\x1a\x83\x86\xe4,ve9s\xd8\xc9\xe0Ug\xb9\"\x103%\x94k/\x80\xf9\\_\xdeS\xec\xbc\xb1w\xd0\x8cz`\x8f\xae_\xa6I6\x8d\xaf\xb8J\xc7\"-\x14\xd6\x92\x05mq\x9e\x14\\\xe7\x04\x8f\xf7\xc6sR\xc8\x82\xbb\xb8\x90\x97\xd0\x1aXN\x7f1\xf8\x0b\xa9\xc8\xe4\xff\x97B`0\x81(\x8c\xb3m\x14\x12\xb3\x1e \x08W\x10\x80\xc6\x84\xbeM\xe11\xa1\xef\xd2\x88L\x88g]{%\x07*\xe3\xc3e\xd6\x7f\x0f\xd5\xfdo(\xfb7\x0c\x9euc3\xc1\x1d\x99\x86\xce\x84\x16\x93\x0d\x9f -0\x11\xa1 \x19I90\x1a7J\xe32[Y\x91\x1a\x12\xab\x89^+(\xbf\xb2\xd7@{`\x92\x08\xdc&\x04\xb9\xc9V\xadH\xfc\xc6\x03@\xb8W\xad(h\x87\xd4d\xeb@\x8fc\xd1\xe7Z\xf4n\x1b\xc0\xff\x01\xc0\xdb\x0d `\x96U\x98\x90U\x93\x03+\xf2\xa2E\x19\x1b\x93\x0f3\nF\x8d\xfc\xb8\x91\x139\xf26\xde3\x98\xf3\xe2Gv\x04\x89\xc6\x90\xec(R2\x8e\x94\x84$E\x1ba+\x9e\x94\x07QJ\xb6\x0c\x0e\\\xc9;\x92\x002cK^tiM\x95\x1c3;/\xc6dG\x99\xec8S2\xd2\x94\xfc\xe1\x1dx\xd3\x9a^\x8e\xc1\x9c\x9c\xa8\x93\xb3p7\xaa\x93\x1f{\xf2\xa0O9\xea\x9a\x0d\x83\nD\nbq(\x13\x89*\x8e\xfd\xe2\xd8/\x8e\xfd\xdf\x88c?\x046\x9e\xbd\xf9\xc69V\xfc.\x12:pL\x8f\xed\x15\xda\x84\xf7^\xf7\xd9!\x168\x1e\x02\xb4\x9b4\x1d\xce\xe7\xe9v\xe3\xdf\x0bD\x8c7o\xaf\x00|\x01\x86\xaa\xdb\xb1\xd0\xcb\xe6\xe8\xc9\xba\xec\xc6`\xc4\x00\xef\xcc6|\x9fa0\xf0\xfcr\x01\x80\xcb:Q\xd6\x89\xdf\xe2:A\xf7\x92\xcb2\xfb\xa1_\xcd\xaf\xa5c\xbe\xb3\xd9\x08@{-\x958#\xed]\xf0\xa2\xe1Ex)#N<\xa6\x1bn\xe3\x11y@I\xb5\xce^\x0cw*a\xfd\n\xfam\xa3\xb7\xea*\xb1e\xfd \x97 y\x8b\x93$9\x1bZs\x19\x13\x7f\xa3K^\xed\xda\x19H2\xb3\xf9o\x8e\x03\xb4\x0f\xa8\x82\xbc\xf4f(v\x923\x94|Tg(\xd9\x08\xcfP\xac\xb4g(C<\xf9\x19J.\n4\x147\x11\x1aJ\x14\x1d\x1aJ4)\x1a\xddw\x8fGy\x03\x15E\x8d\x86\x12M\x90FjC\x87\x86\x85&\x0d%\x85,\x8dTx:B\xc5\xdbj)/\x828\x8dTd%SCI\xa4T\x93J\x02\x88\xd5\xc87\x83\xc9\xd6P\x12(\xd7P\x12\x88\xd7l\x13\xddR\xd5l\x94l(y\x89\xd9P\xb2\xd1\xb3\xa1\xf8I\xdaP\xb2Q\xb5\xa1\xd8\x08\xdbPRh\xdbh[AP\xb9\xa1\x0c!\x84n(\xb1\xb4n\xa42\x1b\xd5\x1bJ$\xe1\x1b\x8a\x15\x90\xf1l)\xacgW\x94\x90\x1dG$\x1d\x1cmL%E\x1c~#\xed\x19_m\xd2\x08\xe2\x0cu\x9c0\x8e\xa0\x89C\xc9@\x16\x87\x92F\x19g\xa8\xe3;\x1ar\xf3\x90H\x1fg\x96d\xd0\xc9\xa1\xa4\x90\xca\xa18\xd9\xd6P,\x04s(^\x9a9\x14\x82\xe1\x8aK8\xe5\x1c\x8aM\x8f\xc1)\x94HB\x87\x12\xde9>B:\x14_/x\xc9\xe9PVP\xd4\xa18z'\x92\xae\x0e\xc5IZ\x87b\xa7\xae\x9b\xfen%\xb0CqtZ(\x99\x1d\x8a\x8f\xd2\x0eE#\xb6CI\xa0\xb7C \xb9C \xa7\xbaC\xf1\x12\xde\xa1\xd8:\xd1$\xbfC\xb1>\xef#\xc2CI\xa3\xc3CqT\xd9\xf8=\x89 \xcf\xd0\xa6\x11\xe6\xa1\xa4\xd0\xe6\x99%\x184z(Idzf\x95\x97\xe4z(9)\xf6P\xacD{(\x06\xdd\x1eJ\x1e\xd2=\x94l\xd4{(y \xf8P\xc2h\xf8P\xbcd|(\xc2\xe1\xe3\xa3\xe4[<\xec$\xe6C!\xa6\x17\x904n(\xa1dnn\xaa>\xa1+\x8c\xb0O<\xec\xa7\xedC!\x1a\x94\x93\xc2\x0f%\x89\xc8\xcf\xd0f\x10\xfb\xa1\xe4\xa3\xf7S\x8a\xc9B\xf2\x87\x92:F\xbc\x84\x7fB\x9d\x87\xf6\x0fE_\x9a\xecQg\x02'\xa5\x03o\xf88\xf9<\xb0n4\x07\xe8\xdfW<\xd8D\x80\xec\xa6m\x1a\xb6\x19('\xee\x14rE^s\x8cr\x9c\xaf\xe3\x9dEb\xb1K\xe2\xbea\x11\xb2\xcb_t\xd7X\xd7\x1a\xe7V7\xae\x00\x9e\xc5\xa1\x11\x02B\xde\\\x0e{\xf0\x9f\xb0!\xe0\xe0*%\xd6yoU\xb8<\x85Z\xb6\x81\x91N|\xab2\x87s\x1fb\x1d\xfcVm\xbcR\x1e'?\xe4p\xf4C\xbc\xb3\xdf\xaa\xaf\nr\xf8C\x9a\xd3\x1fb\x1d\xff\xf6j\xcb[R|\xce\x7f\x88\x04\x00\xac\xca\xe6\x9bS\xdc \x00$\x00\x01v\x85\xe26\x15\x07\x18\x009\x01\x01\xf0\x83\x02\x90\x0b\x18\x80$p\x00\xd6\x03\x04\x90\x03$\x80\x04\xa0\xc0a\x9f\xc8\xd3\xd1,\x99\x01\x03x\"\xd0\x00\xf2\x03\x07\xb0\x02<\x80h\x00\xc1i\xc3\xdd \x02D\x01 VU\xee{afY\x01(@nP\x01\xbc\xc0\x02\xa4\x82\x0b\x90!\xe3\xc3\x034\xc0\x8a]RN\xc0\x01\xbc\xa0\x03\x04\xd6,\x0e| U\xc95\xc2\x0d@@N\x10\x02\xd2\x80\x08R\x9fX\xe8\xed\x1b\x9b\x04@\x82\xd4G\xdfq3K:0\x01a\xfew\xf0\x01\x14\x10\x0eR\x80\xcb\xeb\x18\x01V\x80G\x9f\xc5\xd3\x92\x01\xb8\x80\xd5\x9d\x17\x06`@`\x0f\x05\x02\x19\x10\x03f\x80\xbf\xe7\x92@\x0d\x08\x036 \x00\xdc\x80 \x80\x03\xfc\x9d\xba\x0e\xe8\x80`\xb0\x03l\x80\x07\xe4\x00=`\x0d\xf0\x01\x11\xe0\x07\x84\x03 \xe0\xe9d\x1b\x10\x02\xbe\xf7\xc2\x00\x11\xc8\x04\x8a\x80\xaf:\x96\x99\x11\x05\x90\x90\x9a,\xb7\n\xcd\x92\x15(\x01\x07X\x02 \x80 \xa9\x8c\xba\x91h\x96\x04\xe0\x84\xd4g?\xdaz\x00\x15\xb0\x83*\x90\x19X\x81$p\x85TG\x01.\x10\x0b\xba\xb8\xec\x96\xc5G\x0d+\xc1\x18\x08\x07d`-(\x03\xab\x80\x19\xb0Oop8\xdfa\x85\x03>\x04\xa4\x81\xb5@\x0d\xac\x01k\xc0\xde\xc8\x04\xd0\xc61\x87\xa8\xbf$\x809\xf4\xd8\xb6\x01:\x10\x0d\xea\xd0\xaal@\x0f<\x01\xd8\x03\x99\xc6\\ \xe8\x03\xc1\xc0\x0fXVs7\xed@\xca\x85\xedt\x7f\xcf\xd4*\x96\x0d\x92\xfd\x12\xf7Y\x9c|\x0b\x05n)p\x0b\xb9\xe3)pK\x81[\n\xdc\xa2(*pK\x81[\n\xdc2K\x81[&)pK\x81[\n\xdc\x02\xab\x11\x83\x02\xb7,d]\xe7\x15\xb8E\x95\x02\xb7\x14\xb8e\x96\x02\xb7(R\xe0\x96\x02\xb7\x14\xb8\xc5*\x05n\xa1_(pK\x81[\xbei\xb8\xe5zbu\xd6\x10\x97\x07\x92\xfa\xd9q6\xba\xdcWus\xc3>\x0f\x16\x86\xe7\xe3\xf8\xf7\xdb\x81}6\xf8\x1a\xc1\x7f\xc0\xf7`FS\xd1\x8eF\xa0\xf1\x17\x0c\xdbu\x03m\xb7\xb5\x9c\x8e\xc7C\xa8\xf0\x0eZ\xfd\xbfS\xbf-\xfe\x8a\xecg\x9b\xb6\xb9\xafw\x96\xdc!\xce7\xf6\x92?\xb1\xb4\xee\xf8\x96\x18\x0ft\xfe\x90\xae1.o(\xe2F\"\x9f{\xc2\xda(5{\x0bS\xa0\xb8\xb3a\xc9\xd2l\xa8\xab{~\xf7\xc7r\x9d{b*l\xaaU\xeb\xd9\xb1%+\xba\xa1\xcb\xa4\xcc\xf6\xd0\x91\x92l\x81\xa2\n\xe3\xca\xc9j\xee\xdb\xab\x1a\xa8\x9b\x81u?A\xdb\xc1\xa6k\xfb\xfe'sD.\x87\xb0\xd2\xe5\x85o\xb4\xf0\x8d\x16\xbe\xd1\xea\xf7\xc27\xda/:k\xc1G=n\x16\xc5\xddN\xea\xab?\xcf\xef\xc2\xd8\x95x\xb0\xee\xce\xc2\xc0Y\x188\x0b\x03\xe7\xd30p\x8aO\xba\xe4\xde\xf4\xd1aZ\x998U%?\xdb\xb4(\x9c\x9c\x0eJ\xce\x8bf\xd3\x1e\xeaf\xf7\xea\xa6\xda\xddtU\xd3\xdf\xb3Nt\xe0zZN\xf1Y\x9e\x98\x99s;T\xbb\xdb\xa1\xbd\x1d\xbaj\xbbf9\xb2/7\xbc\xf1\xed\xcd\xa8oi\xfcq\x06\x88Ut|\nw\xe6S\x00\x80\xa1i\x10]\xd8\xb1-\xdcw-\xe1\x1c\xc7\x0f\xbaa\xf5\xc7\x19\xc3\x90\xc3Y@\xf4=k\xf4\x0d\x12\xfe\x94\xa5\xb1\xd7\\\x95\xbe\xaa\xca\x8cn\x89\xaal\xb8\x91\x10\xcde\xfc_fkE\xbd\xbf[\xfe\x86m\xcbR\xd7+\xd9QZm\xad\x1d\xf8P\x8d\xb6\xcb\x0c\x9a\x91\x91\x14\xcf\xb8\x9d7\xbf\xca\xae\xfe\xc8\x96\xdd?\xfe\xb3\xee\xf8GW\x87*YUb\xf2\xcc5\x86J\x8c\x1c\xf1\xc0T\xd9;6|b\xac\x81\xe1\xd3r\xd1:\xf5\xac\x9bQ\x17\xaaD9A\x95Bp\x1f\x84\xbb\x07\x1e\xc31\x0dX\xadX\xdc\xe0\xa9Mj?U\xdd\xb6W\xfbd|y\xac\x85\xf8\xa9\xec\x16\xcan\xa1\xec\x16\xbe\xe0n\x01 \x96J\xdf\xc1\xf4\x1d\xb2\xd2\x87s\x7f\xbb\xb4\x05\xb2\x81_V]uX\xbf\xc98\xf2\xd7\xe2,Q\xbd\xf9`\x9e\xc1\xad\x87y\xfbQ\xfeP7\xb7{\xd6\xec\x86\x07\xf38\xef\xf4\xa78B%\x0e\xd5\xe7\xcc:m\x96\xe1\xad\xe8\x06\xfc\x00\xda\xb8\xea\xaa\x03\x1bX7\xae-{>\xb0\xc5\xaa(?\x9f\xa6Kv\xa9\xfa\xfb\xb8AK\xee\xe2\x8e\xedn\xd9\xe7U]\xf1\x9b\xfa*\xe3\xc4 \xfe\x00\x929~|I\xed\xe9\xbb\xbaM\xee\xe8'k\xe1\x9f\xebvu\x03\xef\xeav\xd7U\xc7\x07\x15\nl\xbbj\xb3O\x9f\xb3h\x18o\xebmd3\x89\xa5\x17\x9c\x9bW\x80k^\xe4\xc5+}\xfbz\xf1Jn\\\xb1m\xa2nb\xcd\xdbT\xfb=\x19\xf97\xb4\xf0\x91u\xf5=\xdf\xa1P\xce\xd1m5\xe8A\x9cU\xff\xe1\x96\xaf\xe0_\xae\xd5/\xfa\x0f/\xf9\xe1Ak\xf5\xbc\x03\xc1V\xf35\x1e\xbdxU\xff\xc1\xdc\x8c\x8d2\xb7\x97j\xdc\x81\xbb|\xbfh\xe3~\xad\x1b\xb2q\x87\xba\xa9\x0f\xa7\x03\xe0\xb1Im\xe3|`$\xd4m\xda\xc3q\xcf\x06\xab\xbb\x9b\xb7_\x04\xc0B\x7f\xdalX\xdfs\xb4Y{\xf6\xd8\xb1c\xd5\xb1\xdb]e\xb9\x05\xe2)\xfa\xe2\x12\x0b\xfdK\xd5\x1b\xa7\xc9\x83\xec\x86]%\xb7r|\xc7\xb5=q\xf0\x91F2\xb0\x11\xbc\xadT_\xf4\xc3\xb8c\xa2&\x8e\xf60\xfb\xcc6\xa7\xe1\x0bw\xc69\x16\x9a\xad3\xb0\x11\x08HP\xbd\xe1\xeb\x84{\xc6n\xb1d[\x1f,\xbd2R\x0c\xef\xcc\xf2\xa5\xe8T\x9b-k\xda\x03\xfd'\xcfG\x19\xc5\xd6\x12\x14\xcf\xeb>\x0ce\x94\x97m=\xef\xb0+\x18\xda\x0fL &\x15V]n\xb7\xabf\xcb\x03@y\x85l\xd1\x88o\xdf\xdd\x9c?\xe7\x81\x11\xe2\xe3c\x84A\xcdcG/\x9aA\x98\xbd)^W\x05`I\x85\xc2\x8fG\xfem\xc2\x08{~\xd2\xa9;\x04\x06v\xed\xae\xe5h\xa7\x19\xb4\xe0\x1a\xc7\xaf\x19{q\xa0,\xdc<\x8c\xef\x19\x9b\x02\xd5\xabG7\xa67\xb4r:\xdaL\x9c}\x10\xebNS)\xef\xf8\x1b\xc1{\x8by\xa6hz\xb8i\x96'\xf9\x93\xf0\x11(+\xce\xcc,\xd8\xdeC\x05\x1b\xd6\x0c\x9d\xc8\xb6Z*\xaa\xe6,\x85\xc9sv\xf7\x08\x95\x9d\xe5\xb0:\x1eo\xb5K\x8c n[\xc3\xe3\xa4\xeb\xe1\xf1v+\x00\xcc\x95&OnG\x05\xe2$\xd5\x81T\x07w\xf0T\x8b?\xac?\xd6\xe2{Q\xe7\xda\x81Lc\xb4~v\xb7=\x8cMT$\xd61{zbLR\"\x9d|\x18\x95rH]\xe1dM4\x1c\xe2\xd3\x0b#\x93\n\x8dT,w*aT\x02aT\xda\xe0\x9c\x1eH\x99R*Y0&EPI\x05\xd4\xb4Y\x12\x03c\xd3\x01\xa7\xb4?\xbd5D\xa4dL\xea\x9f=\xc5/1\xb1/(\x9d/\x94%\x85\xcc\x9b8f\xe6b\x84'\x89\x99\xef\xfe\x8djkT\x1aXHc})_\xf6\xb6y\xd3\xbbV$u\x91m\x8eL\xe0r\xa6m\xd9\x93\xb5\\)Zd'\x84\xa6c\xf9\x92\xb0\xb4\xd4\xab\x84\x84\xab\x804\xab\xf0\xe4*oJ\x15\x91\x81d\x14G<\xe3K\x95JK\x90\"+\xa5\xfc\x12\x95\x02eKwJIr\"\x12\x9ab\xd3\x98\xc8\x94\xa5\x84D%c\xabmME2\x12\x90\xf2\xa4\x1d\xc5'\x1bi\x89EQ\xe9D\xd6\xd4\xa1\xb0\x84!o\x9aP`rPHJ\x90\x91#c\x96\x16\x9a\x80\xe1N\xfa L\xf5 H\xf0YT9!\x99\xc7H\xdcIH\xd7\xa1Rs\xe2\x12r\xa8\xe4\x9b|)7\xf1_\xd7\x9b^\xe3K\xaa!\xee\xac\xff\xc7E$\x8b\xe6b\x0br\xe1 |\xf9\xea\xf2\xa5\xd0\xe4\xf4\xe4]\xf1\xa3j\xb0\xefN\x00s\x8a\xef\x0e\xfd\x96\xd7\xf8\xbb\xeaI\xaf\x14\x14o\x81\xee\xcd\xef\x86\xfb\xfd\xd6\x9ceD\x95~1\xf2r\xf8\xe0\xc5\xec \x99\xa3#\xd2\nL\xb7\xb5\x85\x8bmM\xa1sF\x93R0k\xa4\xa3\x81\x17>>#\x90\xb1EJ\xd3}U\xef\xd9\xd6\xe8\xe6\xd7\xfc\xe7e/\xe3\xa3\xc9=\xcc}\x1e\xeb\x1a{>\xbe\x82\x8dC\x0f\x8e\xc1\x997\xd6M\xe6/\x89\x97p\xc0-\x9b\xb0\xc0~\xd1y\xe2\x1a\xadg\xaf\x95\xde \x18\xb4Z\xd3\xc8f\xa54i\x82m\xc4\xe7\x99g\xe9\xd8R\\\xa5\x0dDa\x1a\x13M;\xe0\xb8\xc0^\x98\xce\xc4\x1a\x06n\xef\x8dkuN\x06t\x876\x97\\\xdd\x11?\x87\x88\xf9\x13ZP\xfc\xbc\xd1\xbf\x87\xb4J\xeb>\x08/\x8c\x88@P\xbe\x8f\xbe\x06\xbch\x1e\x83\xbb\x7f0 \x0c\xb2c\xec\xce\x8fL\xb0\x05\x0dY\xe4\x81+\xe2\xa1\n\x1a\x9c\xa0\xf6\xec\x01\xc0D4(1\xc3\x10\x8a6\xdd\x07\xb3\x1a\x8cH\x04\"\xf8G^v\xca\x02\x84H\x04 \xf89l\xa1]U\x9e\x0c<\x18\xe7\x9f|0C\x02\xc4\x90\x11^\x88\x84\x16r\xc2\nY \x85|pB\x16(\xc1\x0d#\xc4C\x08$h\x90\x150 \x0e\x0fK{\x90\x15(\x88\x00 B6\x02$0`_\x9br\x02\x02\xc3\x04\x06\xd0\xe5\xe5\x00\x01T2\x95 \x00Ht\xfe\xa7;\xfe\x17KM^W\x7f\xac\x9b\xdf\xea\xf5&\xdc\xfbN\xd7\xfe\xd2\x97\x18\xe6\xd2_\xbe\xf37\xbd-\xab\xdd\xf8\xbe\xc6\xb8\xdc\xf7t\xfd\x9dn\xfb@\x97\xbd\xd1\xae\x08W\xbd\xd5MO\xbb\xe8m\xeey\xa3\x91!ny\x97K^q\xc7G\xba\xe2=n\xf80\x17\xbc\xd3\xfd\xaey\xb9\x17\xea\xb5\xbf\xb9\xdc\xed\xf1\xaev\xa3\x02\xe2\xff\xb2\xb9\xd73\xba\xd6\xb3\xb9\xd5s\xb9\xd4Iw\xfa\xc2\x95\x9e\xeeF\xcf\xe2B\xcf\xe7>\xf7\xbb\xce\x9dn\xf3\x00\x97\xb9\xcf]\xbe\xf0;/\xb5\x87:Q\xed.\xf2\x00\xf7\xb8\xc75>U/\x97K<\xa3;<\x8f+<\x8f\x1b<\xee\xcb9\xdd\xdf.\xd7\xf7h.w\xddqs\xb6\xab\x06\xf6\xa9z<\xebN\xcdP\x1f\xd8\xd9\xf9\xec\xa8\x0bp\xa4\xf8\xddz\x9bvk\xeco\xebf`;%\x80[np\xebf\xf8\xfb?\x89_E\x0f:uo\xd9P\xd5\xfb'&\x80\x18,\xb7v\x90[u\x14_\n@&\xef\x11\x8a\xebV\x8e<\x9e$\x94x\x7f\x92\xa1\xca\x1a\xfc\x1a\xedeB\x89\xf65\x19\x9a|\xb7i\xac\xf6;\xa1$z\x9f\x88\xde\xb2\xde\x9a\x91\xe8\x892\xf4Yo\xc9H\xf4J\x19\xfal\xb7b\xe4\xf3U\xa1$x\xac\xa4\x82l~+\x94H\xef\xd5T\x9bl>,\x94,\x9e,\x94|\xfe,\x94,^-\x14\x7f\x88l\x8a\x87\xcb\xb4\xa2\xd6['R\xfc^\x862\xfa\x96 b/AY\xa94\x9f\x98\xa1\x8e\xbaM\"\xc2S\x86B\xde\x1e\xe1X\x8a\x1d\xc9\xf6\xbeU:\xd2\x8ff\x1a.\xeb\xad\x10\xae\x1a\xe4\xf0\xac-\x14R\xb7?$z\xd9P\xd2}m\x0bu\xe6\x82\x9b\xe8}[\xe8\x1a\x88[\x1db\xfdq(\x9e\x8b\x08\xac\xb77x\x83oi*\xf40o\x9d\xfd\xfd\xbf\xd1m_\xed\xbfC k\xbc/\x14\xd7\xddRo8n\xb0w\x0f\xc5\xd2\x03\x11\x9e>\x14\xcfm\n\xae[\x14\xdc\xb7'X:%\xc4\x0f\x88\xe2\x0b\xd0%nG\x88\xf4\x0c\xa2\x04\x84\xe9\x86z Q\xbc\xa1\xba\x96\xeb\x02\x88b\xc9\xe7|!\xbb)\x9eD\x14K\xf5\x16\xbfe\xf3-\xa2d\xf40\xa2d\xf33\xa2\xe4\xf26\xa28n\x13 n\x11H\xf7?\xa2d\xf1B\xa2\xe4\xf3E\xa2\xf8=\x92(\xdep\xde \xef\xe4\xe2A\x0f\xcb?A|O\x95\x1a\xea\xfb\xf2\xb1\xf9\x07\xf8.\xc5\x83\xfe\xe0^\xa3\xf2\xb9\xbc\x99(\x19}\x9a(y<\x9b(y\xfc\x9b()\xdf\xdb\x1b\xea\xeb\x0f\xf6\xc5\x95A\x84\xf1q>\x80q/\xf9P\x1f\xfb\xb3\x8f\x7f\xc4\x8c\xfa?\xef\xdb\xcd\x87\xf5\xac\x1a<\xfe\xb5\x0d#*a\xd0Z\x85Vb\xeb\xa9\x84P\xaf\x12\x82\xa2t\xac\xeaM\xba G\xb1\xbe\xe3\xdd\x15W\xa8WG\xfa\xa7Dys\xc7LQ\x89\xa2\x86\x86\xbe{\xdd+\xd3\x9f\xee\xfac\xb5a\x04 X\xc0\x81\x95$\x05r\xf0\xec\x8a\xc2\\\xf4_\xb2BP7}\xbde3\xa7\xbd\xa1\x8d\xb7X\xd0H\x19\x7f\xbccD\x1f\xb8z\xfb}\xcf:\xfe\xf5\xf5\xaa\xddW\x9ba\xf2aN\xa3\x94\xf7\xb4\x18\x06\xe3\xef\xbb\xfa\xa3F\xb4/\x86\xd2\xb2jc\x9d\xe5\x07(\x1c\xb2\x85C\xb6p\xc8~A\x0eY\x07\x13\xecrA\x0dI\x9f\xc17\\\xd93\xf4\xd2}\xa5\xfe\xbaz\x05_\xe8|\xda\x85\x9c_\x12\xa2gz\x84\xac\xa1/\xf1E\xdd\x8e\n}0\xf1\x93\xcf-Y\x96;N\x0c\xd6\x1d\xabnx\\_8us\x8a\xa2\xd0XI\xf9\xf6\x81\xaf$u\xf3\xb1\xdd\x7f\xc49A3\xbb[*\xfc\x8d,\xa1\xf5\xd6XB\xc7\x11k_?\xd5\x06A\xdd\x9bk(\xf7(+\xbf\xbaV\x8a\xab\xa52\xac\xc7\xd0\x9d6\x98F\xb1(l\xb9\x03\xb9P\x89\xe1\x07\x04\xff6\xec\xc8\xdf\xfb\x1e\xa1\xb1\xefy\xcb\xbaj:\x83\xf2l\x9b=4l\xf8\xd4v\x1f\xfa\xb2\xa2\x96\x15\xb5\xac\xa8\xdf\xd6\x8aJ\xaes\xce\x85U}\xfb\xe7\xc5\xeb4\xcf\x9c\xb1\xbe\xaa\xef\x04\xaf\xa8\xc62G\x0e\xed\xd4\xa5\x8d^\xd4\x9cEE\xadZT\xd9\xe4\xfaD\x16m\x99\xbc\xd4\xc4\xcd\xb2\x0e9V\xa0y\xed\xa1\xc7X\xccz\x93i\xa5\xb1\x0d\xbf\xe9\x04\x19<\xf6\x0c_\x89k@\xe4\xf1\x8f\x18\x9e\x11\x7f\x91\x11\xde\x10\xdd\x0fB\x16\xb2\xf8\xb0\x89\x8e\x0e\xd5\xb1\xf1\x85\xc7{\x80\xebBw\x14\x99N\x0b\xcd]A;*2\xba(4\xe7\x84tK\x88\xa1-\x1b\xc2\x93\x87\xff\xd2U\xcd\x9a\xbc\xff<\x9d\x7faZ\x11\xb2W\xf9\xd2\xbe\x1b\xab(Z\xc9\xe3\x89\xaaf#\x07<\xfe-p\x8e\xbd &\x13\xefW\x7f \x85\xa6tm\xb4f\xb6XMk\xa4\xe6\x10\x1f\xa7\x99+J\xb3\xd0\x94\xa2\x14\x9aR\xf9z\xd6x\xcc\x84h\xcc\xdc\xb1\x98\xd9\"1\xf3\xc6af\x8b\xc2\xf4\xc7`f\x8b\xc0,4\xa5\x85\xa64%\x8e\xb2\xd0\x94\xa6\xc5K\x860w\x16\x9aRE\nMi\xa1)]\xc1\x08\xea\x7f\xc6\x17\xf3\x98\x16\xf1XhJ\x85\xe4\x8cr,4\xa5\\\xc2\"\x1b\xbdq\x8d\x81Q\x8d!1\x8d\x85\xa6t\xd6\x959\x861_\x04c\xbe\xf8\xc5\xf8\xaf\xeb\x8d]\xf4E.\x1aW\xf5\xdeT\xdd\x8e\xf1\x8d\xe1\xec\xb5\x9b\xdcg\xb3\x13Wx\xd7\xc4\xdb\xd3\x03\xc5\xa3V\xa4\x1b\xc5`\xd1\x864\xd4\x1b%\x00\xfbF G\xc0Q\xbc88\x8a\xad\x13)vmp=\xef\xc3\xc7Q\xd2Pr\x14G\x95\x8d\xdf\x93psC\x9b\xc1\xc2\x0d\x89h\xbaY\x02\xc1\xcc\x0d\xa9\x18\xbbYe\x9d\xad\x1b2#\xef(\x0e\xd6n\xa0\x99\xbb!\x1b\x16\x8f\x92\x0d\x91G\xc9\x8b\xcb\xa3\x84\xa1\xf3(^\x8c\x1e%\x10\xa9_<\xeca\xf5\x06zz\x81\x85\xed\x19V`\xbc>\x86o\x08\xc7\xf1\xc5\xc3~4\x1f\x85hPNd\x1f% \xdf7\xb4\x11,\xe0\x90\x15\xf5W\x8a\xc9\x82\xfd\xa3\xa4\x8e\x11o\x1c\x80P\xe7e\x06\x07beK\xc9\xb5A!2n\x84\xea\xe2\x9f\x86\xe2\x9f.\xfe\xe9\xe2\x9f.\xfeiC\x8a\x7f\xba\xf8\xa7u)\xfe\xe9\xe2\x9f.\xfeiCQ\xf1O\x1b\x12\xee\x82-\xfei\xea\x91\xe2\x9f.\xfe\xe9\xe2\x9f\xd6\xa5\xf8\xa7\x8b\x7fZJ\xf1OC\xf1O\x17\xfft\xf1O\xfb\xc7\xc8\x97\xf0O\x13\x87\x99\x98\xfc5C\xc92\x9f\x8d0\xbbjZ\x1bJdr\x1b\x94+\x86\xca\x15C\xe5\x8a\xa1/{\xc5\x10\xcc\x9fu\x9e{\xe8kf\xdc\xff\xa1\xfc*o\xe8\x93\x1d\xf3\x9d\xf2\xf2\xf2v\"K\xce\x0d\x04\xdfO\xa4)Pn(r\xa5\xfa\\c\xf2\xe7\xea\x14\x1f\x914\x1aer\xac\xa9; \x13,$CG&\xba\xb2\xcfu?\xa8p\xc0S\xa6B\xcaB\xc7-\xa6\xd8p\xcb\x1a*\xef\x1f\xab\x8e5C\xce\x9c\xcc\x1f$\xc8\xf2\xa3\xd27X\x8c\xac\x93\xf2\xda\xb8\x0f\x0c\xfc\x16B\xff[\x05\xaf\x0bk\xa3j]V\x15\xa54\xe5\xd5\xacC+\\\x9f\x9ab`k\xc9\x9dSRg_7\xbb\xbd2XT-B\x035?\xec\xd3\x11'\xa1,u\xd5\xe4[\x9f`'j\xfb\x9bM\xb1K\x9a\xad\xe6|uM\x14\xd7TI\x9d\xb5\xd6y\x9b\\\xa1u\xb3\x97\x9a\xbf!\xe9\x83\xeb\xe7\xb0c\x16\x87\x14\xb8n&\xe7\x98\xcbe\x7f\\\xf6\xc7e\x7f\xfcE\xf7\xc7\xc4\xf2\x19\xb0\x9d]\xac\x9f\xc1\xbbW\xf1\xcb\xfa\x05T\xbc\x18e\x122n[\xe7\x85\x87{\x89\xb4(1\xc2\x00\xaf\xdf\xa8\xfdr:T\xcdO\x1d\xab\xb6|\xb6\xa8qV97i\xef\xe4\xc5\x88[\xdd\xb0\xd7=U\xd0\xd0\xb1\xaa?u\xa1v\xd5f'\xae\x96\xf7\x0eJ\xadPm\xf8\xcc\x17\xdd\xca#t\xdaM\xcd\xc7:w\xf6\x12t\xd8f\x1d\xdbO\xcdZ\xfe\x19kF~\xfb\xa9\xb1~T\xf2b\xf3\x95%M\xab\x9fP\xa6\xab\xaf\xdb\xe6v\xa8\x83\x07\x8f\x1c\xba\xdbj`?\x8d\xefQU\x18\xe4M\xb3\xdc\xc3X;\x07\xd6\xecI\xbf\xbdg\xecvh?\xb0\xa6\xa7*\xb3\x8a\x0dfu \xe8\x965\xed\xc1\xfc\xd9\xb9y\x01\xa8\x0e\xe3`Z\xf9\x9a/p\xe2e[+n\x03\xe0=\"\x90\x08\xac\xa6t\"T\xcd\x96\x87U\xf0JP\xd8\xff\xdbw7\xe7\xcf9\x8c\x82\xcf\x08\xac\xa2\xe6\xde\x88\x8bf\x10\xbb\xea\xc9q\xa9\xba\x8a\x0de\xc2\xea\x1a\xbf\xf7\xf5\xae\xa9\x86S\xc7z\xbe$\xd5\x1dBj\xbbv\xd7r\x7f\xedY\xd0|}S\xf7<\xfc\xf0\x9e1\xd1b\xde\xd4\x1e\x1b.\xe9\x15\x0fuS\x1fN\x07\xd8U=\x1c\xbbz3v\x10\xc6\xa1i\xea\xc4\xa9\x81b\x1d\xd7\x87\xa0\xdcKN\xf3d\x8aX\xd9\xef\xb5\x0d\xe5+\xbe\xde,U,V5m\xd9q:i\xe4\xca&\xcb\x0d_\xd5\"\xce\x85\xf2\xcd\xa7=\x18f?\x0f\xae^\x06cO<\xeb\x16\xc3\xc4\xd3\xce\xda%\xd1\xb6(\x86\x94E\xd8\x97|K#\xb98\x92\xcbcHU\xa3\x96H\xcb\"\x19Q\x9ec\xa1t.\x95A\x83\x9c^.\xa3\x16\xcc\xa0%\xd3\xbehZ\x96M\xe7\xc2\xe9^:\x1d\x8b\xa7g\xf9t-\xa0\x9eW}\x8bh\xcee4\xf3Bj_J\xd7.\xa6\xaeY\x9eyAu-\xa9\xa4\x19H\\V\x8b\x7f\xa6\xf8g\x8a\x7f\xe6k\xf8g\x96\xf0\xa3\xb1\xe7\\\xb3\xa7\xe5\xee\x1a\xa1\xcd\xbf\xbd}\xdf\xb3\xae\x90\x0b\xce\x12\x02\x86\x14r\xc1\x92\xbcY\x927)m%y\xb3$o\x96\xe4M(\xc9\x9bK)\xc9\x9b%y\xb3$ozkS\x927\xa1$oBI\xde,\xc9\x9b%y\xb3$o\x1aR\x927K\xf2\xa6\x94\x92\xbc %y\xb3$o\x96\xe4M\xff\x18\xf9\x12\xc9\x9b\x85\\\xb0\xf8\xa7\xc9?\x17\xfft\xf1O\x17\xfft\xf1O\x17\xff4!\xc5?]\xfc\xd3\xfe\x1dG\xf1O\x17\xff\xf4B\x8a\x7fZH\xf1O\x17\xfft\xf1OG9{\xc9\x9f\x8b\x7fZ\xff\xb1\xf8\xa7\x8b\x7f\xba\xf8\xa7M \xf5=\x16\xfft\xf1O\xfb\xc6\xc8\x97\xf0O\x17r\xc1\x92\x9cS\x92sJr\x8e\x90\xd0\xe4\x1c\x98?k\x12\xb9\xe0?.\xb2{\xe8\x94\x1bg\x8a\x8f\xfa\xfa\xcf\xcb\xf7e\x7f\x85q\xb4\x8c\xefrn\xc2_\xc7/\xda\xadO\xf89\xe0{Q\x19?\x8b\xf9T\x8cY1f\xc5\x98}AcFf\x1a\xda\xec\xc1:k\xa4jXk\x88V[ \xbe#\x8a\xb2\x19\xd6D\xc2\x84\x19r\xf1\xca\x97/X\xf7Xe\x93;QP\xe3=9\xd1\xa8d\x13\xb4U\xac\xee\x11ZP\x14f\xac\x92\x9bND\xdd\xdfBnJ-\xbe\x8d\xd6Kx\x1aR-\xbd\x94#\xeb\x0eu\xdf/yA\xc1\xb2^\x82\x9bW\xc9^%\xc3>_\xce\xc5bw\xcb5eJ\x13m'.\x80\xb1wz8V\xdd [\xa1)[\xb6I~N9q\xf5\xc3\xcb\xf8S{\x8fZ\xbf\x03\xaf\xc1 \xb24\xba\x8dY\x9d\xda\xcc\xdfZ\xbf\xcb\xe1\xad\x89\xdb\xe4|\x03i\xcd)6\xc9n\x95\\F \x9eF5\xc26=)\xe5l\x88\x8dz\x02\xbe#\xd2R=%\xe3\x91Y\x96\xd5b\xd9m\x96\x87\xd6\xc6U9\xc2#\x93\xd5v\xe9\xd6+\xc2~\x953J9\xa3\x943\xca7tF ;\x9d\xe8{\x86\xf5|(\x8a!Z\xbds \xad\xe8\x8a\xed\xc3b\nl\xd9P\xd5\xfb8E\xdf\xc2>\xc4\xe4R\x19\xbf\x91\xb2\xc6\xcf\xbdE/\xf4O\xb6\x1717 +k6.\x13F\x9d\xe6\x15f\xb9\xb8\xf0\xd5}\xd6H6eu\xa0;U\x03p\x7f4\xd0*\xa9\xb6\x99\xa9M\x16\xf6\xcdx}~\xc4^2\xb5M\x00\xfbV\x01\x82\xab\xac\xee\x0fz\xcc6\x90[\x81\xc5K\x9a\x83`\xa1\xc3\xba\xf2\xe7\xfe:\\+1n\xc13v\xc13~\x01\x88M\xab\x18\xca\xe6\x9e\x0e\xbe\xd1of\xd9\x9b\xcdO\xbf\xe2\x96O\xbbc\x00\xad\xa1\xc2a\xa7}4\xeb\xea\xb10\xe8\xb8$\xae\xf2o\xa9\xadp.!\xd7\xeaE<\x01\xab\x05i{\xc9\x9e\xb5\xd8[\xbb\xa5\x0d\xbb\xc2\xc3,W\x1f\x96\xf4`\xb4\x0dA\xff\xc5\x15\xc4%\x1d\x11\x05\x87_\xc9\xb1<\xaa\x91}+t\xae\xbb\x80\x83<\x9a\xb9\xd4\x87_\xb7!^\x88\xbeh\x83\x1c\x99\xe2\x7f\x82\x87f\xe2\x88\\E\"\x1c\xfe\x8d\xc2)\x83W\x7f\x9f5\x04\xc1&5\xb0Ks\x02\xf7\xaf^\xb0\xc6\xf2\xeb*u5\xb3\xaf\xc1\xe9\xbbB\xbb\x85\xc7\xd7\xc2\xe0\xeb\x1cO&k\xaf(r\x08\xe4\xeb\xf50\xf5>\xc5\x1e\x9a\xe4\xe2\xb5\xae\x904\xff\xae\xe5q\xd7\xe1?\x9amWU\x92B\xb3;\xaf\x86\xb3\x84\xb3\xe9R\x07\xf8\x8c\x0c\xba4w\xeeb\xb0HK;\x8d\xde5|\xb9\x94\x99\x9dN\x9d\xc1v6\xdb\x16 \xd2\xe9K\x1d\xb1r-\xc8+\x9d\xbb\x89U\x08w\xe2fYo\x0c\x97m\xde\x15g\x11\xf8\x95\xd3\xa9@\xee\xcd\xd7\xfb[\x95\n*G\xca\x10\xcf\xaa\x987\xc7\xb6\x1f\xf8\x9cy1\x0c\xd5\xe6a4-_|\xd2,LO\xc8&z\xac\xb4\x9a\xe6>Z\xc9\xa9\xfa\x8a\xae)\x17Y5=\x9b\xb6i\xd8f\xec\xd9\xc9]=\xeaKm\x84\xb2\x01v\xd5N\xc9\x8f\x9e*\x92g\xe2]\xdcO\x83\xc2\xe8\x0c\x9e\x87\xac.v\xe4\xcaJ\xaf\xab\x03\x99\xcao]V\xdd\xe9k\x19\x13\xf7\xed)\xfb\xf9\x92\xf5\xb3\xa5\xe9[\x13\xf4\x87\xf8\xd4\xfc\\I\xf9\xeet\xfc\xa8D\xfc\xe8\x14|\xde^\x1dE\xb2&\xdfG\xa7\xdd\xe3\xdc\xd4\xb4Y\x12\xeeSR\xedyZ\xbd\xde\x1a\"\x93#&\xbd\xde\x9eJ\x9f\x98D\x1f\x94>\x1f\x9e*\x9f\x90$\x9f\x90\x1eO\x18\x8c\x8cI\xf0y\xd3\xdf\xb3%\xbe\xfbS\xde\xb3%\xbb\xdb\xd2\xdcS\x12\xdc\xc9d\xf6!$\x8d=6\x81\xdd\x9a\xac\x1e\x99\xa6N$\xa8[\x17\xca0\xa0\xd9XA#\x13\xd1\xe7\xa4s\xaa\x7f\xbf\xf3\x97\x9d\x96v\x8ei\xe6\x8a:3\xe1X\xb5C'C\xc3\xdb\xae\xde\xd5\xe3\xf6\x9aw\xa4\x1c\xedJ\xa9B\xcbdn\xb7\xb7\xfc\xb0\x15\xd5\xc7\xc1\xde\x18\xfe8=\x8cnD4\xc8T!\xfd1\xfb(f\xcd\xc9H\x0e\x01\xf8 .\xdf]\xdf\xdc^\x9d\xbf>\xbf:\x7f\xfb\xf2\xfc\xf6\xe6_.\xcfo\xdf\xbf\xbd\xbe<\x7fy\xf1\xfa\xe2\xfcU\xe0\x1bW\xe7\x97o\xfe%\xf0\xd9\xff\xf1\xfe\xdd\xcdy\xe0\xb3W\xe7\xe3\xaf\xda\xc3\x02\xc6}\xbe\xb2\xeen\x06\x8b\x80\xbex\x0eo[e\xe9\xb5\x85\x14\xb9;\xe99\x86\xe1\xcej\x16+p\xc7\x8e\xfbG B\xcd\x17e,\x0eW\x9eRx\xf7\xbaK\xf9\xf7S;\xccQEQ\xa5\xe0\x87\xf16F\x99W\x8er\x8ez\x00:\x8ac4\x079\xf9\xa6y>\xcf_\xb2l\x8e\xfce.\x9c\xa2\x96\x11%\x19\xb5\xd2M\xfa\x1fzn\xd4e\xc0\xf6\x14\xc5\xaf+'o\xaf\xcfon.\xde\xfe\xc5b<\xf4\xa7\xce\xff\xf9\xfc\xea_\xde\xbd=w<\xf2\xfa\xdd\x9b7\xef\xfe\xe7\xf9\xd5\xb5\xe3\x99_\xdf\xdf\xbc\x7f\xf1\xc6\xf5\xc0\xf9\xdb\x9b\x8bwog\x1d\x93\xe1\xf3\xd7\xdan\xec\x1cm\x16\x06N\xe9\\\xda\xc8\xd9:\xe49\x9c\x7fd\xddc\xdb\xb0 \xa2\xe7!\xb4C\xab\x1a6\xfdK\xb9\xba\xef9\xbck\xf6\x8f\"\xd6\x9buSD!\xee/\x12K\xc1\x0f \x8aP\xb4\x1eN\xc3\x89\xa7\x03\xc8B\x13\x8b\x11\x9fQ\x14td\xedq\xcf\xa4\x0b\x80\x07^\x8b\xd9/t\xd1\xc5\x89\x12\xa6d\xd6m5\xf8\xd2\xc7\xbc\xc9\xac/e\"\xeb\xf8\x04\xb1\x01\xe3A+l[\x0fl\x9b\xa5\xbf#\xb95aiNc\xf85'\x05\x06L\x15\x96\x84\xd8\x0f\x01\xe8\xd75B3\xe3\xd3\xeb\xb3\x0d\x8fOO\xf6\xfety\x869P3;n&\xab\x17\x9f~\x97\x8e\x9e\xd9\x93\x02\xa3;\xcd\x87\xa29p4g\xd9\xe6\x84\x0d\xc1\xd2(4me1\x0eD\xcd\x86\xa9\x91\xb5]\x81\xaaE\x1f8\xed\xd8\x9a\xdb\xe7\xe8\xf0:z\xfd\x8e~\xcf\xa3\xc7\xf7\xe8\xddU\xa3x\xf7\xd6(~\x8f\\\x94O\xce\xa1\xcdr\xdf\xeb,\x0e?\xe4\xef\xa1\xedV\x8f\xa4\x13\x05\x08ly>$ \x13\x160\xa9\x89C\xe1\\8\\\x99\xa3\x8a\xe4\x1f\xa7e\x8e\xda\xfe\x9c\xd8\xf2ow\x8e\xc6 v6\xcc\xae\xccNE\xf2\x8eP\xcb\xad\xd5\xb3\xfc\x8eg\xa7\xf5\xce7\x14\x07x\x16\xd8\xf2\x90&\xc5\xc0~.\x8bC\x03\x82A\x90\xe0\xbaV\xc5\xc1\x82\xf3a%\x1a\x18\x9cT\xac\x82\x06)p\xd0eW\x9c\x14i\xae\xf3K\"HH\xc3\x84!\x05;\xa1B\x0fX\x98|\xf6L\x86\x0c}\xa0a\xf4\xb7\xb2\xd8~\xb7\xdd\xe7\xaf\xba\x86o\x08\x80\x180\x9f\xec b\x00D\xb6\xea=;\x90\xb8\x1eJ\\\x0d&&\xc1\x89>\x9f\xb7\x14o\x7f\xad\x83\x14\xbf$\xa8\xf8%a\xc5/\x06,:\xa1\xc5\x80\xb9\x11\xb0o0\xdcq>\x80\xd1\x0d1f\xad\x94u\xd5\xcf\x085\xae\x00\x1b\xd7\xc2\x8d\x0b\x0fy\"\xe0\xe8\xea\x93x\x14\xd2Pe\xa0\x92n\\r\xaaU(2\xe9\x1c\x1e\xb6+J\xc3P=\xeaY\x0bB\x19\x8eQ\x06\xa2\x94\x818\xe5j\xa4\xd2o\xb73\xa1\x95O\x84W~I\xc4\xf2\x8bb\x96_\x00\xb5t\xe2\x96A\x9bM\x1a;\x9c\xe6l\x08z\xe9\xc3/s\xd4c=\x8aI\xe2\x98!\xfb{;\x96\xb9\xb0\xd5qhf\xc9\xb1-9\xb6%\xc7\xf6k\xe4\xd8.Y\x8d)\xc8?$\xa2@}O\xe8\x0b\xe65\x96l\xfe%\xce\xa0\xc4\x19\x84tZ\x893\xa0\xd5\x948\x03\xdb\x1f\x03\x0e\xd6\xe0\x1b|\xb3\xf8\x0e\xd8\x90\x1d)(\x18\xe6\x7fJ\x0c\xb3\xc4\x19\x98\xf2M\x8f\xd32Gm\x7fNl\xf9\xb7;GK\x9c\x81*\xdf\xec\x08-q\x06%\xce`\x965\xad*q\x06\xba\xae\xc9\x16\x978\x83\x12g\x80\x0f\xfb\xe6S\x893\x08i\x93\x0f\xafB\xf1\xf6W\x893p\x95U\xe2\x0c\xf2V\xaa\xc4\x19\x98\xbaJ\x9cA\x893P\xa4\xc4\x19\xd8\xcb*q\x06%\xce`YT\x893(q\x06%\xce@Q\xf6\xbb\x8c3\xa00\xffp&\xef\xc5\xeb\xb2\xb1NB\x03\xbe\xf9\xb9\xc6%\x16\x87\xa91<\xd5\xad\x8d\x7fC\xe3\xd9\xc6\xf86/\xce-\x8bs\xa3\x12\xb8=\xa1\x07g\xe2V$\xeb\x06\xe4\xe9\xb7\x1d_`\xb3\xf1\x84[\x0cu\xdb.F\xee\xf2\\rl\xfb\xbe\x1e_\xeb\x96;{~c\x898\xa9l\xaa\x86_\xd2IL \x81\x80\xa8\xb3\xc1\x19i\xa3\x01\x04\xa4y\xb7\x98vy\x80]\xef\xd76q\xb5\x85\xa7\xfe\x0bVBq\xa1/\x00-\xb2\n)\x80U$@\xa5\x7f\xde\xf7\xd2\x03\xfe\xcd~Z\x03\x94\xf9\x1a\x9fVCG\x16\xb8\x81\xeb\xd3\xc6\x00\x1a\xf3\x1e\x8d\x84)\\\xc5\x85\xc2\x10\x11\xb0\x831pz\xd6\xbdh\xfaOr\xf3\x1e2~\xa8\x08\xb9\x88\x0f\xb8\xd8\xf7]O!q[K\xdc\x99\x0e?(W\xe2/u\x90e,\xf1#\xcd\x95\xf8eu\xfc\xb3T\x15\xe5\xcd\xf8Z7\x0e\xc9J\xcf\x91\xc3\xc7\x93\xea\xe7!\x11\x95,u\xc2\x1dSK\xd5\x852\x9c`\xbdh(\xf1\xda\xa3\xa9Tm7\xa7\xbcE\\ON~Zp\xc2\xbc\xe3+t4\x84\xb5?!\xe0\xdap\x80\x17\xe3\xf6\xe1\xe7\x8e\xf5\xed\xa9\xdb\x88kL\xf9T=\xf1\xf8\xec\xfd#\xd4\xdb\xf1\xd8s_\x9b\xb7|\x13\xea\xe6\x1b>)`\xc7r\xfd8bF\xa2\x0dp8\xcdn\xc1q\x93\xb7gU?P\xda\xc6s\xea\xf7?\x7f?\x9b\x823n\xe7\xf6U?@\xcfv\x07\xe5V\xc1\xf7Wo\xfe\xd0\xc3\xb1\x1a\x1e\xb8zB\xd9\xb4\x86P%\x0d\xc4\xad\xaf\xbc\xa7\x84z\xde'?T\xfcRr\xe2\xf5\xbf\x8e\x05[\xafU\xfc\xeb\x8fXo\xaep^\x07\xc6\xc6\x13\xba6U\xd36\xf5\x86\x9fs\xa9\x9b\xce\x01~`g\xbb\xb3gc\xb7qO\xd3\xf7g\xdf\x8fs\xa2i\x07\xa86\x1bv\x1c\xd8\xf6G\xfa\xca\xff\x8b\x06\x8ecG\xd6\x1b\xf6\x0c\x066\x1a\xc3S\x7f\xaa\xc6f\x1f;\xb6i\x0f\xc7z?\xd6K@\xc5wuSu\x8fP\x89ey)c\x8f\x88#\xec\xf0\xc0H\x94\x8f}\x1e\x0d>\xd4|\"\x9fz&o\xc2\x1d?\xbd\x08\xa5\x7f\xd1<\x9e\xc1/\xed'\xf6\x91ux1\xee\xfb\xab7\x14\xb8\x88v@\\\xd0K\x15\xd6o\x1e\xd8\x81\xc1_\x1f\x86\xe1\xf8\xd7g\xf8\xdf\xfe\xaf\xcf\xa0\xed\xa0i\xc5_\x9f\xf1\x115\xae&r\x97\x8e\xc7qB\xdd\xe98\x9e\xe2\xc8\xdbw\xf9\x1c\xf8\xc8\xaf\x01\xae\x068T\xc7\x1e\x87\xc7X\xf3\xb1\xa5\xd2\x8f\xc7\x1d\x925.\xb9U/\xbc\x16\xfds\xf2\xcb\xfc\x1d\\\xdc\xcf\xf5\x1c?\xa7\xbcOyj\x8a\xb0{\xa7\x03\xdb\x92\x97\x83\xff\x1d\xbch\xe0\x97\x9b\x9bK\xf8\xcb\xf9\x0d\xb4\xcdt\xe0\xe1\xd3\x0d\xaf\x13\xae\xccKFo\x1e\x8f\xec_\xff\xf7\xbf\x12\nAzW\x1b9\x12\xd0n\xf2>=v\xed\xf6\xb4\x19\xf7\x8b\xc0\xba\xae\xed\xa8\x9b\xa3\xff\x0e^\x1c\x8f\xfbzS\x89>\xe8\xd88\x96\xdaO\xb8\xfb\xdeT\x9bq.\xb7\xed\x87\xd3qrb\xe2J\xdc\x9a7\xff\x83\xc5\x1c\x01^\xa9\xdcv|;3>tP\xc6\xf2\x16\x07s%\x1b0\xfe\xfbc[o\xa1\"\xae\xfc\x07~\x02\x19\xab\xc3\xa7k\xc7\xee\xdb\x8e=\x93\xaf\x8e\x1a\xab\xa1\xbe\xab\xf7\xf5\xf0\x08\x0dc[\xe9.\xe6f\xa5\xfbh \xdch\x9b\xd1|5;\xc6\x1f\xe7\xb3\xe6\x0c~x\xdf3\xf8\xc8\xba\x1e\x9dM\x83\xbc_\x1a\xc7O\xd5T;\xba\xadw\x1d\xab>p\xff\x12\xaa<\xfb\x91\x1a o\xdb\x81=\xc7\xb3\xc6\xfd\xa9\xd9\xe0H\x1fk-\xac\xc4\xe6\xd4u\x1cUP\xbd\xf1\x8d\xa5\x83[\x0eB\x98nx\x90\xd6\xfe\xeet?\x1e\xf0X\xd5\xb3g\xfc\xee\xdez\x90\x05\xf1\x0d\x1b\xf7\x0bO\xf3\xe3\x8e\xed\xea\xa6\xa1\xc3\x19\xc6%\x964\xce\xe6\x15\xb6\xb4}\xbb\xe6\xb3\xa7G\x08`\x9c\x9e\x8dn\x0f\xe0\x07\x91\x0e\x87\x18\nN\xb7\x1f\xe1P\xef\x1e(+pGN\x7f\xde,\x1e\xbeP\x1f\x8e{v\x98\xae\x1b\x16~\xd8\x0d\xf4\xecP5C\xbd\xe9\xf5iA\xec\x15\xc0\xb7\xc4[\xb1)\x08Z\xff\x7f\x1d\xa7\xff\x1d\x83j,\xbc\xde*\x0b\xb8\xb1Z\xcb3\xe0]\xfb\x91\\\xfa\xa7\x00\x1b\xfeE\x16O\xb8\xeb\x81\x97\x8b\xcfH`\x03UwW\x0f\xfcnxG}\x84%\xd5\x94U\xfb\xb6\xd9\x89\xbb\xc4\xf5\xcf3\xda;n\x96\xb1>w\xe6\x96F-O\xeeN\x8c\xc1t\xa9_`/\xacq\x0f\xfd\xe9xl;\xbe\xa2\x1d\xab\xcd\x87\x9f\xf1^\xf9q\x1d\xc3o\xdb\xd33\x89Z\xca\xdb{8\x0dhN\xe44\xedGC\xa6\\\x86\xce\x1d@\xdc]1\xddS\x8f\x8dxa\xd8/\xfc$z\x19\xf2\xa2\xe9?>\x87\xcb\xb1\x9e\xe3\xfc\x14U\xae\xa6\x85\xaan\xe0\xe5\x7f\xfd\xaf\xe4\xa2\xf2\xbam\xe1\xbem\xe1\x1f\xe0\xec\xec\x8c\x82\x97\xc6\x86W\xcd#\xf5\xa7\xaay<\x1b\x0b}\xdd\xb5\x87\x1f\xee\xdb\xf6G\xea\xa1\xb33j\xe5\xa8\xef\xe1\x87\xf1\xf5\xf7\xbc\xaa7\xed\x0f\xffe|\xffG\xcbu\xd7\xb4\x0e\xe3\x12r\xd9\x17\x7f\xf2\xf4\xc5\x7f\xaf>VI\x9d\x01\xff\xc0\xf75\xa3\xe6\xc8v\xd7\xfd\x0f\xaf\xdb\xf6l\xb3\xaf\xfa\xde\xdal\xac\xca\xf88\xb6By\x85*\xd1\xda\x1f\x7f\xef\xe9\x8f\xcb\xc7\xe1azu~\xfd\xf2\xea\xe2\xf2\xe6\xdd\xd5\x8f\xa6]\x05Q\x08\x8e#[1X\x90\xa5w\xfe\xff\x9e\xde\xf9KK\x06\xb8\x8d=\xf3\xfc\x1f\xe0\xbf\x1c\xef\xce^\xb7\xed\xff{vv\xa6\xdf\x8e\xce\xa5j\x1e\x9f\x8d\x1b\xa8\xf1\xd9\xaay<\xde\x9d\xbde\x9f\xac\xf5\xac\xef\xf9\xb3\xff\xbf\x7f\x80\xa6\xde\xdb\xee~\xa7;\xcd\xb8\x9c\xdd\xf5\xacVy\xf2UQ\x17\xac\xf7\xd9\xfb\xe6Pu\xfdC\xb5\xbfiq\xc8\xa7TT\xfb\xf5\x86\xbbn6\x1f&\x1b(\xb7\xc6p\xf78oA\xa4\xa5F\x9c\xeeQ\xc2\xaf\xe3b\xad+\xfc\x03\xb1\xa1\xf8y<\xfd\x9d\xf1?\x8c\x1b\xb1?\x8c;\xf6i\xe5\x18W\x95\xf1\xfb\x9bv\x1dG\x84^\xc0d\xac\x9b\xfd\xa3<\xb3\x18\xc7\xcbi\xd3\x07\xd5\xfd\xc0pW\xc2O\xb6\x7f\xf8\xf9\x0f\xbaBqp\x92\x95\xc1\x93\x12\x13#\xf4\xfb\xfb\xb6=\xbb\xab:\xde\x8c\xcf??\x9e\xfd\x9f\xef\xb1\x17p\xcfO\x1dbx\xb1\xdf\x8fO\x8eK\x86\xf6\xc7\xff~\xfd\xee\xad\xf1\xe3\xf8\x11\xc6?\xcc\xc7h\xdc\xf2\xb4\xe3d\x14\xeb;\x1e\x17N=\x93\xe1\x01\xbb\xd3\xbe\xeatM\xa6\x02\xc4=\xe6u\xf9\xd9\x1c\x81!&\xda3\xb1\xdc\x1b\x87oe\xad\xbc\xe7\xad\xfd\xeb\xff3\xb6\xf7\xaf\xe2\xbc\xb8p\xff\xc9\xde;\x93s\xfb9\xb9\xa7\xad6\x1f\xc6\xa9=\x9f\x93\xee\xeb=\xa3\x0c\xaa4\x02\x97\xac\xeb\xdb\xc62\xca\x85\xcb\xe3\xbe\xee\xfa\xe1\x96w\xbb-NC>\xca\x83\xc4\xc4\x93\x7f\n2\xe4\xa3\xd0\xa5\x7f\xcf{\xe3\xfb\xe7\xf0=5\xe4\x97M<\xc3v|\xff\x8c\xd6\xc4[\xf0\xb6:\x8c\xda\xfeo\xac\xea?Z\x1e\x1d[\xa0=\x19\xd2\x8c\x8b{\xb13_~{\xfcnu\x0f\x9f\xd8~\xff\xd3\x87\xa6\xfd\xd4\xf0\xc9\xf8\xc0=\xc1\x9bS?\xb4\x071f\x97\xfa\x96\x03\xed\x19\xee\x0b\xb5\xd17\x87T\x89B\xc7\x01\xd5\xec\x0c\xc7\x0c\x1f\\z\x01\x7f\xe5\x03^\x8e\xb5\x87v\xbf\xc5\x81\xa6\xd4\x89;y\xc4\x18\x05\xe1V\x11CT\xd7\xc6\x8b\x98\xc6&\xfc0Nq\xd9\x05\xc6\xa9]\xba\x96\xfe\xf5\x7f\xff\xeb\x8f\xe40N\x1b\x0f\xcbBlC\x827\x7fT\xf6\xc7\xb3?\xfd\xf1O\xfd\xf7\xe4G\x9e\xff\x9d~\xaf\xa1t\xc6~\xa7=%\x9d\xf2\x1a\x94Z\x0d\x15\xe2\xa8Jt\xe1R\x87x\xff?\x161O\xba\x8b?\x84We\xaa\xc1\xd5\xe5K\xa1K\x0fq\xb2c =\x82\x15\xab!\x85\xa3\x82g\x91\xaf\xd0\xaf\xc1\x97\x03\x14\xc6N\x9a<\xf8\xfd\x84\xc0T\x1d\xc3\xc3\xa8\xa2\xa6c\xbb\xba\x1fX\xc7\xb6\xb7&T\xa2\x94\"\x80\x1d\x05R\xbe\x9a\xde\x94\x1d\xaa\x01^D\x03W\xb9\xe6\x0d P\xca@\x02\x82\xd3_\x97\xc0\xa0\xb7\x9aV\x88p\x94\xfb\x8e\xb1[\x93\xc1\xc4\xda)\x16\xec\xef\xdb\xe8\x8a\xb5\x18\xa9\x14\n+\x9d\x8a\xb0\xa2=\xe0D|\x002a\xa8Rt,u*$\x0d\xc6Y\x87\xb1\x12\nb\xc1VB\xd5\x12~\x05p\xc7\x85hf\x8e\xc4d\x95\x91+\xcd5a\xad\xbe\xfb\xce\xac\x03\x0ei\xa7!\xd7\xeckx\xf8\xeaR\x01\x19\xb8\xea\xb0\xea\xab\xed\xf9\xa4K7\xe9Aq\x1f\xbf\x11\x9a,\x1f\xa4lM\xd3\xcbV\xb7\x08h\xd9\xce\x8e\x95\x81\xb3+\x00b\xb68\x8e\xad\x06\xdc\x7f\xe9\xb1-\xf1\xdei\xa5B\xecTv\xc0\xd9\x079\xe7\x06\x9d3\xc3\xce\x1e\xe09\x19z\xce\x0b>\x87\xc0\xcf \x00t^\x08:\x08\x84\xce\x0bC\x07\x00\xd1\xd9\xa1h\x0f\x18\x1d\x07G\x93\x8a\x9c\x10u\x16\x90:\x10\xa6&\xdf\\\x05]'\x83\xd7\xb9\xe1k;\x80\x9d\x19\xc2~\n\x10;3\x8c\x1d\ndg\x86\xb2\xdd`vv8\xdb\x0eh\xaf\x80\xb4\xe3AmR\x19\x07\xba-\xb0v\x12\xb0m\x85\xb6\xbd[\n'\xbc\x1d\xb6\xe3\xc8\x07q\xbbAn\x7fm\xb2\x02\xddn\xa8;\x1b\xd8\x9d\nw\x1b\xea\xf8\x8e\x86\xdc<\xe4\x85\xbcm\xa0w:\xec\x1d\x80\xf5:\xa1\xef@\xf0\xdb\x8a\x81\xad\x04\xc0\xedz\x08\xac \x19\x06_\xd39!P\xb8\xbf\x17\x82\xe0\xf0\xd5\x80\xb8\xb3w\x12@\xf1\x00X\xdc\x07\x8c\xfb\xa1qg\xa7\xad\x81\xc7\xc3\x00r\x12\"O\x06\xc9\x83a\xf2\xb5@y Tn\xefD\x1a.w<\x1f\x02\x99\xe7\x00\xcd\x9dU6~O\x82\xce\x0dm\x04\x94\x9e\x15L\xb7\xc1\xe9\x89\x80\xbaYe\x13`\xcf\x0f\xb1{@v\x0b\xcc\x9e\x13h\xcf\x0c\xb5?\x05\xd8\xbe\x06n\x0f\x04\xdcWA\xee\xe1\xa0\xbb\x05v\xb7\x01\xad\xe1P\xab\x1fz_\x05\xbe\x07\xc3\xefd\x83rC\xf0yAx\x0b\x0c\x9f\x1b\x88\xcf\x0d\xc5\xa7\x8f\x91 8>\x0c\x90\xd7W\xb6<\xec\x9e\x060\x9f\x0e\xcd\x17\x06\xa0\xc2\x00T\x18\x80\xbe\x06\x03\x90\x05D\x0d\x82Ou\xe0te<\x8c\x1e!\x11\x01\xa1:\xa2HV\x18\x8f\xaf\x10\x1f\xc3iNultn\x8f\xa2\xf1\x89\x12]eI\x945\xef\x1f\xdanx\xa8\x9a\xed\xed\xa6\xdd\x92\xc9\xae\xf6\x18.q\x0f\xd0\xa4\x02F\x15\x14\x15\x03Q\xae\xe4\xdf\xb0\xe6\xd8\xda\x8b\xc5\xc0\x08\xbe\xdf\x98a/\xa1\x8fm\xc7\xf9\xdb\xc0\xa9G\xf2\x01\xaap\xca\xc0\x99#\xd4\xc1\xde\xe1\xeeQ\x01\xf6.\xdczS\x9c\x03\xd8g\xa3m\x8a\xac\x89j0\x1a\x11\x1a\xd9\xa0\xbf\x18\x13\xe3`L\xd0\xdfS\xb8C\xdc\x84~\xe2\xf0\x02\xd70tO\xed\x90\x9d`\xca\xf4vN\xf0\x90\xc2S'\xb9m\x1f\x93q\xa2\xd3S]\x9b\xece\xb7[v\xbbe\xb7\xfb-\xecv\xadK\\\xca\x02\xdb\xfbW\xd8\xab\xc5v5`%\xcd\xc5\xe5\x95\x1a\xb4\xf7\x044]\xe1\xc1y\xd9x\xba\xca\x9a/\xd6\xdc\x18z\x1a\x1b5\x0dm\xbb!$6+\x9d\x8e\x86\xa2\xa2!g\x00x\x91\xffu\xf43\xcbwc\x99g\xa6\xf6\xa1B\xdd\xa8'\xf2\xcb\xe8\x01\x18\xa4=:\xb6\xdd\xc0\xad\xd1Z\xe33T\xcd\xb6\xea\xf8\xc4\xef\x9f<\xc4\xe9I\xa3\x87\xc6\xfa\xab\xd7\x01i\xdd\xa6\xbeGV\xc2\x15\xbes3\xfegY\x94uL\xaeVN\xa4\xe7*\xb7s\x9d\x7f\x1eX3\xee\xfd\x952\xb4F\xcb#\xfa\xa6\x1a\x0f\xa9\xb5\x99HT\x1d\x8f{\x8e\xb4\xaa!.t\xe9\xd7b@\\\xa1j\xdbFW<%k\xc0\xe7\x1bN\x8b\x85\xb6c\xbd\xf90N\x92F\x03o\x11\x1e\xe8\xda\x03l\xeb{~\x9d\xdd0}/\xc5\x90\x125|S\xe3E\xfa3n!F.\xaa\xc3\xd5\xaea\x9ffu\xbc^cE\xc66\xd4\xea \x93\xf9c\xcaOm\xc3\x16DM\xd4T=\xb4\xdb\xd3^\xccX6\x1a\x04r\"\xf2\x10\x8b\xaf@\x98g\x9d\xd0`\x99\xd4@Ml\xb0On\xf0\xb0\xf6\x98\x93\x1c<\x13\x1d<\x93\x1d\x12&<\xd8&=\xb8\xe7&\x84O~p\x1b\x00\x08.\xc8\xc2\x1a\x90`\x0cH}\xf5@\x1b\x04p\xd6$\xcd0\x18\xea\xee\x98\xd58@\xb0\x81\x00G\x8ds\x1a\n\xa0\x8d\x05\xa8\x06\x03\xd6\x1b\x8d\xe9\x05\xc2V\xd8\xa3\xb80vK\x94A\x87k-\x8d\x10~\xb1\xd5F\x08\xbb+\xce\x08}\xad\xac\x84\x1e\xc3\xaft\xce\xce'JD\x080@\x84\xe9\xb1\xf6A\x90\xb9\xb1\x1a\x1a\x9fZc\x82$\x98\x15s\x8fA\x18\x14Q\xae\xd5^\xc8+\xf5q\xb8bh\xe6\xd4Xub,\xc7\xafob\x88\xf2\xc2'\xc6\xfa\xe5\xf9\x8b\xec\x95\xbfr:\x80e&\x95=<\xad\xfc\xeb\xee\xe1\xe3\xe6X\x89\xe5/\xb1\xfc%\x96\xffk\xc4\xf2S\xabO\xd8\xba\x16\xba\xe3\x1b\xff?b]\x1b_\x8b2\x05_a\xc7\xc7D}gpj\xd3\xb1\xa0\xabV\x13k\x83\xc5*\xcf\x88\xfd\xc0m\xbdM?n\xaf]Fm\x8b\xa8X\xc7\xc9\x0eR\x10\x10\x98\xe7D`O\x89\x02\x95\xd5\xedW\x19\xfb\xc7o(_`kFG\x8d?\xb0\xb5w+,o\xe4\x96J\x94G\x87\xaa\xdb1\x9dq\xde\xe6\xbd\xb0\xfb.\x86r\xb5\xad!\xd9R#\xc0\xc70<\xc4\xa7H@\xc64 \xf0\xa6J@l\xba\x04\xa4\xa4LP=\xe6g\x15\x8eN\x9d ty\x19\x85SR(\x08u\xe5j\xdb\xb4\xb4\nHK\xad\xa0\xa7(Y\xc9l \x17\x90=\xe9\x02r&^@P\xf2\x05\xe4L\xc0\x80r\xb5-ULd\xe2\x06\x94\xabm\xe3\x12;4e\xe5j\xdbr\xb5m\x80\x8er\xb5\xedR\xca\xd5\xb6\xe5j\xdb\xc0g}i'\x90\x9cz\x02\xe5j\xdb!09\x052'\xa8\x80\x8fu\xb7\\m\xebO\\\x81\x90\xe4\x15\x08O`\x81\xc0$\x16(W\xdb\x06%\xb8@j\x92\x8b\xa6\xab\\mK(\x0b`\xd2].\x1d\x12\x0c\xe5\x1eS\xabG\x9b;\x8a\xeb\xb6\xb9\xddVC\xa8cX\x9e\x91\xc6W~\x1a\xea\x03\x05\xda\xc2M}\xe0K\xb6\xe1\xc4\xffT\xf5\x86\xff~B7\xf9\x13\x96\x88#\xbe?\xaf7j\x1b\x96(\x8b\n\x85\xf8A\x16^T8\xc6\x12\x13<\xc0\xdf\xfb\x9d\x06\x0f\x84\x802\xf6\x18\x82\x0c\xb52\x86\xb2\x03\x9e\xb1\x034\x16\x88\xc6\x0d\xd2\xc4E;\xac\x00j,PMH|B\x14\\c\x03lB\n\xf4\x8364l\xe3\x00n\xdca\xa7C\xb9,\xb2\\\x16Y.\x8b\x8c\x01v\x02\xa0\x9d\xec\xe0N\xb9,\x12e\x15\x18\x94\x0c\x07\xe5\x06\x84\xcae\x91\xaa\x84AC\x99\xc1\xa1rYd\xb9,\xd2\x03\x1a\x95\xcb\"\xd7\x03H\x86\xba\xa1\\\x16\x19\x06'\xf9\xafI\x0c\x83\x94\xcae\x91\\VBL\xe5\xb2H\x94\x10\xc8\xa9\\\x16\x89R.\x8b\xd4\x7f\xcc\x08O\x95\xcb\"\xb3BW\x99\xc1\xab\xa7\x80\xaf\xd6\x00X\x81\x10\xd6*\x10+\x1c\xc6*\x97E\xc6\x80Zya\xadrYd\xfe\xcb\"Ca.'\xd0\x15\x04J\xd0`W\x1c\xdc\x15\x0fx\x95L\xbe\x92\xc9W2\xf9\xbeb&\xdf\x02\n\x0e\x03\x99\xbd\x99|W\n\xff\x821\x95\xbf\x1a\x8d\x9c5;<#\x11\xa4'\x0b\\\xcb\xff&\xdb\xe8\xcd\xf9&\xb3\xbd]\xaa\x16\x937-\xb7[\xe6r/\x0c\x8d:\xaab\xf2\xb9\xa9\x01t\x9c\xd29\xbf\x9d\x01\xe4\x8b\x10\xc8V\xfab}$c\x00\x86\xf0\xc8\x0b\x13\xf1_7\x9a\x03Q~\x03\xdfw\x8d\xc8\xd5\x98\xbe\x89\xe6\xbb\xd4\xbb\x11|\x1d\xbb_\xb1\xd9\x18\xcaMS\xe9(|\xb9i*\x0ca\xe7\xed-7MM\xae\x8b\xa8\xf4\xc8D\x8c<\x08\x1d\x0fG\xc2\x130\xf0\x04\xf4\x9b0\x18\x191\xee\xbc\xe8v6\\\xdb\x8fhg\xc3\xb2\xcbMS\xe5\xa6\xa9\x15\xa8r\xb9iJt\xb4\xaa1\x05!\x0e\xb9|\xa9\xdc4\xa5H\xb9i\xaa\xdc4\xb5\xe2R'\xff3>\xb45\x0dg-7M \xc9\x89\x89\x96\x9b\xa6\xb8\x84\xe1\x9d^\xa43\x10\xe3\x0cA7\xcbMS\xb3\xae$\xb4\xb2\xdc4\x15x\xd3T\x08\xe6hA\x1b\xc9\x1d\xbd\x1da\\\x8b-\xc6\xa1\x8a\xa6?y\xc9\x00\x1e\xecW.\xc0@>``*+\x8d\x8d}f_\x17\xea\x14\x0ev\x1f\xf3\xba\x18\x17\xe3\xf9g\xff8eC\xbe\xac\xbb\xcdi_\x0du\xb3[\x9d\x11\xb9\x99\xdf\xbdE\xb5\x8e\x8e\xd7;\xc2V\xba\x1d\x84\x1b\x7fE NyMh\xbb\xba|)\xfbAG\xe6\xb4\x06\xdf\xb4C\xb5_\xddT\x0e\xd1\x067\xd2,(\xa4U\xfc\x05\x12\\\x1c\xda\x0f\xac\xb9\xaf6C\xdb\x8d\x0d\xb9cC\xb5\xfa\xc2\x98-k\xda\xc3\xedd\xc8\xee\x991\xe1\x82\xf0\x94\xe0LV^\x9e~t\xb0\xba@\xaaC{j,\x19\x85\xc6\xe3\xae`\x85\x97m\xdd\xa0{\x94\x8d++\xef9\xb1\x8f\xc2*\x89h\x0b>\x85\xabF\x14\xac\x9d\xb8\xde\xbe\xbb9\xc7\xeb\x91\xf0\xcfb\xabUsg\xc7E3\x08\xd3=9\x84\x16\xeb\xe8\xf4\xf1f\xe9\xeb]S\x0d\xa7\x8e\xf5\x1c/\xaf;\xdc\x9c\xef\xda]\xcbW\xb2\x10\xaf\xcb\xab\xb1\xf2/\xc5\xe7{\xcd\xd8\xd4H\xbe\xa5fL\xf8\x167\x0f\xe3*&\xfd\x9e\xd3\xc2\xc5\xcd\x8a\xa2\xada\x9f\xbe[\xf4h\xd3\x1e\x10%\x18U\xd5=l\xbb\xeaS\x83\xe6D5\xd80\x8c\x16\xa9;=B\xb5\xe1\xc1\x0b\xcf\xf4k \xeeN]\xc3\xb6\xd8\"\xfaC\x89\x1b\x10\xd4\xfa\xcf\xb7+LsB\x1d\xf3\xe2\x12\x86\xe9+]\xd7\xcd\x86=\x87W|v\xc0\xffu\xf6\xdf\xce\xfe\x9bg\xb2\xe4\xbc\xd4e\xd1\xaa\xa3\xb31b\xd5\x90\xd5\x97\x1a\xc8\xa9DO$\xd7\xb4\x05\xcb\xd4\x057S\xed\xea\x0c]r*\x83k:\x83uJ{^\xf3e\xb4DOoCS\xca\x1c7\x94\x899o\xfc\x1e>\xf1\xc1\xdb\xf8d\x03\xa0\xe9\xabt#\x00y\x0d\x01\xb8\x8c\xc1\xaa\x8bS\xe6%\xd2\xb8<\xe5,d\xde\xcb{\xdcx\x0f\xae\x9f\xff\xbcO\xe2\xa2\x0f\x941N\xdbBG\xfd\x16\xdfw\xea\x94~\xe8N\x9bqD\xc9\x9e\x11\x8a\x96:0\x9e\x8bG\xdc\x9d}\xf7\xff\x05\x00\x00\xff\xffPK\x07\x08-\x0e\x16\x82&\xcc\x00\x00\x1e\xac\x0c\x00PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\x00\x00!(-\x0e\x16\x82&\xcc\x00\x00\x1e\xac\x0c\x00\x0c\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x00\x00\x00\x00swagger.yamlUT\x05\x00\x01\x80Cm8PK\x05\x06\x00\x00\x00\x00\x01\x00\x01\x00C\x00\x00\x00i\xcc\x00\x00\x00\x00" fs.Register(data) } diff --git a/client/docs/swagger-ui/swagger.yaml b/client/docs/swagger-ui/swagger.yaml index c78bc502fb..b658aec771 100644 --- a/client/docs/swagger-ui/swagger.yaml +++ b/client/docs/swagger-ui/swagger.yaml @@ -14797,6 +14797,125 @@ paths: format: uint64 tags: - Query + /desmos/tokenfactory/v1beta1/params: + get: + summary: >- + Params defines a gRPC query method that returns the tokenfactory + module's + + parameters. + operationId: Params + responses: + '200': + description: A successful response. + schema: + type: object + properties: + params: + description: params defines the parameters of the module. + type: object + properties: + denom_creation_fee: + type: array + items: + type: object + properties: + denom: + type: string + amount: + type: string + description: >- + Coin defines a token with a denomination and an amount. + + + NOTE: The amount field is an Int which implements the + custom method + + signatures required by gogoproto. + description: >- + DenomCreationFee defines the fee to be charged on the + creation of a new + + denom. The fee is drawn from the subspace treasruy + account, and + + burned. + description: >- + QueryParamsResponse is the response type for the Query/Params RPC + method. + default: + description: An unexpected error response. + schema: + type: object + properties: + error: + type: string + code: + type: integer + format: int32 + message: + type: string + details: + type: array + items: + type: object + properties: + type_url: + type: string + value: + type: string + format: byte + tags: + - Query + /desmos/tokenfactory/v1beta1/subspaces/{subspace_id}/denoms: + get: + summary: |- + SubspaceDenoms defines a gRPC query method for fetching all + denominations created by a specific subspace. + operationId: SubspaceDenoms + responses: + '200': + description: A successful response. + schema: + type: object + properties: + denoms: + type: array + items: + type: string + description: |- + QuerySubspaceDenomsResponse defines the response structure for the + SubspaceDenoms gRPC query. + default: + description: An unexpected error response. + schema: + type: object + properties: + error: + type: string + code: + type: integer + format: int32 + message: + type: string + details: + type: array + items: + type: object + properties: + type_url: + type: string + value: + type: string + format: byte + parameters: + - name: subspace_id + in: path + required: true + type: string + format: uint64 + tags: + - Query definitions: cosmos.base.query.v1beta1.PageRequest: type: object @@ -23482,3 +23601,73 @@ definitions: total_supply: type: string title: QueryTotalResponse is the response type for the Query/Total RPC method + desmos.tokenfactory.v1beta1.Params: + type: object + properties: + denom_creation_fee: + type: array + items: + type: object + properties: + denom: + type: string + amount: + type: string + description: |- + Coin defines a token with a denomination and an amount. + + NOTE: The amount field is an Int which implements the custom method + signatures required by gogoproto. + description: >- + DenomCreationFee defines the fee to be charged on the creation of a + new + + denom. The fee is drawn from the subspace treasruy account, and + + burned. + description: |- + Params defines the parameters for the tokenfactory module. + + Since: Desmos 6.0.0 + desmos.tokenfactory.v1beta1.QueryParamsResponse: + type: object + properties: + params: + description: params defines the parameters of the module. + type: object + properties: + denom_creation_fee: + type: array + items: + type: object + properties: + denom: + type: string + amount: + type: string + description: >- + Coin defines a token with a denomination and an amount. + + + NOTE: The amount field is an Int which implements the custom + method + + signatures required by gogoproto. + description: >- + DenomCreationFee defines the fee to be charged on the creation of + a new + + denom. The fee is drawn from the subspace treasruy account, and + + burned. + description: QueryParamsResponse is the response type for the Query/Params RPC method. + desmos.tokenfactory.v1beta1.QuerySubspaceDenomsResponse: + type: object + properties: + denoms: + type: array + items: + type: string + description: |- + QuerySubspaceDenomsResponse defines the response structure for the + SubspaceDenoms gRPC query. diff --git a/go.mod b/go.mod index 2b9f5eeb5e..e55fc29153 100644 --- a/go.mod +++ b/go.mod @@ -309,7 +309,7 @@ require ( mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed // indirect mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b // indirect mvdan.cc/unparam v0.0.0-20221223090309-7455f1af531d // indirect - nhooyr.io/websocket v1.8.6 // indirect + nhooyr.io/websocket v1.8.7 // indirect pgregory.net/rapid v0.5.5 // indirect sigs.k8s.io/yaml v1.3.0 // indirect ) diff --git a/go.sum b/go.sum index 6df9c81067..b3d5af653a 100644 --- a/go.sum +++ b/go.sum @@ -2236,8 +2236,9 @@ mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b h1:DxJ5nJdkhDlLok9K6qO+5290kphD mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jCoyKnw3vv5biOc3JnIcYfL4= mvdan.cc/unparam v0.0.0-20221223090309-7455f1af531d h1:3rvTIIM22r9pvXk+q3swxUQAQOxksVMGK7sml4nG57w= mvdan.cc/unparam v0.0.0-20221223090309-7455f1af531d/go.mod h1:IeHQjmn6TOD+e4Z3RFiZMMsLVL+A96Nvptar8Fj71is= -nhooyr.io/websocket v1.8.6 h1:s+C3xAMLwGmlI31Nyn/eAehUlZPwfYZu2JXM621Q5/k= nhooyr.io/websocket v1.8.6/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= +nhooyr.io/websocket v1.8.7 h1:usjR2uOr/zjjkVMy0lW+PPohFok7PCow5sDjLgX4P4g= +nhooyr.io/websocket v1.8.7/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= pgregory.net/rapid v0.5.5 h1:jkgx1TjbQPD/feRoK+S/mXw9e1uj6WilpHrXJowi6oA= pgregory.net/rapid v0.5.5/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= diff --git a/proto/buf.lock b/proto/buf.lock index 9e70ac49f4..9cfb67e595 100644 --- a/proto/buf.lock +++ b/proto/buf.lock @@ -5,23 +5,29 @@ deps: owner: cosmos repository: cosmos-proto commit: 1935555c206d4afb9e94615dfd0fad31 + digest: shake256:c74d91a3ac7ae07d579e90eee33abf9b29664047ac8816500cf22c081fec0d72d62c89ce0bebafc1f6fec7aa5315be72606717740ca95007248425102c365377 - remote: buf.build owner: cosmos repository: cosmos-sdk commit: 954f7b05f38440fc8250134b15adec47 + digest: shake256:2ab4404fd04a7d1d52df0e2d0f2d477a3d83ffd88d876957bf3fedfd702c8e52833d65b3ce1d89a3c5adf2aab512616b0e4f51d8463f07eda9a8a3317ee3ac54 - remote: buf.build owner: cosmos repository: gogo-proto - commit: 34d970b699f84aa382f3c29773a60836 + commit: 5e5b9fdd01804356895f8f79a6f1ddc1 + digest: shake256:0b85da49e2e5f9ebc4806eae058e2f56096ff3b1c59d1fb7c190413dd15f45dd456f0b69ced9059341c80795d2b6c943de15b120a9e0308b499e43e4b5fc2952 - remote: buf.build owner: cosmos repository: ibc - commit: d6a99e4eff7443b1b9c887d1feb2b23f + commit: e6b07bb8a5a548f6a5135067a2538ddd + digest: shake256:5794f44aeabb1402b4d52c98c16f34536aa3b536edfe37354723364da8e98c84c4ade83b0bc32a378e60870e9442222132dcc4bf47d3b4395956f4ab73ed32b1 - remote: buf.build owner: cosmos repository: ics23 commit: 55085f7c710a45f58fa09947208eb70b + digest: shake256:9bf0bc495b5a11c88d163d39ef521bc4b00bc1374a05758c91d82821bdc61f09e8c2c51dda8452529bf80137f34d852561eacbe9550a59015d51cecb0dacb628 - remote: buf.build owner: googleapis repository: googleapis - commit: 463926e7ee924d46ad0a726e1cf4eacd + commit: cc916c31859748a68fd229a3c8d7a2e8 + digest: shake256:469b049d0eb04203d5272062636c078decefc96fec69739159c25d85349c50c34c7706918a8b216c5c27f76939df48452148cff8c5c3ae77fa6ba5c25c1b8bf8 diff --git a/proto/desmos/tokenfactory/module/v1/module.proto b/proto/desmos/tokenfactory/module/v1/module.proto new file mode 100644 index 0000000000..69818ce7af --- /dev/null +++ b/proto/desmos/tokenfactory/module/v1/module.proto @@ -0,0 +1,16 @@ +syntax = "proto3"; + +package desmos.tokenfactory.module.v1; + +import "cosmos/app/v1alpha1/module.proto"; + +// Module is the config object of the tokenfactory module. +message Module { + option (cosmos.app.v1alpha1.module) = { + go_import : "github.com/desmos-labs/desmos/x/tokenfactory" + }; + + // authority defines the custom module authority. If not set, defaults to the + // governance module. + string authority = 1; +} \ No newline at end of file diff --git a/proto/desmos/tokenfactory/v1beta1/genesis.proto b/proto/desmos/tokenfactory/v1beta1/genesis.proto new file mode 100644 index 0000000000..415bac256b --- /dev/null +++ b/proto/desmos/tokenfactory/v1beta1/genesis.proto @@ -0,0 +1,36 @@ +syntax = "proto3"; +package desmos.tokenfactory.v1beta1; + +import "amino/amino.proto"; +import "gogoproto/gogo.proto"; +import "desmos/tokenfactory/v1beta1/params.proto"; +import "desmos/tokenfactory/v1beta1/models.proto"; + +option go_package = "github.com/desmos-labs/desmos/v5/x/tokenfactory/types"; + +// GenesisState defines the tokenfactory module's genesis state. +message GenesisState { + // params defines the paramaters of the module. + Params params = 1 + [ (gogoproto.nullable) = false, (amino.dont_omitempty) = true ]; + + repeated GenesisDenom factory_denoms = 2 [ + (gogoproto.moretags) = "yaml:\"factory_denoms\"", + (gogoproto.nullable) = false, + (amino.dont_omitempty) = true + ]; +} + +// GenesisDenom defines a tokenfactory denom that is defined within genesis +// state. The structure contains DenomAuthorityMetadata which defines the +// denom's admin. +message GenesisDenom { + option (gogoproto.equal) = true; + + string denom = 1 [ (gogoproto.moretags) = "yaml:\"denom\"" ]; + DenomAuthorityMetadata authority_metadata = 2 [ + (gogoproto.moretags) = "yaml:\"authority_metadata\"", + (gogoproto.nullable) = false, + (amino.dont_omitempty) = true + ]; +} diff --git a/proto/desmos/tokenfactory/v1beta1/models.proto b/proto/desmos/tokenfactory/v1beta1/models.proto new file mode 100644 index 0000000000..2ab0a49c67 --- /dev/null +++ b/proto/desmos/tokenfactory/v1beta1/models.proto @@ -0,0 +1,20 @@ +syntax = "proto3"; +package desmos.tokenfactory.v1beta1; + +import "gogoproto/gogo.proto"; +import "cosmos_proto/cosmos.proto"; + +option go_package = "github.com/desmos-labs/desmos/v5/x/tokenfactory/types"; + +// DenomAuthorityMetadata specifies metadata for addresses that have specific +// capabilities over a token factory denom. Right now there is only one Admin +// permission, but is planned to be extended to the future. +message DenomAuthorityMetadata { + option (gogoproto.equal) = true; + + // Can be empty for no admin, or a valid osmosis address + string admin = 1 [ + (gogoproto.moretags) = "yaml:\"admin\"", + (cosmos_proto.scalar) = "cosmos.AddressString" + ]; +} diff --git a/proto/desmos/tokenfactory/v1beta1/msgs.proto b/proto/desmos/tokenfactory/v1beta1/msgs.proto new file mode 100644 index 0000000000..7880e12bfd --- /dev/null +++ b/proto/desmos/tokenfactory/v1beta1/msgs.proto @@ -0,0 +1,218 @@ +syntax = "proto3"; +package desmos.tokenfactory.v1beta1; + +import "amino/amino.proto"; +import "gogoproto/gogo.proto"; +import "cosmos/base/v1beta1/coin.proto"; +import "cosmos/bank/v1beta1/bank.proto"; +import "cosmos_proto/cosmos.proto"; +import "cosmos/msg/v1/msg.proto"; + +import "desmos/tokenfactory/v1beta1/params.proto"; + +option go_package = "github.com/desmos-labs/desmos/v5/x/tokenfactory/types"; + +// Msg defines the tokefactory module's gRPC message service. +service Msg { + option (cosmos.msg.v1.service) = true; + + // CreateDenom allows an account to create a new denom for subspace. It + // requires a subspace and a sub denomination. The (subspace_treasury_address, + // sub_denomination) tuple must be unique and cannot be re-used. + // + // The resulting denom created is defined as + // . The resulting denom's admin is + // originally set to be the subspace treasury account, and this can not be + // changed later. + // + // Since: Desmos 6.0.0 + rpc CreateDenom(MsgCreateDenom) returns (MsgCreateDenomResponse); + + // Mint allows subspace admins to mint more of a token. + // + // Since: Desmos 6.0.0 + rpc Mint(MsgMint) returns (MsgMintResponse); + + // Burn allows subspace admins to burn a token. + // For now, we only support burning from the treasury account. + // + // Since: Desmos 6.0.0 + rpc Burn(MsgBurn) returns (MsgBurnResponse); + + // SetDenomMetadata allows subspace admins to set the denom's bank metadata. + // + // Since: Desmos 6.0.0 + rpc SetDenomMetadata(MsgSetDenomMetadata) + returns (MsgSetDenomMetadataResponse); + + // UpdateParams defines a (governance) operation for updating the module + // parameters. The authority defaults to the x/gov module account. + // + // Since: Desmos 6.0.0 + rpc UpdateParams(MsgUpdateParams) returns (MsgUpdateParamsResponse); +} + +// MsgCreateDenom represents the message to be used to create a denom for +// subspace +// +// Since: Desmos 6.0.0 +message MsgCreateDenom { + option (cosmos.msg.v1.signer) = "sender"; + option (amino.name) = "desmos/MsgCreateDenom"; + + // Id of the subspace which manages the denom + uint64 subspace_id = 1 [ + (gogoproto.customname) = "SubspaceID", + (gogoproto.moretags) = "yaml:\"subspace_id\"" + ]; + + // Address of user having the permission to manage subspace denoms + string sender = 2 [ + (gogoproto.moretags) = "yaml:\"sender\"", + (cosmos_proto.scalar) = "cosmos.AddressString" + ]; + + // Subdenom name of the creating denom + // It can be up to 44 "alphanumeric" characters long + string subdenom = 3 [ (gogoproto.moretags) = "yaml:\"subdenom\"" ]; +} + +// MsgCreateDenomResponse represents the Msg/CreateDenom response type +// It returns the full string of the newly created denom +message MsgCreateDenomResponse { + // Name of the newly created denom + string new_token_denom = 1 + [ (gogoproto.moretags) = "yaml:\"new_token_denom\"" ]; +} + +// MsgMint represents the message to be used to mint subspace tokens to treasury +// account +// +// Since: Desmos 6.0.0 +message MsgMint { + option (cosmos.msg.v1.signer) = "sender"; + option (amino.name) = "desmos/MsgMint"; + + // Id of the subspace which manages the denom + uint64 subspace_id = 1 [ + (gogoproto.customname) = "SubspaceID", + (gogoproto.moretags) = "yaml:\"subspace_id\"" + ]; + + // Address of user having the permission to manage subspace denoms + string sender = 2 [ + (gogoproto.moretags) = "yaml:\"sender\"", + (cosmos_proto.scalar) = "cosmos.AddressString" + ]; + + // Amount of the minting subspace tokens + cosmos.base.v1beta1.Coin amount = 3 [ + (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins", + (gogoproto.moretags) = "yaml:\"amount\"", + (gogoproto.nullable) = false, + (amino.encoding) = "legacy_coins", + (amino.dont_omitempty) = true + ]; +} + +// MsgMintResponse represents the Msg/Mint response type +// +// Since: Desmos 6.0.0 +message MsgMintResponse {} + +// MsgBurn represents the message to be used to burn subspace tokens from +// treasury account +// +// Since: Desmos 6.0.0 +message MsgBurn { + option (cosmos.msg.v1.signer) = "sender"; + option (amino.name) = "desmos/MsgBurn"; + + // Id of the subspace which manages the denom + uint64 subspace_id = 1 [ + (gogoproto.customname) = "SubspaceID", + (gogoproto.moretags) = "yaml:\"subspace_id\"" + ]; + + // Address of user having the permission to manage subspace denoms + string sender = 2 [ + (gogoproto.moretags) = "yaml:\"sender\"", + (cosmos_proto.scalar) = "cosmos.AddressString" + ]; + + // Amount of the burning subspace tokens + cosmos.base.v1beta1.Coin amount = 3 [ + (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins", + (gogoproto.moretags) = "yaml:\"amount\"", + (gogoproto.nullable) = false, + (amino.encoding) = "legacy_coins", + (amino.dont_omitempty) = true + ]; +} + +// MsgBurnResponse represents the Msg/Burn response type +// +// Since: Desmos 6.0.0 +message MsgBurnResponse {} + +// MsgSetDenomMetadata represents the message to be used to set the subspace +// token's bank metadata +// +// Since: Desmos 6.0.0 +message MsgSetDenomMetadata { + option (cosmos.msg.v1.signer) = "sender"; + option (amino.name) = "desmos/MsgSetDenomMetadata"; + + // Id of the subspace which manages the denom + uint64 subspace_id = 1 [ + (gogoproto.customname) = "SubspaceID", + (gogoproto.moretags) = "yaml:\"subspace_id\"" + ]; + + // Address of user having the permission to manage subspace denoms + string sender = 2 [ + (gogoproto.moretags) = "yaml:\"sender\"", + (cosmos_proto.scalar) = "cosmos.AddressString" + ]; + + // Metadata of the denom + cosmos.bank.v1beta1.Metadata metadata = 3 [ + (gogoproto.moretags) = "yaml:\"metadata\"", + (gogoproto.nullable) = false, + (amino.dont_omitempty) = true + ]; +} + +// MsgSetDenomMetadataResponse represents the Msg/SetDenomMetadata response type +// +// Since: Desmos 6.0.0 +message MsgSetDenomMetadataResponse {} + +// MsgUpdateParams is the Msg/UpdateParams request type. +// +// Since: Desmos 6.0.0 +message MsgUpdateParams { + option (amino.name) = "desmos/x/tokenfactoy/MsgUpdateParams"; + option (cosmos.msg.v1.signer) = "authority"; + + // authority is the address that controls the module (defaults to x/gov unless + // overwritten). + string authority = 1 [ + (gogoproto.moretags) = "yaml:\"authority\"", + (cosmos_proto.scalar) = "cosmos.AddressString" + ]; + + // params defines the parameters to update. + // + // NOTE: All parameters must be supplied. + Params params = 2 [ + (gogoproto.moretags) = "yaml:\"params\"", + (gogoproto.nullable) = false, + (amino.dont_omitempty) = true + ]; +} + +// MsgUpdateParamsResponse represents the Msg/UpdateParams response type +// +// Since: Desmos 6.0.0 +message MsgUpdateParamsResponse {} \ No newline at end of file diff --git a/proto/desmos/tokenfactory/v1beta1/params.proto b/proto/desmos/tokenfactory/v1beta1/params.proto new file mode 100644 index 0000000000..3ebdfcdc1f --- /dev/null +++ b/proto/desmos/tokenfactory/v1beta1/params.proto @@ -0,0 +1,26 @@ +syntax = "proto3"; +package desmos.tokenfactory.v1beta1; + +import "amino/amino.proto"; +import "gogoproto/gogo.proto"; +import "cosmos/base/v1beta1/coin.proto"; + +option go_package = "github.com/desmos-labs/desmos/v5/x/tokenfactory/types"; + +// Params defines the parameters for the tokenfactory module. +// +// Since: Desmos 6.0.0 +message Params { + option (amino.name) = "desmos/x/tokenfactory/Params"; + + // DenomCreationFee defines the fee to be charged on the creation of a new + // denom. The fee is drawn from the subspace treasruy account, and + // burned. + repeated cosmos.base.v1beta1.Coin denom_creation_fee = 1 [ + (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins", + (gogoproto.moretags) = "yaml:\"denom_creation_fee\"", + (gogoproto.nullable) = false, + (amino.encoding) = "legacy_coins", + (amino.dont_omitempty) = true + ]; +} \ No newline at end of file diff --git a/proto/desmos/tokenfactory/v1beta1/query.proto b/proto/desmos/tokenfactory/v1beta1/query.proto new file mode 100644 index 0000000000..5ccc9f2da8 --- /dev/null +++ b/proto/desmos/tokenfactory/v1beta1/query.proto @@ -0,0 +1,48 @@ +syntax = "proto3"; +package desmos.tokenfactory.v1beta1; + +import "amino/amino.proto"; +import "gogoproto/gogo.proto"; +import "google/api/annotations.proto"; +import "desmos/tokenfactory/v1beta1/params.proto"; + +option go_package = "github.com/desmos-labs/desmos/v5/x/tokenfactory/types"; + +// Query defines the gRPC querier service. +service Query { + // Params defines a gRPC query method that returns the tokenfactory module's + // parameters. + rpc Params(QueryParamsRequest) returns (QueryParamsResponse) { + option (google.api.http).get = "/desmos/tokenfactory/v1beta1/params"; + } + + // SubspaceDenoms defines a gRPC query method for fetching all + // denominations created by a specific subspace. + rpc SubspaceDenoms(QuerySubspaceDenomsRequest) + returns (QuerySubspaceDenomsResponse) { + option (google.api.http).get = + "/desmos/tokenfactory/v1beta1/subspaces/{subspace_id}/denoms"; + } +} + +// QueryParamsRequest is the request type for the Query/Params RPC method. +message QueryParamsRequest {} + +// QueryParamsResponse is the response type for the Query/Params RPC method. +message QueryParamsResponse { + // params defines the parameters of the module. + Params params = 1 + [ (gogoproto.nullable) = false, (amino.dont_omitempty) = true ]; +} + +// QuerySubspaceDenomsRequest defines the request structure for the +// SubspaceDenoms gRPC query. +message QuerySubspaceDenomsRequest { + uint64 subspace_id = 1 [ (gogoproto.moretags) = "yaml:\"creator\"" ]; +} + +// QuerySubspaceDenomsResponse defines the response structure for the +// SubspaceDenoms gRPC query. +message QuerySubspaceDenomsResponse { + repeated string denoms = 1 [ (gogoproto.moretags) = "yaml:\"denoms\"" ]; +} diff --git a/x/posts/testutil/expected_keepers_mocks.go b/x/posts/testutil/expected_keepers_mocks.go index cc73462020..05c80e7990 100644 --- a/x/posts/testutil/expected_keepers_mocks.go +++ b/x/posts/testutil/expected_keepers_mocks.go @@ -1,5 +1,5 @@ // Code generated by MockGen. DO NOT EDIT. -// Source: types/expected_keepers.go +// Source: ./x/posts/types/expected_keepers.go // Package testutil is a generated GoMock package. package testutil diff --git a/x/subspaces/simulation/utils.go b/x/subspaces/simulation/utils.go index fab1cffefa..8259be4fd4 100644 --- a/x/subspaces/simulation/utils.go +++ b/x/subspaces/simulation/utils.go @@ -36,11 +36,12 @@ func GenerateRandomSubspace(r *rand.Rand, accs []simtypes.Account) types.Subspac simAccount, _ := simtypes.RandomAcc(r, accs) creator := simAccount.Address.String() + id := RandomID(r) return types.NewSubspace( RandomID(r), RandomName(r), RandomDescription(r), - creator, + types.GetTreasuryAddress(id).String(), creator, creator, RandomDate(r), diff --git a/x/tokenfactory/client/cli/cli_test.go b/x/tokenfactory/client/cli/cli_test.go new file mode 100644 index 0000000000..2690f24361 --- /dev/null +++ b/x/tokenfactory/client/cli/cli_test.go @@ -0,0 +1,489 @@ +//go:build norace +// +build norace + +package cli_test + +import ( + "fmt" + "os" + "path" + "testing" + "time" + + tmcli "github.com/cometbft/cometbft/libs/cli" + "github.com/cosmos/cosmos-sdk/client/flags" + clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli" + "github.com/cosmos/cosmos-sdk/testutil/network" + sdk "github.com/cosmos/cosmos-sdk/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + "github.com/gogo/protobuf/proto" + "github.com/stretchr/testify/suite" + + "github.com/desmos-labs/desmos/v5/testutil" + subspacestypes "github.com/desmos-labs/desmos/v5/x/subspaces/types" + "github.com/desmos-labs/desmos/v5/x/tokenfactory/client/cli" + "github.com/desmos-labs/desmos/v5/x/tokenfactory/types" +) + +func TestIntegrationTestSuite(t *testing.T) { + suite.Run(t, new(IntegrationTestSuite)) +} + +type IntegrationTestSuite struct { + suite.Suite + + cfg network.Config + network *network.Network +} + +func (s *IntegrationTestSuite) SetupSuite() { + s.T().Log("setting up integration test suite") + + cfg := testutil.DefaultConfig() + genesisState := cfg.GenesisState + cfg.NumValidators = 2 + + // Initialize the subspaces module genesis state + subspacesGenesis := subspacestypes.NewGenesisState( + 2, + []subspacestypes.SubspaceData{ + subspacestypes.NewSubspaceData(1, 1, 1), + }, + []subspacestypes.Subspace{ + subspacestypes.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1cyjzgj9j7d2gdqk78pa0fgvfnlzradat97aek9", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + nil, + ), + }, + nil, nil, nil, nil, nil, + ) + + subspacesDataBz, err := cfg.Codec.MarshalJSON(subspacesGenesis) + s.Require().NoError(err) + genesisState[subspacestypes.ModuleName] = subspacesDataBz + + tokenfactoryGenesis := &types.GenesisState{ + Params: types.DefaultParams(), + FactoryDenoms: []types.GenesisDenom{ + { + Denom: "factory/cosmos1cyjzgj9j7d2gdqk78pa0fgvfnlzradat97aek9/uminttoken", + AuthorityMetadata: types.DenomAuthorityMetadata{ + Admin: "cosmos1s0he0z3g92zwsxdj83h0ky9w463sx7gq9mqtgn", + }, + }, + { + Denom: "factory/cosmos1cyjzgj9j7d2gdqk78pa0fgvfnlzradat97aek9/utesttoken", + AuthorityMetadata: types.DenomAuthorityMetadata{ + Admin: "cosmos1cyjzgj9j7d2gdqk78pa0fgvfnlzradat97aek9", + }, + }, + }, + } + + tokenfactoryDataBz, err := cfg.Codec.MarshalJSON(tokenfactoryGenesis) + s.Require().NoError(err) + genesisState[types.ModuleName] = tokenfactoryDataBz + + cfg.GenesisState = genesisState + + s.cfg = cfg + s.network, err = network.New(s.T(), s.T().TempDir(), cfg) + s.Require().NoError(err) + + _, err = s.network.WaitForHeight(1) + s.Require().NoError(err) +} + +func (s *IntegrationTestSuite) TearDownSuite() { + s.T().Log("tearing down integration test suite") + s.network.Cleanup() +} + +// -------------------------------------------------------------------------------------------------------------------- + +func (s *IntegrationTestSuite) TestCmdQueryParams() { + val := s.network.Validators[0] + testCases := []struct { + name string + args []string + shouldErr bool + expResponse types.QueryParamsResponse + }{ + { + name: "params is returned properly", + args: []string{ + fmt.Sprintf("--%s=json", tmcli.OutputFlag), + }, + shouldErr: false, + expResponse: types.QueryParamsResponse{ + Params: types.DefaultParams(), + }, + }, + } + + for _, tc := range testCases { + tc := tc + s.Run(tc.name, func() { + cmd := cli.GetCmdQueryParams() + clientCtx := val.ClientCtx + out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) + + if tc.shouldErr { + s.Require().Error(err) + } else { + s.Require().NoError(err) + + var response types.QueryParamsResponse + s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &response), out.String()) + s.Require().Equal(tc.expResponse.Params, response.Params) + } + }) + } +} + +func (s *IntegrationTestSuite) TestCmdQuerySubspaceDenoms() { + val := s.network.Validators[0] + testCases := []struct { + name string + args []string + shouldErr bool + expResponse types.QuerySubspaceDenomsResponse + }{ + { + name: "invalid subspace id returns error", + args: []string{ + "X", + fmt.Sprintf("--%s=json", tmcli.OutputFlag), + }, + shouldErr: true, + }, + { + name: "denoms are returned properly", + args: []string{ + "1", + fmt.Sprintf("--%s=json", tmcli.OutputFlag), + }, + shouldErr: false, + expResponse: types.QuerySubspaceDenomsResponse{ + Denoms: []string{ + "factory/cosmos1cyjzgj9j7d2gdqk78pa0fgvfnlzradat97aek9/uminttoken", + "factory/cosmos1cyjzgj9j7d2gdqk78pa0fgvfnlzradat97aek9/utesttoken", + }, + }, + }, + } + + for _, tc := range testCases { + tc := tc + s.Run(tc.name, func() { + cmd := cli.GetCmdQuerySubspaceDenoms() + clientCtx := val.ClientCtx + out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) + + if tc.shouldErr { + s.Require().Error(err) + } else { + s.Require().NoError(err) + + var response types.QuerySubspaceDenomsResponse + s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &response), out.String()) + s.Require().Equal(tc.expResponse.Denoms, response.Denoms) + } + }) + } +} + +// -------------------------------------------------------------------------------------------------------------------- + +func (s *IntegrationTestSuite) TestCmdCreateDenom() { + val := s.network.Validators[0] + testCases := []struct { + name string + args []string + shouldErr bool + respType proto.Message + }{ + { + name: "invalid subspace id returns error", + args: []string{ + "X", "utrytoken", + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + }, + shouldErr: true, + }, + { + name: "invalid subdenom returns error", + args: []string{ + "1", "", + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + }, + shouldErr: true, + }, + { + name: "valid request returns no error", + args: []string{ + "1", "utrytoken", + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + }, + shouldErr: false, + respType: &sdk.TxResponse{}, + }, + } + + for _, tc := range testCases { + tc := tc + s.Run(tc.name, func() { + cmd := cli.GetCmdCreateDenom() + clientCtx := val.ClientCtx + + out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) + if tc.shouldErr { + s.Require().Error(err) + } else { + s.Require().NoError(err) + s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) + } + }) + } +} + +func (s *IntegrationTestSuite) TestCmdMint() { + val := s.network.Validators[0] + testCases := []struct { + name string + args []string + shouldErr bool + respType proto.Message + }{ + { + name: "invalid subspace id returns error", + args: []string{ + "X", + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + }, + shouldErr: true, + }, + { + name: "invalid amount returns error", + args: []string{ + "1", "X", + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + }, + shouldErr: true, + }, + { + name: "invalid sender returns error", + args: []string{ + "1", "10factory/cosmos1cyjzgj9j7d2gdqk78pa0fgvfnlzradat97aek9/uminttoken", + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + }, + shouldErr: true, + }, + { + name: "valid request returns no error", + args: []string{ + "1", "10factory/cosmos1cyjzgj9j7d2gdqk78pa0fgvfnlzradat97aek9/uminttoken", + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + }, + shouldErr: false, + respType: &sdk.TxResponse{}, + }, + } + + for _, tc := range testCases { + tc := tc + s.Run(tc.name, func() { + cmd := cli.GetCmdMint() + clientCtx := val.ClientCtx + + out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) + if tc.shouldErr { + s.Require().Error(err) + } else { + s.Require().NoError(err) + s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) + } + }) + } +} + +func (s *IntegrationTestSuite) TestCmdBurn() { + val := s.network.Validators[0] + testCases := []struct { + name string + args []string + shouldErr bool + respType proto.Message + }{ + { + name: "invalid subspace id returns error", + args: []string{ + "X", + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + }, + shouldErr: true, + }, + { + name: "invalid amount returns error", + args: []string{ + "1", "X", + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + }, + shouldErr: true, + }, + { + name: "invalid sender returns error", + args: []string{ + "1", "10factory/cosmos1cyjzgj9j7d2gdqk78pa0fgvfnlzradat97aek9/uminttoken", + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + }, + shouldErr: true, + }, + { + name: "valid request returns no error", + args: []string{ + "1", "10factory/cosmos1cyjzgj9j7d2gdqk78pa0fgvfnlzradat97aek9/uminttoken", + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + }, + shouldErr: false, + respType: &sdk.TxResponse{}, + }, + } + + for _, tc := range testCases { + tc := tc + s.Run(tc.name, func() { + cmd := cli.GetCmdBurn() + clientCtx := val.ClientCtx + + out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) + if tc.shouldErr { + s.Require().Error(err) + } else { + s.Require().NoError(err) + s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) + } + }) + } +} + +func (s *IntegrationTestSuite) TestCmdSetDenomMetadata() { + val := s.network.Validators[0] + testCases := []struct { + name string + setupFile func() string + args []string + shouldErr bool + respType proto.Message + }{ + { + name: "invalid subspace id returns error", + args: []string{ + "X", + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + }, + shouldErr: true, + }, + { + name: "invalid path returns error", + args: []string{ + "1", "X", + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + }, + shouldErr: true, + }, + { + name: "invalid metadata schema returns error", + setupFile: func() string { + os.CreateTemp(os.TempDir(), "metadata.json") + return path.Join(os.TempDir(), "metadata.json") + }, + args: []string{ + "1", path.Join(os.TempDir(), "metadata.json"), + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + }, + shouldErr: true, + }, + { + name: "valid request returns no error", + setupFile: func() string { + file, _ := os.CreateTemp(os.TempDir(), "metadata.json") + + bz := s.cfg.Codec.MustMarshalJSON(&banktypes.Metadata{ + Name: "Mint Token", + Symbol: "MTK", + Description: "The custom token of the test subspace.", + DenomUnits: []*banktypes.DenomUnit{ + {Denom: "factory/cosmos1cyjzgj9j7d2gdqk78pa0fgvfnlzradat97aek9/uminttoken", Exponent: uint32(0), Aliases: nil}, + {Denom: "minttoken", Exponent: uint32(6), Aliases: []string{"minttoken"}}, + }, + Base: "factory/cosmos1cyjzgj9j7d2gdqk78pa0fgvfnlzradat97aek9/uminttoken", + Display: "minttoken", + }) + file.Write(bz) + return path.Join(os.TempDir(), "metadata.json") + }, + args: []string{ + "1", path.Join(os.TempDir(), "metadata.json"), + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + }, + shouldErr: false, + respType: &sdk.TxResponse{}, + }, + } + + for _, tc := range testCases { + tc := tc + s.Run(tc.name, func() { + cmd := cli.GetCmdCreateDenom() + clientCtx := val.ClientCtx + + out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) + if tc.shouldErr { + s.Require().Error(err) + } else { + s.Require().NoError(err) + s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) + } + }) + } +} + +func (s *IntegrationTestSuite) TestCmdDraftDenomMetadata() { + val := s.network.Validators[0] + + s.Run("draft denom metadata properly", func() { + outputPath := path.Join(os.TempDir(), "metadata.json") + cmd := cli.GetCmdDraftDenomMetadata() + clientCtx := val.ClientCtx + + _, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, []string{fmt.Sprintf("--%s=%s", cli.FlagOutputPath, outputPath)}) + s.Require().NoError(err) + + out, err := os.ReadFile(outputPath) + s.Require().NoError(err) + + var metadata banktypes.Metadata + err = clientCtx.Codec.UnmarshalJSON(out, &metadata) + s.Require().NoError(err) + s.Require().Equal(banktypes.Metadata{DenomUnits: []*banktypes.DenomUnit{}}, metadata) + }) +} diff --git a/x/tokenfactory/client/cli/query.go b/x/tokenfactory/client/cli/query.go new file mode 100644 index 0000000000..256debb956 --- /dev/null +++ b/x/tokenfactory/client/cli/query.go @@ -0,0 +1,92 @@ +package cli + +import ( + "context" + "fmt" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/version" + subspacestypes "github.com/desmos-labs/desmos/v5/x/subspaces/types" + "github.com/desmos-labs/desmos/v5/x/tokenfactory/types" + "github.com/spf13/cobra" +) + +// DONTCOVER + +// GetQueryCmd returns the command allowing to perform queries +func GetQueryCmd() *cobra.Command { + queryCmd := &cobra.Command{ + Use: types.ModuleName, + Short: "Querying commands for the token factory module", + DisableFlagParsing: true, + SuggestionsMinimumDistance: 2, + RunE: client.ValidateCmd, + } + queryCmd.AddCommand( + GetCmdQuerySubspaceDenoms(), + GetCmdQueryParams(), + ) + return queryCmd +} + +// GetCmdQuerySubspaceDenoms returns the command to query subspace denoms of the given subspace with id +func GetCmdQuerySubspaceDenoms() *cobra.Command { + cmd := &cobra.Command{ + Use: "subspace-denoms [subspace-id]", + Short: "Query the denoms owned by the subspace", + Example: fmt.Sprintf(`%s query tokenfactory subspace-denom 1`, version.AppName), + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + queryClient := types.NewQueryClient(clientCtx) + + subspaceID, err := subspacestypes.ParseSubspaceID(args[0]) + if err != nil { + return err + } + + res, err := queryClient.SubspaceDenoms(context.Background(), types.NewQuerySubspaceDenomsRequest(subspaceID)) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + + return cmd +} + +// GetCmdQueryParams returns the command to query the params of the module +func GetCmdQueryParams() *cobra.Command { + cmd := &cobra.Command{ + Use: "params", + Short: "Query the module parameters", + Example: fmt.Sprintf(`%s query tokenfactory params`, version.AppName), + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, _ []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + queryClient := types.NewQueryClient(clientCtx) + + res, err := queryClient.Params(context.Background(), types.NewQueryParamsRequest()) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + + return cmd +} diff --git a/x/tokenfactory/client/cli/tx.go b/x/tokenfactory/client/cli/tx.go new file mode 100644 index 0000000000..e7388d6b11 --- /dev/null +++ b/x/tokenfactory/client/cli/tx.go @@ -0,0 +1,225 @@ +package cli + +import ( + "fmt" + "os" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/client/tx" + sdk "github.com/cosmos/cosmos-sdk/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + "github.com/spf13/cobra" + + subspacestypes "github.com/desmos-labs/desmos/v5/x/subspaces/types" + "github.com/desmos-labs/desmos/v5/x/tokenfactory/types" +) + +const ( + FlagOutputPath = "output-path" +) + +// DONTCOVER + +// GetTxCmd returns the transaction commands for this module +func GetTxCmd() *cobra.Command { + txCmd := &cobra.Command{ + Use: types.ModuleName, + Short: "Token factory transaction subcommands", + DisableFlagParsing: true, + SuggestionsMinimumDistance: 2, + RunE: client.ValidateCmd, + } + + txCmd.AddCommand( + GetCmdCreateDenom(), + GetCmdMint(), + GetCmdBurn(), + GetCmdSetDenomMetadata(), + GetCmdDraftDenomMetadata(), + ) + + return txCmd +} + +// GetCmdCreateDenom returns the command used to create a denom +func GetCmdCreateDenom() *cobra.Command { + cmd := &cobra.Command{ + Use: "create-denom [subspace-id] [subdenom]", + Short: fmt.Sprintf("create a new denom from an account. (Costs %s though!)", sdk.DefaultBondDenom), + Args: cobra.ExactArgs(2), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + subspaceID, err := subspacestypes.ParseSubspaceID(args[0]) + if err != nil { + return err + } + + sender := clientCtx.FromAddress + msg := types.NewMsgCreateDenom(subspaceID, sender.String(), args[1]) + if err = msg.ValidateBasic(); err != nil { + return fmt.Errorf("message validation failed: %w", err) + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + flags.AddTxFlagsToCmd(cmd) + + return cmd +} + +// GetCmdMint returns the command used to mint a denom to an address +func GetCmdMint() *cobra.Command { + cmd := &cobra.Command{ + Use: "mint [subspace-id] [amount]", + Short: "Mint a denom to an address. Must have permissions to do so.", + Args: cobra.ExactArgs(2), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + subspaceID, err := subspacestypes.ParseSubspaceID(args[0]) + if err != nil { + return err + } + + amount, err := sdk.ParseCoinNormalized(args[1]) + if err != nil { + return err + } + + sender := clientCtx.FromAddress + msg := types.NewMsgMint(subspaceID, sender.String(), amount) + if err = msg.ValidateBasic(); err != nil { + return fmt.Errorf("message validation failed: %w", err) + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + flags.AddTxFlagsToCmd(cmd) + + return cmd +} + +// GetCmdBurn returns the command used to burn a denom from the treasury account +func GetCmdBurn() *cobra.Command { + cmd := &cobra.Command{ + Use: "burn [subspace-id] [amount]", + Short: "Burn tokens from the treasury account. Must have permissions to do so.", + Args: cobra.ExactArgs(2), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + subspaceID, err := subspacestypes.ParseSubspaceID(args[0]) + if err != nil { + return err + } + + amount, err := sdk.ParseCoinNormalized(args[1]) + if err != nil { + return err + } + + sender := clientCtx.FromAddress + msg := types.NewMsgBurn(subspaceID, sender.String(), amount) + if err = msg.ValidateBasic(); err != nil { + return fmt.Errorf("message validation failed: %w", err) + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + flags.AddTxFlagsToCmd(cmd) + + return cmd +} + +// GetCmdSetDenomMetadata returns the command used to set the metadata of the denom +func GetCmdSetDenomMetadata() *cobra.Command { + cmd := &cobra.Command{ + Use: "set-denom-metadata [subspace-id] [json-path]", + Short: "Set a subspace token metadata. Must have permissions to do so.", + Args: cobra.ExactArgs(2), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + subspaceID, err := subspacestypes.ParseSubspaceID(args[0]) + if err != nil { + return err + } + + var metadata banktypes.Metadata + bz, err := os.ReadFile(args[1]) + if err != nil { + return err + } + + err = clientCtx.Codec.UnmarshalJSON(bz, &metadata) + if err != nil { + return err + } + + sender := clientCtx.FromAddress + msg := types.NewMsgSetDenomMetadata(subspaceID, sender.String(), metadata) + if err = msg.ValidateBasic(); err != nil { + return fmt.Errorf("message validation failed: %w", err) + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + flags.AddTxFlagsToCmd(cmd) + + return cmd +} + +// GetCmdDraftDenomMetadata returns the command used to draft a denom metadata +func GetCmdDraftDenomMetadata() *cobra.Command { + cmd := &cobra.Command{ + Use: "draft-denom-metadata", + Short: "Draft a subspace token metadata for setting denom metadata", + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, _ []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + output, err := cmd.Flags().GetString(FlagOutputPath) + if err != nil { + return err + } + + var metadata banktypes.Metadata + bz, err := clientCtx.Codec.MarshalJSON(&metadata) + if err != nil { + return err + } + + return os.WriteFile(output, bz, 0600) + }, + } + + cmd.Flags().String(FlagOutputPath, "metadata.json", "output file path of the draft metadata") + flags.AddTxFlagsToCmd(cmd) + + return cmd +} diff --git a/x/tokenfactory/keeper/admins.go b/x/tokenfactory/keeper/admins.go new file mode 100644 index 0000000000..b99ade0999 --- /dev/null +++ b/x/tokenfactory/keeper/admins.go @@ -0,0 +1,29 @@ +package keeper + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/desmos-labs/desmos/v5/x/tokenfactory/types" +) + +// GetAuthorityMetadata returns the authority metadata for a specific denom +func (k Keeper) GetAuthorityMetadata(ctx sdk.Context, denom string) types.DenomAuthorityMetadata { + bz := k.GetDenomPrefixStore(ctx, denom).Get([]byte(types.DenomAuthorityMetadataKey)) + + var metadata types.DenomAuthorityMetadata + k.cdc.MustUnmarshal(bz, &metadata) + return metadata +} + +// SetAuthorityMetadata stores authority metadata for a specific denom +func (k Keeper) SetAuthorityMetadata(ctx sdk.Context, denom string, metadata types.DenomAuthorityMetadata) error { + err := metadata.Validate() + if err != nil { + return err + } + + store := k.GetDenomPrefixStore(ctx, denom) + + store.Set([]byte(types.DenomAuthorityMetadataKey), k.cdc.MustMarshal(&metadata)) + return nil +} diff --git a/x/tokenfactory/keeper/bankactions.go b/x/tokenfactory/keeper/bankactions.go new file mode 100644 index 0000000000..89c608d35d --- /dev/null +++ b/x/tokenfactory/keeper/bankactions.go @@ -0,0 +1,40 @@ +package keeper + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/desmos-labs/desmos/v5/x/tokenfactory/types" +) + +func (k Keeper) mintTo(ctx sdk.Context, amount sdk.Coin, mintTo string) error { + // verify that denom is an x/tokenfactory denom + _, _, err := types.DeconstructDenom(amount.Denom) + if err != nil { + return err + } + + err = k.bk.MintCoins(ctx, types.ModuleName, sdk.NewCoins(amount)) + if err != nil { + return err + } + + addr := sdk.MustAccAddressFromBech32(mintTo) + + return k.bk.SendCoinsFromModuleToAccount(ctx, types.ModuleName, addr, sdk.NewCoins(amount)) +} + +func (k Keeper) burnFrom(ctx sdk.Context, amount sdk.Coin, burnFrom string) error { + // verify that denom is an x/tokenfactory denom + _, _, err := types.DeconstructDenom(amount.Denom) + if err != nil { + return err + } + + addr := sdk.MustAccAddressFromBech32(burnFrom) + + if err := k.bk.SendCoinsFromAccountToModule(ctx, addr, types.ModuleName, sdk.NewCoins(amount)); err != nil { + return err + } + + return k.bk.BurnCoins(ctx, types.ModuleName, sdk.NewCoins(amount)) +} diff --git a/x/tokenfactory/keeper/common_test.go b/x/tokenfactory/keeper/common_test.go new file mode 100644 index 0000000000..2c28f3635d --- /dev/null +++ b/x/tokenfactory/keeper/common_test.go @@ -0,0 +1,79 @@ +package keeper_test + +import ( + "testing" + + "github.com/golang/mock/gomock" + + "github.com/cometbft/cometbft/libs/log" + tmproto "github.com/cometbft/cometbft/proto/tendermint/types" + + db "github.com/cometbft/cometbft-db" + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/store" + storetypes "github.com/cosmos/cosmos-sdk/store/types" + sdk "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + "github.com/stretchr/testify/suite" + + "github.com/desmos-labs/desmos/v5/app" + "github.com/desmos-labs/desmos/v5/x/tokenfactory/keeper" + "github.com/desmos-labs/desmos/v5/x/tokenfactory/testutil" + "github.com/desmos-labs/desmos/v5/x/tokenfactory/types" +) + +type KeeperTestSuite struct { + suite.Suite + + cdc codec.Codec + legacyAminoCdc *codec.LegacyAmino + ctx sdk.Context + + storeKey storetypes.StoreKey + k keeper.Keeper + + bk *testutil.MockBankKeeper + sk *testutil.MockSubspacesKeeper + ak *testutil.MockAccountKeeper +} + +func (suite *KeeperTestSuite) SetupTest() { + // Define store keys + keys := sdk.NewMemoryStoreKeys(types.StoreKey) + suite.storeKey = keys[types.StoreKey] + + // Create an in-memory db + memDB := db.NewMemDB() + ms := store.NewCommitMultiStore(memDB) + for _, key := range keys { + ms.MountStoreWithDB(key, storetypes.StoreTypeIAVL, memDB) + } + + if err := ms.LoadLatestVersion(); err != nil { + panic(err) + } + + suite.ctx = sdk.NewContext(ms, tmproto.Header{ChainID: "test-chain"}, false, log.NewNopLogger()) + suite.cdc, suite.legacyAminoCdc = app.MakeCodecs() + + // Mocks initializations + ctrl := gomock.NewController(suite.T()) + defer ctrl.Finish() + + suite.bk = testutil.NewMockBankKeeper(ctrl) + suite.sk = testutil.NewMockSubspacesKeeper(ctrl) + suite.ak = testutil.NewMockAccountKeeper(ctrl) + + suite.k = keeper.NewKeeper( + suite.storeKey, + suite.cdc, + suite.sk, + suite.ak, + suite.bk, + authtypes.NewModuleAddress("gov").String(), + ) +} + +func TestKeeperTestSuite(t *testing.T) { + suite.Run(t, new(KeeperTestSuite)) +} diff --git a/x/tokenfactory/keeper/createdenom.go b/x/tokenfactory/keeper/createdenom.go new file mode 100644 index 0000000000..c018228ddb --- /dev/null +++ b/x/tokenfactory/keeper/createdenom.go @@ -0,0 +1,90 @@ +package keeper + +import ( + "fmt" + + sdk "github.com/cosmos/cosmos-sdk/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + + "github.com/desmos-labs/desmos/v5/x/tokenfactory/types" +) + +// ConvertToBaseToken converts a fee amount in a whitelisted fee token to the base fee token amount +func (k Keeper) CreateDenom(ctx sdk.Context, creator string, subdenom string) (newTokenDenom string, err error) { + denom, err := k.validateCreateDenom(ctx, creator, subdenom) + if err != nil { + return "", err + } + + err = k.chargeForCreateDenom(ctx, creator) + if err != nil { + return "", err + } + + err = k.createDenomAfterValidation(ctx, creator, denom) + return denom, err +} + +// Runs CreateDenom logic after the charge and all denom validation has been handled. +// Made into a second function for genesis initialization. +func (k Keeper) createDenomAfterValidation(ctx sdk.Context, creator string, denom string) (err error) { + _, exists := k.bk.GetDenomMetaData(ctx, denom) + if !exists { + denomMetaData := banktypes.Metadata{ + DenomUnits: []*banktypes.DenomUnit{{ + Denom: denom, + Exponent: 0, + }}, + Base: denom, + } + + k.bk.SetDenomMetaData(ctx, denomMetaData) + } + + authorityMetadata := types.DenomAuthorityMetadata{ + Admin: creator, + } + err = k.SetAuthorityMetadata(ctx, denom, authorityMetadata) + if err != nil { + return err + } + + k.AddDenomFromCreator(ctx, creator, denom) + return nil +} + +func (k Keeper) validateCreateDenom(ctx sdk.Context, creator string, subdenom string) (newTokenDenom string, err error) { + // Temporary check until IBC bug is sorted out + if k.bk.HasSupply(ctx, subdenom) { + return "", fmt.Errorf("temporary error until IBC bug is sorted out, " + + "can't create subdenoms that are the same as a native denom") + } + + denom, err := types.GetTokenDenom(creator, subdenom) + if err != nil { + return "", err + } + + _, found := k.bk.GetDenomMetaData(ctx, denom) + if found { + return "", types.ErrDenomExists + } + + return denom, nil +} + +func (k Keeper) chargeForCreateDenom(ctx sdk.Context, creator string) (err error) { + creationFee := k.GetParams(ctx).DenomCreationFee + + // Burn creation fee + if creationFee != nil { + err := k.bk.SendCoinsFromAccountToModule(ctx, sdk.MustAccAddressFromBech32(creator), types.ModuleName, creationFee) + if err != nil { + return err + } + + return k.bk.BurnCoins(ctx, types.ModuleName, creationFee) + } + + return nil +} diff --git a/x/tokenfactory/keeper/createdenom_test.go b/x/tokenfactory/keeper/createdenom_test.go new file mode 100644 index 0000000000..0c8faa1148 --- /dev/null +++ b/x/tokenfactory/keeper/createdenom_test.go @@ -0,0 +1,228 @@ +package keeper_test + +import ( + "fmt" + + sdk "github.com/cosmos/cosmos-sdk/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + "github.com/desmos-labs/desmos/v5/x/tokenfactory/types" + "github.com/golang/mock/gomock" +) + +func (suite *KeeperTestSuite) TestKeeper_CreateDenom() { + testCases := []struct { + name string + setup func() + store func(ctx sdk.Context) + shouldErr bool + creator string + subdenom string + expDenom string + check func(ctx sdk.Context) + }{ + { + name: "subdenom with existing supply returns error", + setup: func() { + suite.bk.EXPECT(). + HasSupply(gomock.Any(), "uminttoken"). + Return(true) + }, + subdenom: "uminttoken", + creator: "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", + shouldErr: true, + }, + { + name: "invalid token denoms returns error", + setup: func() { + suite.bk.EXPECT(). + HasSupply(gomock.Any(), "uminttoken"). + Return(false) + }, + subdenom: "uminttoken", + creator: "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/", + shouldErr: true, + }, + { + name: "existing denom returns error", + setup: func() { + suite.bk.EXPECT(). + HasSupply(gomock.Any(), "uminttoken"). + Return(false) + + suite.bk.EXPECT(). + GetDenomMetaData(gomock.Any(), "factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/uminttoken"). + Return(banktypes.Metadata{}, true) + }, + subdenom: "uminttoken", + creator: "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", + shouldErr: true, + }, + { + name: "burn creation fees returns error - send coins to module failed", + setup: func() { + suite.bk.EXPECT(). + HasSupply(gomock.Any(), "uminttoken"). + Return(false) + + suite.bk.EXPECT(). + GetDenomMetaData(gomock.Any(), "factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/uminttoken"). + Return(banktypes.Metadata{}, false) + + suite.bk.EXPECT(). + SendCoinsFromAccountToModule( + gomock.Any(), + sdk.MustAccAddressFromBech32("cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47"), + types.ModuleName, + sdk.NewCoins(sdk.NewCoin("test", sdk.NewInt(100))), + ). + Return(fmt.Errorf("send coin to module error")) + }, + store: func(ctx sdk.Context) { + suite.k.SetParams(ctx, types.NewParams(sdk.NewCoins(sdk.NewCoin("test", sdk.NewInt(100))))) + }, + subdenom: "uminttoken", + creator: "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", + shouldErr: true, + }, + { + name: "burn creation fees returns error - bank burn failed", + setup: func() { + suite.bk.EXPECT(). + HasSupply(gomock.Any(), "uminttoken"). + Return(false) + + suite.bk.EXPECT(). + GetDenomMetaData(gomock.Any(), "factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/uminttoken"). + Return(banktypes.Metadata{}, false) + + suite.bk.EXPECT(). + SendCoinsFromAccountToModule( + gomock.Any(), + sdk.MustAccAddressFromBech32("cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47"), + types.ModuleName, + sdk.NewCoins(sdk.NewCoin("test", sdk.NewInt(100))), + ). + Return(nil) + + suite.bk.EXPECT(). + BurnCoins(gomock.Any(), types.ModuleName, sdk.NewCoins(sdk.NewCoin("test", sdk.NewInt(100)))). + Return(fmt.Errorf("bank burn coins error")) + }, + store: func(ctx sdk.Context) { + suite.k.SetParams(ctx, types.NewParams(sdk.NewCoins(sdk.NewCoin("test", sdk.NewInt(100))))) + }, + subdenom: "uminttoken", + creator: "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", + shouldErr: true, + }, + { + name: "create denom properly", + setup: func() { + suite.bk.EXPECT(). + HasSupply(gomock.Any(), "uminttoken"). + Return(false) + + suite.bk.EXPECT(). + GetDenomMetaData(gomock.Any(), "factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/uminttoken"). + Return(banktypes.Metadata{}, false).Times(2) + + suite.bk.EXPECT(). + SendCoinsFromAccountToModule( + gomock.Any(), + sdk.MustAccAddressFromBech32("cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47"), + types.ModuleName, + sdk.NewCoins(sdk.NewCoin("test", sdk.NewInt(100))), + ). + Return(nil) + + suite.bk.EXPECT(). + BurnCoins(gomock.Any(), types.ModuleName, sdk.NewCoins(sdk.NewCoin("test", sdk.NewInt(100)))). + Return(nil) + + suite.bk.EXPECT(). + SetDenomMetaData(gomock.Any(), banktypes.Metadata{ + DenomUnits: []*banktypes.DenomUnit{{ + Denom: "factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/uminttoken", + Exponent: 0, + }}, + Base: "factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/uminttoken", + }) + }, + store: func(ctx sdk.Context) { + suite.k.SetParams(ctx, types.NewParams(sdk.NewCoins(sdk.NewCoin("test", sdk.NewInt(100))))) + }, + check: func(ctx sdk.Context) { + suite.Require().Equal( + types.DenomAuthorityMetadata{Admin: "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47"}, + suite.k.GetAuthorityMetadata(ctx, "factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/uminttoken"), + ) + suite.Require().Equal( + []string{"factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/uminttoken"}, + suite.k.GetDenomsFromCreator(ctx, "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47"), + ) + }, + subdenom: "uminttoken", + creator: "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", + expDenom: "factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/uminttoken", + }, + { + name: "create denom properly - no creation fees", + setup: func() { + suite.bk.EXPECT(). + HasSupply(gomock.Any(), "uminttoken"). + Return(false) + + suite.bk.EXPECT(). + GetDenomMetaData(gomock.Any(), "factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/uminttoken"). + Return(banktypes.Metadata{}, false).Times(2) + + suite.bk.EXPECT(). + SetDenomMetaData(gomock.Any(), banktypes.Metadata{ + DenomUnits: []*banktypes.DenomUnit{{ + Denom: "factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/uminttoken", + Exponent: 0, + }}, + Base: "factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/uminttoken", + }) + }, + check: func(ctx sdk.Context) { + suite.Require().Equal( + types.DenomAuthorityMetadata{Admin: "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47"}, + suite.k.GetAuthorityMetadata(ctx, "factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/uminttoken"), + ) + suite.Require().Equal( + []string{"factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/uminttoken"}, + suite.k.GetDenomsFromCreator(ctx, "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47"), + ) + + }, + subdenom: "uminttoken", + creator: "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", + expDenom: "factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/uminttoken", + }, + } + + for _, tc := range testCases { + tc := tc + suite.Run(tc.name, func() { + ctx, _ := suite.ctx.CacheContext() + if tc.setup != nil { + tc.setup() + } + if tc.store != nil { + tc.store(ctx) + } + + denom, err := suite.k.CreateDenom(ctx, tc.creator, tc.subdenom) + if tc.shouldErr { + suite.Require().Error(err) + } else { + suite.Require().NoError(err) + suite.Require().Equal(tc.expDenom, denom) + if tc.check != nil { + tc.check(ctx) + } + } + }) + } +} diff --git a/x/tokenfactory/keeper/creators.go b/x/tokenfactory/keeper/creators.go new file mode 100644 index 0000000000..ae78a52199 --- /dev/null +++ b/x/tokenfactory/keeper/creators.go @@ -0,0 +1,27 @@ +package keeper + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" +) + +func (k Keeper) AddDenomFromCreator(ctx sdk.Context, creator, denom string) { + store := k.GetCreatorPrefixStore(ctx, creator) + store.Set([]byte(denom), []byte(denom)) +} + +func (k Keeper) GetDenomsFromCreator(ctx sdk.Context, creator string) []string { + store := k.GetCreatorPrefixStore(ctx, creator) + + iterator := store.Iterator(nil, nil) + defer iterator.Close() + + denoms := []string{} + for ; iterator.Valid(); iterator.Next() { + denoms = append(denoms, string(iterator.Key())) + } + return denoms +} + +func (k Keeper) GetAllDenomsIterator(ctx sdk.Context) sdk.Iterator { + return k.GetCreatorsPrefixStore(ctx).Iterator(nil, nil) +} diff --git a/x/tokenfactory/keeper/creators_test.go b/x/tokenfactory/keeper/creators_test.go new file mode 100644 index 0000000000..7689435d3f --- /dev/null +++ b/x/tokenfactory/keeper/creators_test.go @@ -0,0 +1,73 @@ +package keeper_test + +import sdk "github.com/cosmos/cosmos-sdk/types" + +func (suite *KeeperTestSuite) TestKeeper_AddDenomFromCreator() { + testCases := []struct { + name string + creator string + denom string + check func(ctx sdk.Context) + }{ + { + name: "add denom creator properly", + creator: "creator", + denom: "denom", + check: func(ctx sdk.Context) { + store := suite.k.GetCreatorPrefixStore(ctx, "creator") + suite.Require().Equal( + []byte("denom"), + store.Get([]byte("denom")), + ) + }, + }, + } + + for _, tc := range testCases { + tc := tc + suite.Run(tc.name, func() { + ctx, _ := suite.ctx.CacheContext() + + suite.k.AddDenomFromCreator(ctx, tc.creator, tc.denom) + + if tc.check != nil { + tc.check(ctx) + } + }) + } +} + +func (suite *KeeperTestSuite) TestKeeper_GetDenomsFromCreator() { + testCases := []struct { + name string + store func(ctx sdk.Context) + creator string + denom string + expResult []string + }{ + { + name: "get denoms from creator properly", + store: func(ctx sdk.Context) { + suite.k.AddDenomFromCreator(ctx, "creator", "bitcoin") + suite.k.AddDenomFromCreator(ctx, "creator", "litecoin") + }, + creator: "creator", + expResult: []string{"bitcoin", "litecoin"}, + }, + } + + for _, tc := range testCases { + tc := tc + suite.Run(tc.name, func() { + ctx, _ := suite.ctx.CacheContext() + if tc.store != nil { + tc.store(ctx) + } + + suite.Require().Equal( + tc.expResult, + suite.k.GetDenomsFromCreator(ctx, tc.creator), + ) + }) + } +} diff --git a/x/tokenfactory/keeper/genesis.go b/x/tokenfactory/keeper/genesis.go new file mode 100644 index 0000000000..9325cfdc28 --- /dev/null +++ b/x/tokenfactory/keeper/genesis.go @@ -0,0 +1,52 @@ +package keeper + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/desmos-labs/desmos/v5/x/tokenfactory/types" +) + +// InitGenesis initializes the tokenfactory module's state from a provided genesis +// state. +func (k Keeper) InitGenesis(ctx sdk.Context, genState types.GenesisState) { + k.createModuleAccount(ctx) + + k.SetParams(ctx, genState.Params) + + for _, genDenom := range genState.GetFactoryDenoms() { + creator, _, err := types.DeconstructDenom(genDenom.GetDenom()) + if err != nil { + panic(err) + } + err = k.createDenomAfterValidation(ctx, creator, genDenom.GetDenom()) + if err != nil { + panic(err) + } + err = k.SetAuthorityMetadata(ctx, genDenom.GetDenom(), genDenom.GetAuthorityMetadata()) + if err != nil { + panic(err) + } + } +} + +// ExportGenesis returns the tokenfactory module's exported genesis. +func (k Keeper) ExportGenesis(ctx sdk.Context) *types.GenesisState { + genDenoms := []types.GenesisDenom{} + iterator := k.GetAllDenomsIterator(ctx) + defer iterator.Close() + + for ; iterator.Valid(); iterator.Next() { + denom := string(iterator.Value()) + + authorityMetadata := k.GetAuthorityMetadata(ctx, denom) + genDenoms = append(genDenoms, types.GenesisDenom{ + Denom: denom, + AuthorityMetadata: authorityMetadata, + }) + } + + return &types.GenesisState{ + FactoryDenoms: genDenoms, + Params: k.GetParams(ctx), + } +} diff --git a/x/tokenfactory/keeper/genesis_test.go b/x/tokenfactory/keeper/genesis_test.go new file mode 100644 index 0000000000..9113b704ba --- /dev/null +++ b/x/tokenfactory/keeper/genesis_test.go @@ -0,0 +1,137 @@ +package keeper_test + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + "github.com/desmos-labs/desmos/v5/x/tokenfactory/types" + "github.com/golang/mock/gomock" +) + +func (suite *KeeperTestSuite) TestKeeper_ExportGenesis() { + testCases := []struct { + name string + store func(ctx sdk.Context) + expGenesis *types.GenesisState + }{ + { + name: "genesis denoms are exported properly", + store: func(ctx sdk.Context) { + suite.k.AddDenomFromCreator(ctx, + "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", + "factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/bitcoin") + + suite.k.SetAuthorityMetadata(ctx, + "factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/bitcoin", + types.DenomAuthorityMetadata{Admin: "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47"}) + + suite.k.AddDenomFromCreator(ctx, "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", "factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/litecoin") + + suite.k.SetAuthorityMetadata(ctx, + "factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/litecoin", + types.DenomAuthorityMetadata{Admin: "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47"}) + }, + expGenesis: &types.GenesisState{ + FactoryDenoms: []types.GenesisDenom{ + {Denom: "factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/bitcoin", AuthorityMetadata: types.DenomAuthorityMetadata{Admin: "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47"}}, + {Denom: "factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/litecoin", AuthorityMetadata: types.DenomAuthorityMetadata{Admin: "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47"}}, + }, + }, + }, + { + name: "params are exported properly", + store: func(ctx sdk.Context) { + suite.k.SetParams(ctx, types.DefaultParams()) + }, + expGenesis: &types.GenesisState{ + FactoryDenoms: []types.GenesisDenom{}, + Params: types.DefaultParams(), + }, + }, + } + + for _, tc := range testCases { + tc := tc + suite.Run(tc.name, func() { + ctx, _ := suite.ctx.CacheContext() + if tc.store != nil { + tc.store(ctx) + } + + genesis := suite.k.ExportGenesis(ctx) + suite.Require().Equal(tc.expGenesis, genesis) + }) + } +} + +func (suite *KeeperTestSuite) TestKeeper_InitGenesis() { + testCases := []struct { + name string + setup func() + data types.GenesisState + check func(ctx sdk.Context) + }{ + { + name: "denoms are imported properly", + setup: func() { + suite.ak.EXPECT().GetModuleAccount(gomock.Any(), types.ModuleName) + + suite.bk.EXPECT(). + GetDenomMetaData(gomock.Any(), "factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/bitcoin"). + Return(banktypes.Metadata{}, true) + + suite.bk.EXPECT(). + GetDenomMetaData(gomock.Any(), "factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/litecoin"). + Return(banktypes.Metadata{}, true) + }, + data: types.GenesisState{ + FactoryDenoms: []types.GenesisDenom{ + {Denom: "factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/bitcoin", AuthorityMetadata: types.DenomAuthorityMetadata{Admin: "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47"}}, + {Denom: "factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/litecoin", AuthorityMetadata: types.DenomAuthorityMetadata{Admin: "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47"}}, + }, + }, + check: func(ctx sdk.Context) { + suite.Require().Equal( + []string{"factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/bitcoin", "factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/litecoin"}, + suite.k.GetDenomsFromCreator(ctx, "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47"), + ) + + suite.Require().Equal( + types.DenomAuthorityMetadata{Admin: "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47"}, + suite.k.GetAuthorityMetadata(ctx, "factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/bitcoin"), + ) + + suite.Require().Equal( + types.DenomAuthorityMetadata{Admin: "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47"}, + suite.k.GetAuthorityMetadata(ctx, "factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/litecoin"), + ) + }, + }, + { + name: "params are imported properly", + setup: func() { + suite.ak.EXPECT().GetModuleAccount(gomock.Any(), types.ModuleName) + }, + data: types.GenesisState{ + Params: types.DefaultParams(), + }, + check: func(ctx sdk.Context) { + suite.Require().Equal(types.DefaultParams(), suite.k.GetParams(ctx)) + }, + }, + } + + for _, tc := range testCases { + tc := tc + suite.Run(tc.name, func() { + ctx, _ := suite.ctx.CacheContext() + if tc.setup != nil { + tc.setup() + } + + suite.k.InitGenesis(ctx, tc.data) + if tc.check != nil { + tc.check(ctx) + } + }) + } +} diff --git a/x/tokenfactory/keeper/gprc_query.go b/x/tokenfactory/keeper/gprc_query.go new file mode 100644 index 0000000000..ad69a1d2b8 --- /dev/null +++ b/x/tokenfactory/keeper/gprc_query.go @@ -0,0 +1,30 @@ +package keeper + +import ( + "context" + + sdk "github.com/cosmos/cosmos-sdk/types" + + subspacestypes "github.com/desmos-labs/desmos/v5/x/subspaces/types" + "github.com/desmos-labs/desmos/v5/x/tokenfactory/types" +) + +var _ types.QueryServer = Keeper{} + +// Params implements the Query/Params gRPC method +func (k Keeper) Params(ctx context.Context, request *types.QueryParamsRequest) (*types.QueryParamsResponse, error) { + sdkCtx := sdk.UnwrapSDKContext(ctx) + params := k.GetParams(sdkCtx) + + return &types.QueryParamsResponse{Params: params}, nil +} + +// SubspaceDenoms implements the Query/SubspaceDenoms gRPC method +func (k Keeper) SubspaceDenoms(ctx context.Context, request *types.QuerySubspaceDenomsRequest) (*types.QuerySubspaceDenomsResponse, error) { + sdkCtx := sdk.UnwrapSDKContext(ctx) + + treasury := subspacestypes.GetTreasuryAddress(request.SubspaceId) + denoms := k.GetDenomsFromCreator(sdkCtx, treasury.String()) + + return &types.QuerySubspaceDenomsResponse{Denoms: denoms}, nil +} diff --git a/x/tokenfactory/keeper/grpc_query_test.go b/x/tokenfactory/keeper/grpc_query_test.go new file mode 100644 index 0000000000..3b659e4c22 --- /dev/null +++ b/x/tokenfactory/keeper/grpc_query_test.go @@ -0,0 +1,85 @@ +package keeper_test + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + + subspacestypes "github.com/desmos-labs/desmos/v5/x/subspaces/types" + "github.com/desmos-labs/desmos/v5/x/tokenfactory/types" +) + +func (suite *KeeperTestSuite) TestQueryServer_Params() { + testCases := []struct { + name string + store func(ctx sdk.Context) + request *types.QueryParamsRequest + shouldErr bool + expParams types.Params + }{ + { + name: "params are returned properly", + store: func(ctx sdk.Context) { + suite.k.SetParams(ctx, types.DefaultParams()) + }, + request: types.NewQueryParamsRequest(), + shouldErr: false, + expParams: types.DefaultParams(), + }, + } + + for _, tc := range testCases { + tc := tc + suite.Run(tc.name, func() { + ctx, _ := suite.ctx.CacheContext() + if tc.store != nil { + tc.store(ctx) + } + + res, err := suite.k.Params(sdk.WrapSDKContext(ctx), tc.request) + if tc.shouldErr { + suite.Require().Error(err) + } else { + suite.Require().NoError(err) + suite.Require().Equal(tc.expParams, res.Params) + } + }) + } +} + +func (suite *KeeperTestSuite) TestQueryServer_SubspaceDenoms() { + testCases := []struct { + name string + store func(ctx sdk.Context) + request *types.QuerySubspaceDenomsRequest + shouldErr bool + expDenoms []string + }{ + { + name: "denoms are returned properly", + store: func(ctx sdk.Context) { + suite.k.AddDenomFromCreator(ctx, subspacestypes.GetTreasuryAddress(1).String(), "bitcoin") + suite.k.AddDenomFromCreator(ctx, subspacestypes.GetTreasuryAddress(1).String(), "minttoken") + }, + request: types.NewQuerySubspaceDenomsRequest(1), + shouldErr: false, + expDenoms: []string{"bitcoin", "minttoken"}, + }, + } + + for _, tc := range testCases { + tc := tc + suite.Run(tc.name, func() { + ctx, _ := suite.ctx.CacheContext() + if tc.store != nil { + tc.store(ctx) + } + + res, err := suite.k.SubspaceDenoms(sdk.WrapSDKContext(ctx), tc.request) + if tc.shouldErr { + suite.Require().Error(err) + } else { + suite.Require().NoError(err) + suite.Require().Equal(tc.expDenoms, res.Denoms) + } + }) + } +} diff --git a/x/tokenfactory/keeper/keeper.go b/x/tokenfactory/keeper/keeper.go new file mode 100644 index 0000000000..2c6baa4633 --- /dev/null +++ b/x/tokenfactory/keeper/keeper.go @@ -0,0 +1,76 @@ +package keeper + +import ( + "github.com/cometbft/cometbft/libs/log" + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/store/prefix" + storetypes "github.com/cosmos/cosmos-sdk/store/types" + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/desmos-labs/desmos/v5/x/tokenfactory/types" +) + +type Keeper struct { + storeKey storetypes.StoreKey + cdc codec.BinaryCodec + + sk types.SubspacesKeeper + ak types.AccountKeeper + bk types.BankKeeper + + // the address capable of executing a MsgUpdateParams message. Typically, this + // should be the x/gov module account. + authority string +} + +// NewKeeper returns a new instance of the x/tokenfactory keeper +func NewKeeper( + storeKey storetypes.StoreKey, + cdc codec.BinaryCodec, + sk types.SubspacesKeeper, + ak types.AccountKeeper, + bk types.BankKeeper, + authority string, +) Keeper { + return Keeper{ + storeKey: storeKey, + cdc: cdc, + + sk: sk, + ak: ak, + bk: bk, + + authority: authority, + } +} + +// Logger returns a logger for the x/tokenfactory module +func (k Keeper) Logger(ctx sdk.Context) log.Logger { + return ctx.Logger().With("module", "x/"+types.ModuleName) +} + +// createModuleAccount creates a module account with minting and burning capabilities +// This account isn't intended to store any coins, +// it purely mints and burns them on behalf of the admin of respective denoms, +// and sends to the relevant address. +func (k Keeper) createModuleAccount(ctx sdk.Context) { + k.ak.GetModuleAccount(ctx, types.ModuleName) +} + +// GetDenomPrefixStore returns the substore for a specific denom +func (k Keeper) GetDenomPrefixStore(ctx sdk.Context, denom string) sdk.KVStore { + store := ctx.KVStore(k.storeKey) + return prefix.NewStore(store, types.GetDenomPrefixStore(denom)) +} + +// GetCreatorPrefixStore returns the substore for a specific creator address +func (k Keeper) GetCreatorPrefixStore(ctx sdk.Context, creator string) sdk.KVStore { + store := ctx.KVStore(k.storeKey) + return prefix.NewStore(store, types.GetCreatorPrefix(creator)) +} + +// GetCreatorsPrefixStore returns the substore that contains a list of creators +func (k Keeper) GetCreatorsPrefixStore(ctx sdk.Context) sdk.KVStore { + store := ctx.KVStore(k.storeKey) + return prefix.NewStore(store, types.GetCreatorsPrefix()) +} diff --git a/x/tokenfactory/keeper/msg_server.go b/x/tokenfactory/keeper/msg_server.go new file mode 100644 index 0000000000..4eddbea576 --- /dev/null +++ b/x/tokenfactory/keeper/msg_server.go @@ -0,0 +1,195 @@ +package keeper + +import ( + "context" + "fmt" + + "cosmossdk.io/errors" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" + + subspacestypes "github.com/desmos-labs/desmos/v5/x/subspaces/types" + "github.com/desmos-labs/desmos/v5/x/tokenfactory/types" +) + +type msgServer struct { + Keeper +} + +// NewMsgServerImpl returns an implementation of the stored MsgServer interface for the provided keeper +func NewMsgServerImpl(keeper Keeper) types.MsgServer { + return &msgServer{Keeper: keeper} +} + +// CreateDenom defines a rpc method for MsgCreateDenom +func (k msgServer) CreateDenom(goCtx context.Context, msg *types.MsgCreateDenom) (*types.MsgCreateDenomResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + + // Check if the subspace exists + subspace, exists := k.sk.GetSubspace(ctx, msg.SubspaceID) + if !exists { + return nil, errors.Wrapf(sdkerrors.ErrInvalidRequest, "subspace with id %d not found", msg.SubspaceID) + } + + // Check the permission to manage the subspace tokens + if !k.sk.HasPermission(ctx, msg.SubspaceID, subspacestypes.RootSectionID, msg.Sender, types.PermissionManageSubspaceTokens) { + return nil, errors.Wrap(subspacestypes.ErrPermissionDenied, "you cannot manage the subspace tokens inside this subspace") + } + + denom, err := k.Keeper.CreateDenom(ctx, subspace.Treasury, msg.Subdenom) + if err != nil { + return nil, err + } + + ctx.EventManager().EmitEvents(sdk.Events{ + sdk.NewEvent( + sdk.EventTypeMessage, + sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), + sdk.NewAttribute(sdk.AttributeKeyAction, sdk.MsgTypeURL(msg)), + sdk.NewAttribute(sdk.AttributeKeySender, msg.Sender), + ), + sdk.NewEvent( + types.EventTypeCreateDenom, + sdk.NewAttribute(types.AttributeKeySubspaceID, fmt.Sprintf("%d", msg.SubspaceID)), + sdk.NewAttribute(types.AttributeCreator, msg.Sender), + sdk.NewAttribute(types.AttributeNewTokenDenom, denom), + ), + }) + + return &types.MsgCreateDenomResponse{ + NewTokenDenom: denom, + }, nil +} + +// Mint defines a rpc method for MsgMint +func (k msgServer) Mint(goCtx context.Context, msg *types.MsgMint) (*types.MsgMintResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + + // Check if the subspace exists + subspace, exists := k.sk.GetSubspace(ctx, msg.SubspaceID) + if !exists { + return nil, errors.Wrapf(sdkerrors.ErrInvalidRequest, "subspace with id %d not found", msg.SubspaceID) + } + + err := k.ValidateManageTokenPermission(ctx, subspace, msg.Sender, msg.Amount.Denom) + if err != nil { + return nil, err + } + + err = k.mintTo(ctx, msg.Amount, subspace.Treasury) + if err != nil { + return nil, err + } + + ctx.EventManager().EmitEvents(sdk.Events{ + sdk.NewEvent( + sdk.EventTypeMessage, + sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), + sdk.NewAttribute(sdk.AttributeKeyAction, sdk.MsgTypeURL(msg)), + sdk.NewAttribute(sdk.AttributeKeySender, msg.Sender), + ), + sdk.NewEvent( + types.EventTypeMint, + sdk.NewAttribute(types.AttributeKeySubspaceID, fmt.Sprintf("%d", msg.SubspaceID)), + sdk.NewAttribute(types.AttributeMintToAddress, subspace.Treasury), + sdk.NewAttribute(types.AttributeAmount, msg.Amount.String()), + ), + }) + + return &types.MsgMintResponse{}, nil +} + +// Burn defines a rpc method for MsgBurn +func (k msgServer) Burn(goCtx context.Context, msg *types.MsgBurn) (*types.MsgBurnResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + + // Check if the subspace exists + subspace, exists := k.sk.GetSubspace(ctx, msg.SubspaceID) + if !exists { + return nil, errors.Wrapf(sdkerrors.ErrInvalidRequest, "subspace with id %d not found", msg.SubspaceID) + } + + err := k.ValidateManageTokenPermission(ctx, subspace, msg.Sender, msg.Amount.Denom) + if err != nil { + return nil, err + } + + err = k.burnFrom(ctx, msg.Amount, subspace.Treasury) + if err != nil { + return nil, err + } + + ctx.EventManager().EmitEvents(sdk.Events{ + sdk.NewEvent( + sdk.EventTypeMessage, + sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), + sdk.NewAttribute(sdk.AttributeKeyAction, sdk.MsgTypeURL(msg)), + sdk.NewAttribute(sdk.AttributeKeySender, msg.Sender), + ), + sdk.NewEvent( + types.EventTypeBurn, + sdk.NewAttribute(types.AttributeKeySubspaceID, fmt.Sprintf("%d", msg.SubspaceID)), + sdk.NewAttribute(types.AttributeBurnFromAddress, subspace.Treasury), + sdk.NewAttribute(types.AttributeAmount, msg.Amount.String()), + ), + }) + + return &types.MsgBurnResponse{}, nil +} + +// SetDenomMetadata defines a rpc method for MsgSetDenomMetadata +func (k msgServer) SetDenomMetadata(goCtx context.Context, msg *types.MsgSetDenomMetadata) (*types.MsgSetDenomMetadataResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + + // Check if the subspace exists + subspace, exists := k.sk.GetSubspace(ctx, msg.SubspaceID) + if !exists { + return nil, errors.Wrapf(sdkerrors.ErrInvalidRequest, "subspace with id %d not found", msg.SubspaceID) + } + + err := k.ValidateManageTokenPermission(ctx, subspace, msg.Sender, msg.Metadata.Base) + if err != nil { + return nil, err + } + + k.bk.SetDenomMetaData(ctx, msg.Metadata) + + ctx.EventManager().EmitEvents(sdk.Events{ + sdk.NewEvent( + sdk.EventTypeMessage, + sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), + sdk.NewAttribute(sdk.AttributeKeyAction, sdk.MsgTypeURL(msg)), + sdk.NewAttribute(sdk.AttributeKeySender, msg.Sender), + ), + sdk.NewEvent( + types.ActionSetDenomMetadata, + sdk.NewAttribute(types.AttributeKeySubspaceID, fmt.Sprintf("%d", msg.SubspaceID)), + sdk.NewAttribute(types.AttributeDenom, msg.Metadata.Base), + sdk.NewAttribute(types.AttributeDenomMetadata, msg.Metadata.String()), + ), + }) + + return &types.MsgSetDenomMetadataResponse{}, nil +} + +// UpdateParams defines a rpc method for MsgUpdateParams +func (k msgServer) UpdateParams(goCtx context.Context, msg *types.MsgUpdateParams) (*types.MsgUpdateParamsResponse, error) { + if k.authority != msg.Authority { + return nil, errors.Wrapf(govtypes.ErrInvalidSigner, "invalid authority; expected %s, got %s", k.authority, msg.Authority) + } + + ctx := sdk.UnwrapSDKContext(goCtx) + k.SetParams(ctx, msg.Params) + + ctx.EventManager().EmitEvents(sdk.Events{ + sdk.NewEvent( + sdk.EventTypeMessage, + sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), + sdk.NewAttribute(sdk.AttributeKeyAction, sdk.MsgTypeURL(msg)), + sdk.NewAttribute(sdk.AttributeKeySender, msg.Authority), + ), + }) + + return &types.MsgUpdateParamsResponse{}, nil +} diff --git a/x/tokenfactory/keeper/msg_server_test.go b/x/tokenfactory/keeper/msg_server_test.go new file mode 100644 index 0000000000..54cdf7971f --- /dev/null +++ b/x/tokenfactory/keeper/msg_server_test.go @@ -0,0 +1,966 @@ +package keeper_test + +import ( + "fmt" + "time" + + sdk "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + + subspacestypes "github.com/desmos-labs/desmos/v5/x/subspaces/types" + + "github.com/desmos-labs/desmos/v5/x/tokenfactory/keeper" + "github.com/desmos-labs/desmos/v5/x/tokenfactory/types" + "github.com/golang/mock/gomock" +) + +func (suite *KeeperTestSuite) TestMsgServer_CreateDenom() { + testCases := []struct { + name string + setup func() + msg *types.MsgCreateDenom + shouldErr bool + expResponse *types.MsgCreateDenomResponse + expEvents sdk.Events + check func(ctx sdk.Context) + }{ + { + name: "subspace does not exist returns error", + setup: func() { + suite.sk.EXPECT(). + GetSubspace(gomock.Any(), uint64(1)). + Return(subspacestypes.Subspace{}, false) + }, + msg: types.NewMsgCreateDenom( + 1, + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + "uminttoken", + ), + shouldErr: true, + }, + { + name: "no permissions returns error", + setup: func() { + suite.sk.EXPECT(). + GetSubspace(gomock.Any(), uint64(1)). + Return(subspacestypes.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + nil, + ), true) + + suite.sk.EXPECT(). + HasPermission( + gomock.Any(), + uint64(1), + uint32(subspacestypes.RootSectionID), + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + types.PermissionManageSubspaceTokens, + ). + Return(false) + }, + msg: types.NewMsgCreateDenom( + 1, + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + "uminttoken", + ), + shouldErr: true, + }, + { + name: "create denom failed returns error", + setup: func() { + suite.sk.EXPECT(). + GetSubspace(gomock.Any(), uint64(1)). + Return(subspacestypes.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + nil, + ), true) + + suite.sk.EXPECT(). + HasPermission( + gomock.Any(), + uint64(1), + uint32(subspacestypes.RootSectionID), + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + types.PermissionManageSubspaceTokens, + ). + Return(true) + + suite.bk.EXPECT(). + HasSupply(gomock.Any(), "uminttoken"). + Return(true) + }, + msg: types.NewMsgCreateDenom( + 1, + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + "uminttoken", + ), + shouldErr: true, + }, + { + name: "valid request returns no error", + setup: func() { + suite.sk.EXPECT(). + GetSubspace(gomock.Any(), uint64(1)). + Return(subspacestypes.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + nil, + ), true) + + suite.sk.EXPECT(). + HasPermission( + gomock.Any(), + uint64(1), + uint32(subspacestypes.RootSectionID), + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + types.PermissionManageSubspaceTokens, + ). + Return(true) + + suite.bk.EXPECT(). + HasSupply(gomock.Any(), "uminttoken"). + Return(false) + + suite.bk.EXPECT(). + GetDenomMetaData(gomock.Any(), "factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/uminttoken"). + Return(banktypes.Metadata{}, false). + Times(2) + + suite.bk.EXPECT(). + SetDenomMetaData(gomock.Any(), banktypes.Metadata{ + DenomUnits: []*banktypes.DenomUnit{{ + Denom: "factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/uminttoken", + Exponent: 0, + }}, + Base: "factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/uminttoken", + }) + }, + msg: types.NewMsgCreateDenom( + 1, + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + "uminttoken", + ), + expResponse: &types.MsgCreateDenomResponse{ + NewTokenDenom: "factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/uminttoken", + }, + expEvents: sdk.Events{ + sdk.NewEvent( + sdk.EventTypeMessage, + sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), + sdk.NewAttribute(sdk.AttributeKeyAction, sdk.MsgTypeURL(&types.MsgCreateDenom{})), + sdk.NewAttribute(sdk.AttributeKeySender, "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69"), + ), + sdk.NewEvent( + types.EventTypeCreateDenom, + sdk.NewAttribute(types.AttributeKeySubspaceID, "1"), + sdk.NewAttribute(types.AttributeCreator, "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69"), + sdk.NewAttribute(types.AttributeNewTokenDenom, "factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/uminttoken"), + ), + }, + check: func(ctx sdk.Context) { + suite.Require().Equal( + types.DenomAuthorityMetadata{Admin: "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47"}, + suite.k.GetAuthorityMetadata(ctx, "factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/uminttoken"), + ) + suite.Require().Equal( + []string{"factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/uminttoken"}, + suite.k.GetDenomsFromCreator(ctx, "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47"), + ) + }, + }, + } + + for _, tc := range testCases { + tc := tc + suite.Run(tc.name, func() { + ctx, _ := suite.ctx.CacheContext() + if tc.setup != nil { + tc.setup() + } + + msgServer := keeper.NewMsgServerImpl(suite.k) + res, err := msgServer.CreateDenom(sdk.WrapSDKContext(ctx), tc.msg) + if tc.shouldErr { + suite.Require().Error(err) + } else { + suite.Require().NoError(err) + suite.Require().Equal(tc.expResponse, res) + suite.Require().Equal(tc.expEvents, ctx.EventManager().Events()) + if tc.check != nil { + tc.check(ctx) + } + } + }) + } +} + +func (suite *KeeperTestSuite) TestMsgServer_Mint() { + testCases := []struct { + name string + setup func() + store func(ctx sdk.Context) + msg *types.MsgMint + shouldErr bool + expResponse *types.MsgMintResponse + expEvents sdk.Events + }{ + { + name: "subspace does not exist returns error", + setup: func() { + suite.sk.EXPECT(). + GetSubspace(gomock.Any(), uint64(1)). + Return(subspacestypes.Subspace{}, false) + }, + msg: types.NewMsgMint( + 1, + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + sdk.NewCoin("factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/uminttoken", sdk.NewInt(100)), + ), + shouldErr: true, + }, + { + name: "no permissions returns error", + setup: func() { + suite.sk.EXPECT(). + GetSubspace(gomock.Any(), uint64(1)). + Return(subspacestypes.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + nil, + ), true) + + suite.sk.EXPECT(). + HasPermission( + gomock.Any(), + uint64(1), + uint32(subspacestypes.RootSectionID), + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + types.PermissionManageSubspaceTokens, + ). + Return(false) + }, + msg: types.NewMsgMint( + 1, + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + sdk.NewCoin("factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/uminttoken", sdk.NewInt(100)), + ), + shouldErr: true, + }, + { + name: "mint failed returns error - bank mint coins failed", + setup: func() { + suite.sk.EXPECT(). + GetSubspace(gomock.Any(), uint64(1)). + Return(subspacestypes.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + nil, + ), true) + + suite.sk.EXPECT(). + HasPermission( + gomock.Any(), + uint64(1), + uint32(subspacestypes.RootSectionID), + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + types.PermissionManageSubspaceTokens, + ). + Return(true) + + suite.bk.EXPECT(). + GetDenomMetaData(gomock.Any(), "factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/uminttoken"). + Return(banktypes.Metadata{}, true) + + suite.bk.EXPECT(). + MintCoins( + gomock.Any(), + types.ModuleName, + sdk.NewCoins(sdk.NewCoin("factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/uminttoken", sdk.NewInt(100))), + ). + Return(fmt.Errorf("error")) + }, + store: func(ctx sdk.Context) { + suite.k.SetAuthorityMetadata(ctx, + "factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/uminttoken", + types.DenomAuthorityMetadata{Admin: "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47"}) + }, + msg: types.NewMsgMint( + 1, + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + sdk.NewCoin("factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/uminttoken", sdk.NewInt(100)), + ), + shouldErr: true, + }, + { + name: "mint failed returns error - module send coins to treasury failed", + setup: func() { + suite.sk.EXPECT(). + GetSubspace(gomock.Any(), uint64(1)). + Return(subspacestypes.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + nil, + ), true) + + suite.sk.EXPECT(). + HasPermission( + gomock.Any(), + uint64(1), + uint32(subspacestypes.RootSectionID), + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + types.PermissionManageSubspaceTokens, + ). + Return(true) + + suite.bk.EXPECT(). + GetDenomMetaData(gomock.Any(), "factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/uminttoken"). + Return(banktypes.Metadata{}, true) + + suite.bk.EXPECT(). + MintCoins( + gomock.Any(), + types.ModuleName, + sdk.NewCoins(sdk.NewCoin("factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/uminttoken", sdk.NewInt(100))), + ). + Return(nil) + + suite.bk.EXPECT(). + SendCoinsFromModuleToAccount( + gomock.Any(), + types.ModuleName, + sdk.MustAccAddressFromBech32("cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47"), + sdk.NewCoins(sdk.NewCoin("factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/uminttoken", sdk.NewInt(100))), + ). + Return(fmt.Errorf("error")) + }, + store: func(ctx sdk.Context) { + suite.k.SetAuthorityMetadata(ctx, + "factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/uminttoken", + types.DenomAuthorityMetadata{Admin: "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47"}) + }, + msg: types.NewMsgMint( + 1, + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + sdk.NewCoin("factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/uminttoken", sdk.NewInt(100)), + ), + shouldErr: true, + }, + { + name: "valid request returns no error", + setup: func() { + suite.sk.EXPECT(). + GetSubspace(gomock.Any(), uint64(1)). + Return(subspacestypes.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + nil, + ), true) + + suite.sk.EXPECT(). + HasPermission( + gomock.Any(), + uint64(1), + uint32(subspacestypes.RootSectionID), + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + types.PermissionManageSubspaceTokens, + ). + Return(true) + + suite.bk.EXPECT(). + GetDenomMetaData(gomock.Any(), "factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/uminttoken"). + Return(banktypes.Metadata{}, true) + + suite.bk.EXPECT(). + MintCoins( + gomock.Any(), + types.ModuleName, + sdk.NewCoins(sdk.NewCoin("factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/uminttoken", sdk.NewInt(100))), + ). + Return(nil) + + suite.bk.EXPECT(). + SendCoinsFromModuleToAccount( + gomock.Any(), + types.ModuleName, + sdk.MustAccAddressFromBech32("cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47"), + sdk.NewCoins(sdk.NewCoin("factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/uminttoken", sdk.NewInt(100))), + ). + Return(nil) + }, + store: func(ctx sdk.Context) { + suite.k.SetAuthorityMetadata(ctx, + "factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/uminttoken", + types.DenomAuthorityMetadata{Admin: "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47"}) + }, + msg: types.NewMsgMint( + 1, + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + sdk.NewCoin("factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/uminttoken", sdk.NewInt(100)), + ), + expResponse: &types.MsgMintResponse{}, + expEvents: sdk.Events{ + sdk.NewEvent( + sdk.EventTypeMessage, + sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), + sdk.NewAttribute(sdk.AttributeKeyAction, sdk.MsgTypeURL(&types.MsgMint{})), + sdk.NewAttribute(sdk.AttributeKeySender, "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69"), + ), + sdk.NewEvent( + types.EventTypeMint, + sdk.NewAttribute(types.AttributeKeySubspaceID, "1"), + sdk.NewAttribute(types.AttributeMintToAddress, "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47"), + sdk.NewAttribute(types.AttributeAmount, sdk.NewCoin("factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/uminttoken", sdk.NewInt(100)).String()), + ), + }, + }, + } + + for _, tc := range testCases { + tc := tc + suite.Run(tc.name, func() { + ctx, _ := suite.ctx.CacheContext() + if tc.setup != nil { + tc.setup() + } + if tc.store != nil { + tc.store(ctx) + } + + msgServer := keeper.NewMsgServerImpl(suite.k) + res, err := msgServer.Mint(sdk.WrapSDKContext(ctx), tc.msg) + if tc.shouldErr { + suite.Require().Error(err) + } else { + suite.Require().NoError(err) + suite.Require().Equal(tc.expResponse, res) + suite.Require().Equal(tc.expEvents, ctx.EventManager().Events()) + } + }) + } +} + +func (suite *KeeperTestSuite) TestMsgServer_Burn() { + testCases := []struct { + name string + setup func() + store func(ctx sdk.Context) + msg *types.MsgBurn + shouldErr bool + expResponse *types.MsgBurnResponse + expEvents sdk.Events + }{ + { + name: "subspace does not exist returns error", + setup: func() { + suite.sk.EXPECT(). + GetSubspace(gomock.Any(), uint64(1)). + Return(subspacestypes.Subspace{}, false) + }, + msg: types.NewMsgBurn( + 1, + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + sdk.NewCoin("factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/uminttoken", sdk.NewInt(100)), + ), + shouldErr: true, + }, + { + name: "no permissions returns error", + setup: func() { + suite.sk.EXPECT(). + GetSubspace(gomock.Any(), uint64(1)). + Return(subspacestypes.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + nil, + ), true) + + suite.sk.EXPECT(). + HasPermission( + gomock.Any(), + uint64(1), + uint32(subspacestypes.RootSectionID), + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + types.PermissionManageSubspaceTokens, + ). + Return(false) + }, + msg: types.NewMsgBurn( + 1, + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + sdk.NewCoin("factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/uminttoken", sdk.NewInt(100)), + ), + shouldErr: true, + }, + { + name: "burn failed returns error - send coins to module failed", + setup: func() { + suite.sk.EXPECT(). + GetSubspace(gomock.Any(), uint64(1)). + Return(subspacestypes.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + nil, + ), true) + + suite.sk.EXPECT(). + HasPermission( + gomock.Any(), + uint64(1), + uint32(subspacestypes.RootSectionID), + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + types.PermissionManageSubspaceTokens, + ). + Return(true) + + suite.bk.EXPECT(). + GetDenomMetaData(gomock.Any(), "factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/uminttoken"). + Return(banktypes.Metadata{}, true) + + suite.bk.EXPECT(). + SendCoinsFromAccountToModule( + gomock.Any(), + sdk.MustAccAddressFromBech32("cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47"), + types.ModuleName, + sdk.NewCoins(sdk.NewCoin("factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/uminttoken", sdk.NewInt(100))), + ). + Return(fmt.Errorf("error")) + }, + store: func(ctx sdk.Context) { + suite.k.SetAuthorityMetadata(ctx, + "factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/uminttoken", + types.DenomAuthorityMetadata{Admin: "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47"}) + }, + msg: types.NewMsgBurn( + 1, + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + sdk.NewCoin("factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/uminttoken", sdk.NewInt(100)), + ), + shouldErr: true, + }, + { + name: "burn failed returns error - bank burn failed", + setup: func() { + suite.sk.EXPECT(). + GetSubspace(gomock.Any(), uint64(1)). + Return(subspacestypes.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + nil, + ), true) + + suite.sk.EXPECT(). + HasPermission( + gomock.Any(), + uint64(1), + uint32(subspacestypes.RootSectionID), + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + types.PermissionManageSubspaceTokens, + ). + Return(true) + + suite.bk.EXPECT(). + GetDenomMetaData(gomock.Any(), "factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/uminttoken"). + Return(banktypes.Metadata{}, true) + + suite.bk.EXPECT(). + SendCoinsFromAccountToModule( + gomock.Any(), + sdk.MustAccAddressFromBech32("cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47"), + types.ModuleName, + sdk.NewCoins(sdk.NewCoin("factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/uminttoken", sdk.NewInt(100))), + ). + Return(nil) + + suite.bk.EXPECT(). + BurnCoins( + gomock.Any(), + types.ModuleName, + sdk.NewCoins(sdk.NewCoin("factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/uminttoken", sdk.NewInt(100))), + ). + Return(fmt.Errorf("error")) + }, + store: func(ctx sdk.Context) { + suite.k.SetAuthorityMetadata(ctx, + "factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/uminttoken", + types.DenomAuthorityMetadata{Admin: "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47"}) + }, + msg: types.NewMsgBurn( + 1, + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + sdk.NewCoin("factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/uminttoken", sdk.NewInt(100)), + ), + shouldErr: true, + }, + { + name: "valid request returns no error", + setup: func() { + suite.sk.EXPECT(). + GetSubspace(gomock.Any(), uint64(1)). + Return(subspacestypes.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + nil, + ), true) + + suite.sk.EXPECT(). + HasPermission( + gomock.Any(), + uint64(1), + uint32(subspacestypes.RootSectionID), + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + types.PermissionManageSubspaceTokens, + ). + Return(true) + + suite.bk.EXPECT(). + GetDenomMetaData(gomock.Any(), "factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/uminttoken"). + Return(banktypes.Metadata{}, true) + + suite.bk.EXPECT(). + SendCoinsFromAccountToModule( + gomock.Any(), + sdk.MustAccAddressFromBech32("cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47"), + types.ModuleName, + sdk.NewCoins(sdk.NewCoin("factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/uminttoken", sdk.NewInt(100))), + ). + Return(nil) + + suite.bk.EXPECT(). + BurnCoins( + gomock.Any(), + types.ModuleName, + sdk.NewCoins(sdk.NewCoin("factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/uminttoken", sdk.NewInt(100))), + ). + Return(nil) + }, + store: func(ctx sdk.Context) { + suite.k.SetAuthorityMetadata(ctx, + "factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/uminttoken", + types.DenomAuthorityMetadata{Admin: "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47"}) + }, + msg: types.NewMsgBurn( + 1, + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + sdk.NewCoin("factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/uminttoken", sdk.NewInt(100)), + ), + expResponse: &types.MsgBurnResponse{}, + expEvents: sdk.Events{ + sdk.NewEvent( + sdk.EventTypeMessage, + sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), + sdk.NewAttribute(sdk.AttributeKeyAction, sdk.MsgTypeURL(&types.MsgBurn{})), + sdk.NewAttribute(sdk.AttributeKeySender, "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69"), + ), + sdk.NewEvent( + types.EventTypeBurn, + sdk.NewAttribute(types.AttributeKeySubspaceID, "1"), + sdk.NewAttribute(types.AttributeBurnFromAddress, "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47"), + sdk.NewAttribute(types.AttributeAmount, sdk.NewCoin("factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/uminttoken", sdk.NewInt(100)).String()), + ), + }, + }, + } + + for _, tc := range testCases { + tc := tc + suite.Run(tc.name, func() { + ctx, _ := suite.ctx.CacheContext() + if tc.setup != nil { + tc.setup() + } + if tc.store != nil { + tc.store(ctx) + } + + msgServer := keeper.NewMsgServerImpl(suite.k) + res, err := msgServer.Burn(sdk.WrapSDKContext(ctx), tc.msg) + if tc.shouldErr { + suite.Require().Error(err) + } else { + suite.Require().NoError(err) + suite.Require().Equal(tc.expResponse, res) + suite.Require().Equal(tc.expEvents, ctx.EventManager().Events()) + } + }) + } +} + +func (suite *KeeperTestSuite) TestMsgServer_SetDenomMetadata() { + metadata := banktypes.Metadata{ + Name: "Mint Token", + Symbol: "MTK", + Description: "The custom token of the test subspace.", + DenomUnits: []*banktypes.DenomUnit{ + {Denom: "factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/uminttoken", Exponent: uint32(0), Aliases: nil}, + {Denom: "minttoken", Exponent: uint32(6), Aliases: []string{"minttoken"}}, + }, + Base: "factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/uminttoken", + Display: "minttoken", + } + + testCases := []struct { + name string + setup func() + store func(ctx sdk.Context) + msg *types.MsgSetDenomMetadata + shouldErr bool + expResponse *types.MsgSetDenomMetadataResponse + expEvents sdk.Events + }{ + { + name: "subspace does not exist returns error", + setup: func() { + suite.sk.EXPECT(). + GetSubspace(gomock.Any(), uint64(1)). + Return(subspacestypes.Subspace{}, false) + }, + msg: types.NewMsgSetDenomMetadata( + 1, + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + metadata, + ), + shouldErr: true, + }, + { + name: "no permissions returns error", + setup: func() { + suite.sk.EXPECT(). + GetSubspace(gomock.Any(), uint64(1)). + Return(subspacestypes.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + nil, + ), true) + + suite.sk.EXPECT(). + HasPermission( + gomock.Any(), + uint64(1), + uint32(subspacestypes.RootSectionID), + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + types.PermissionManageSubspaceTokens, + ). + Return(false) + }, + msg: types.NewMsgSetDenomMetadata( + 1, + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + metadata, + ), + shouldErr: true, + }, + { + name: "valid request returns no error", + setup: func() { + suite.sk.EXPECT(). + GetSubspace(gomock.Any(), uint64(1)). + Return(subspacestypes.NewSubspace( + 1, + "Test subspace", + "This is a test subspace", + "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", + "cosmos1m0czrla04f7rp3zg7dsgc4kla54q7pc4xt00l5", + "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", + time.Date(2020, 1, 1, 12, 00, 00, 000, time.UTC), + nil, + ), true) + + suite.sk.EXPECT(). + HasPermission( + gomock.Any(), + uint64(1), + uint32(subspacestypes.RootSectionID), + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + types.PermissionManageSubspaceTokens, + ). + Return(true) + + suite.bk.EXPECT(). + GetDenomMetaData(gomock.Any(), "factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/uminttoken"). + Return(banktypes.Metadata{}, true) + + suite.bk.EXPECT(). + SetDenomMetaData(gomock.Any(), metadata) + }, + store: func(ctx sdk.Context) { + suite.k.SetAuthorityMetadata(ctx, + "factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/uminttoken", + types.DenomAuthorityMetadata{Admin: "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47"}) + }, + msg: types.NewMsgSetDenomMetadata( + 1, + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + metadata, + ), + expResponse: &types.MsgSetDenomMetadataResponse{}, + expEvents: sdk.Events{ + sdk.NewEvent( + sdk.EventTypeMessage, + sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), + sdk.NewAttribute(sdk.AttributeKeyAction, sdk.MsgTypeURL(&types.MsgSetDenomMetadata{})), + sdk.NewAttribute(sdk.AttributeKeySender, "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69"), + ), + sdk.NewEvent( + types.EventTypeSetDenomMetadata, + sdk.NewAttribute(types.AttributeKeySubspaceID, "1"), + sdk.NewAttribute(types.AttributeDenom, metadata.Base), + sdk.NewAttribute(types.AttributeDenomMetadata, metadata.String()), + ), + }, + }, + } + + for _, tc := range testCases { + tc := tc + suite.Run(tc.name, func() { + ctx, _ := suite.ctx.CacheContext() + if tc.setup != nil { + tc.setup() + } + if tc.store != nil { + tc.store(ctx) + } + + msgServer := keeper.NewMsgServerImpl(suite.k) + res, err := msgServer.SetDenomMetadata(sdk.WrapSDKContext(ctx), tc.msg) + if tc.shouldErr { + suite.Require().Error(err) + } else { + suite.Require().NoError(err) + suite.Require().Equal(tc.expResponse, res) + suite.Require().Equal(tc.expEvents, ctx.EventManager().Events()) + } + }) + } +} + +func (suite *KeeperTestSuite) TestMsgServer_UpdateParams() { + testCases := []struct { + name string + setup func() + msg *types.MsgUpdateParams + shouldErr bool + check func(ctx sdk.Context) + expEvents sdk.Events + }{ + { + name: "invalid authority return error", + msg: types.NewMsgUpdateParams( + types.DefaultParams(), + "invalid", + ), + shouldErr: true, + }, + { + name: "set params properly", + msg: types.NewMsgUpdateParams( + types.NewParams(sdk.NewCoins(sdk.NewCoin("test", sdk.NewInt(100)))), + authtypes.NewModuleAddress("gov").String(), + ), + shouldErr: false, + check: func(ctx sdk.Context) { + suite.Require().Equal( + types.NewParams(sdk.NewCoins(sdk.NewCoin("test", sdk.NewInt(100)))), + suite.k.GetParams(ctx), + ) + }, + expEvents: sdk.Events{ + sdk.NewEvent( + sdk.EventTypeMessage, + sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), + sdk.NewAttribute(sdk.AttributeKeyAction, sdk.MsgTypeURL(&types.MsgUpdateParams{})), + sdk.NewAttribute(sdk.AttributeKeySender, "cosmos10d07y265gmmuvt4z0w9aw880jnsr700j6zn9kn"), + ), + }, + }, + } + for _, tc := range testCases { + tc := tc + suite.Run(tc.name, func() { + ctx, _ := suite.ctx.CacheContext() + if tc.setup != nil { + tc.setup() + } + + // Reset any event that might have been emitted during the setup + ctx = ctx.WithEventManager(sdk.NewEventManager()) + + // Run the message + service := keeper.NewMsgServerImpl(suite.k) + _, err := service.UpdateParams(sdk.WrapSDKContext(ctx), tc.msg) + + if tc.shouldErr { + suite.Require().Error(err) + } else { + suite.Require().NoError(err) + suite.Require().Equal(tc.expEvents, ctx.EventManager().Events()) + if tc.check != nil { + tc.check(ctx) + } + } + }) + } +} diff --git a/x/tokenfactory/keeper/params.go b/x/tokenfactory/keeper/params.go new file mode 100644 index 0000000000..cac1080f7e --- /dev/null +++ b/x/tokenfactory/keeper/params.go @@ -0,0 +1,25 @@ +package keeper + +import ( + "github.com/desmos-labs/desmos/v5/x/tokenfactory/types" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// SetParams sets the params on the store +func (k Keeper) SetParams(ctx sdk.Context, params types.Params) { + store := ctx.KVStore(k.storeKey) + bz := k.cdc.MustMarshal(¶ms) + store.Set([]byte(types.ParamsPrefixKey), bz) +} + +// GetParams returns the params from the store +func (k Keeper) GetParams(ctx sdk.Context) (p types.Params) { + store := ctx.KVStore(k.storeKey) + bz := store.Get([]byte(types.ParamsPrefixKey)) + if bz == nil { + return p + } + k.cdc.MustUnmarshal(bz, &p) + return p +} diff --git a/x/tokenfactory/keeper/params_test.go b/x/tokenfactory/keeper/params_test.go new file mode 100644 index 0000000000..036b829187 --- /dev/null +++ b/x/tokenfactory/keeper/params_test.go @@ -0,0 +1,80 @@ +package keeper_test + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/desmos-labs/desmos/v5/x/tokenfactory/types" +) + +func (suite *KeeperTestSuite) TestKeeper_SetParams() { + testCases := []struct { + name string + store func(ctx sdk.Context) + params types.Params + check func(ctx sdk.Context) + }{ + { + name: "default params are saved correctly", + params: types.DefaultParams(), + check: func(ctx sdk.Context) { + stored := suite.k.GetParams(ctx) + suite.Require().Equal(stored, types.DefaultParams()) + }, + }, + { + name: "params are overridden properly", + store: func(ctx sdk.Context) { + suite.k.SetParams(ctx, types.DefaultParams()) + }, + params: types.NewParams(sdk.NewCoins(sdk.NewCoin("udsm", sdk.NewInt(100)))), + check: func(ctx sdk.Context) { + stored := suite.k.GetParams(ctx) + suite.Require().Equal(types.NewParams(sdk.NewCoins(sdk.NewCoin("udsm", sdk.NewInt(100)))), stored) + }, + }, + } + + for _, tc := range testCases { + tc := tc + suite.Run(tc.name, func() { + ctx, _ := suite.ctx.CacheContext() + if tc.store != nil { + tc.store(ctx) + } + + suite.k.SetParams(ctx, tc.params) + if tc.check != nil { + tc.check(ctx) + } + }) + } +} + +func (suite *KeeperTestSuite) TestKeeper_GetParams() { + testCases := []struct { + name string + store func(ctx sdk.Context) + expParams types.Params + }{ + { + name: "params are returned properly", + store: func(ctx sdk.Context) { + suite.k.SetParams(ctx, types.NewParams(sdk.NewCoins(sdk.NewCoin("udsm", sdk.NewInt(100))))) + }, + expParams: types.NewParams(sdk.NewCoins(sdk.NewCoin("udsm", sdk.NewInt(100)))), + }, + } + + for _, tc := range testCases { + tc := tc + suite.Run(tc.name, func() { + ctx, _ := suite.ctx.CacheContext() + if tc.store != nil { + tc.store(ctx) + } + + params := suite.k.GetParams(ctx) + suite.Require().Equal(tc.expParams, params) + }) + } +} diff --git a/x/tokenfactory/keeper/permissions.go b/x/tokenfactory/keeper/permissions.go new file mode 100644 index 0000000000..b781d3735a --- /dev/null +++ b/x/tokenfactory/keeper/permissions.go @@ -0,0 +1,33 @@ +package keeper + +import ( + "cosmossdk.io/errors" + sdk "github.com/cosmos/cosmos-sdk/types" + + subspacestypes "github.com/desmos-labs/desmos/v5/x/subspaces/types" + "github.com/desmos-labs/desmos/v5/x/tokenfactory/types" +) + +// ValidateManageTokenPermission validates the sender has the manage denom permission to the subspace tokens inside the given subspace +func (k Keeper) ValidateManageTokenPermission(ctx sdk.Context, subspace subspacestypes.Subspace, sender string, denom string) error { + + // Check the permission to manage the subspace tokens + if !k.sk.HasPermission(ctx, subspace.ID, subspacestypes.RootSectionID, sender, types.PermissionManageSubspaceTokens) { + return errors.Wrap(subspacestypes.ErrPermissionDenied, "you cannot manage the subspace tokens inside this subspace") + } + + // Check if the denom exists + _, denomExists := k.bk.GetDenomMetaData(ctx, denom) + if !denomExists { + return types.ErrDenomDoesNotExist.Wrapf("denom: %s", denom) + } + + authorityMetadata := k.GetAuthorityMetadata(ctx, denom) + + // Check if the subspace treasury is the admin of the denom + if subspace.Treasury != authorityMetadata.GetAdmin() { + return types.ErrUnauthorized + } + + return nil +} diff --git a/x/tokenfactory/keeper/permissions_test.go b/x/tokenfactory/keeper/permissions_test.go new file mode 100644 index 0000000000..045a5c2c7f --- /dev/null +++ b/x/tokenfactory/keeper/permissions_test.go @@ -0,0 +1,175 @@ +package keeper_test + +import ( + "github.com/golang/mock/gomock" + + sdk "github.com/cosmos/cosmos-sdk/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + + subspacestypes "github.com/desmos-labs/desmos/v5/x/subspaces/types" + "github.com/desmos-labs/desmos/v5/x/tokenfactory/types" +) + +func (suite *KeeperTestSuite) TestKeeper_ValidateSubspaceTokenPermission() { + + testCases := []struct { + name string + setup func() + store func(ctx sdk.Context) + subspace subspacestypes.Subspace + sender string + denom string + shouldErr bool + }{ + { + name: "no permissions returns error", + setup: func() { + suite.sk.EXPECT(). + HasPermission( + gomock.Any(), + uint64(1), + uint32(subspacestypes.RootSectionID), + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + types.PermissionManageSubspaceTokens, + ). + Return(false) + }, + subspace: subspacestypes.Subspace{ + ID: 1, + Treasury: "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", + }, + sender: "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + denom: "factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/uminttoken", + shouldErr: true, + }, + { + name: "denom does not exist returns error", + setup: func() { + suite.sk.EXPECT(). + HasPermission( + gomock.Any(), + uint64(1), + uint32(subspacestypes.RootSectionID), + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + types.PermissionManageSubspaceTokens, + ). + Return(true) + + suite.bk.EXPECT(). + GetDenomMetaData(gomock.Any(), "factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/uminttoken"). + Return(banktypes.Metadata{}, false) + }, + subspace: subspacestypes.Subspace{ + ID: 1, + Treasury: "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", + }, + sender: "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + denom: "factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/uminttoken", + shouldErr: true, + }, + { + name: "denom admin does not match subspace treasury returns error", + setup: func() { + suite.sk.EXPECT(). + HasPermission( + gomock.Any(), + uint64(1), + uint32(subspacestypes.RootSectionID), + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + types.PermissionManageSubspaceTokens, + ). + Return(true) + + suite.bk.EXPECT(). + GetDenomMetaData(gomock.Any(), "factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/uminttoken"). + Return(banktypes.Metadata{}, true) + }, + subspace: subspacestypes.Subspace{ + ID: 1, + Treasury: "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", + }, + sender: "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + denom: "factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/uminttoken", + shouldErr: true, + }, + { + name: "subspace treasury does not match admin returns error", + setup: func() { + suite.sk.EXPECT(). + HasPermission( + gomock.Any(), + uint64(1), + uint32(subspacestypes.RootSectionID), + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + types.PermissionManageSubspaceTokens, + ). + Return(true) + + suite.bk.EXPECT(). + GetDenomMetaData(gomock.Any(), "factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/uminttoken"). + Return(banktypes.Metadata{}, true) + }, + store: func(ctx sdk.Context) { + suite.k.SetAuthorityMetadata(ctx, + "factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/uminttoken", + types.DenomAuthorityMetadata{Admin: ""}) + }, + subspace: subspacestypes.Subspace{ + ID: 1, + Treasury: "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", + }, + sender: "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + denom: "factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/uminttoken", + shouldErr: true, + }, + { + name: "valid request returns no error", + setup: func() { + suite.sk.EXPECT(). + HasPermission( + gomock.Any(), + uint64(1), + uint32(subspacestypes.RootSectionID), + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + types.PermissionManageSubspaceTokens, + ). + Return(true) + + suite.bk.EXPECT(). + GetDenomMetaData(gomock.Any(), "factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/uminttoken"). + Return(banktypes.Metadata{}, true) + }, + store: func(ctx sdk.Context) { + suite.k.SetAuthorityMetadata(ctx, + "factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/uminttoken", + types.DenomAuthorityMetadata{Admin: "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47"}) + }, + subspace: subspacestypes.Subspace{ + ID: 1, + Treasury: "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", + }, + sender: "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + denom: "factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/uminttoken", + }, + } + + for _, tc := range testCases { + tc := tc + suite.Run(tc.name, func() { + ctx, _ := suite.ctx.CacheContext() + if tc.setup != nil { + tc.setup() + } + if tc.store != nil { + tc.store(ctx) + } + + err := suite.k.ValidateManageTokenPermission(ctx, tc.subspace, tc.sender, tc.denom) + if tc.shouldErr { + suite.Require().Error(err) + } else { + suite.Require().NoError(err) + } + }) + } +} diff --git a/x/tokenfactory/module.go b/x/tokenfactory/module.go new file mode 100644 index 0000000000..46d5d4a57e --- /dev/null +++ b/x/tokenfactory/module.go @@ -0,0 +1,272 @@ +package tokenfactory + +import ( + "context" + "encoding/json" + "fmt" + + "cosmossdk.io/core/appmodule" + "cosmossdk.io/depinject" + + abci "github.com/cometbft/cometbft/abci/types" + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/codec" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + storetypes "github.com/cosmos/cosmos-sdk/store/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" + distrkeeper "github.com/cosmos/cosmos-sdk/x/distribution/keeper" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" + paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" + + "github.com/grpc-ecosystem/grpc-gateway/runtime" + "github.com/spf13/cobra" + + modulev1 "github.com/desmos-labs/desmos/v5/api/desmos/tokenfactory/module/v1" + + subspaceskeeper "github.com/desmos-labs/desmos/v5/x/subspaces/keeper" + + "github.com/desmos-labs/desmos/v5/x/tokenfactory/client/cli" + "github.com/desmos-labs/desmos/v5/x/tokenfactory/keeper" + "github.com/desmos-labs/desmos/v5/x/tokenfactory/simulation" + "github.com/desmos-labs/desmos/v5/x/tokenfactory/types" +) + +const ( + consensusVersion = 1 +) + +// type check to ensure the interface is properly implemented +var ( + _ module.AppModule = AppModule{} + _ module.AppModuleBasic = AppModuleBasic{} + _ module.AppModuleSimulation = AppModule{} + _ appmodule.AppModule = AppModule{} + _ depinject.OnePerModuleType = AppModule{} +) + +// AppModuleBasic defines the basic application module used by the tokenfactory module. +type AppModuleBasic struct { + cdc codec.Codec +} + +// Name returns the tokenfactory module's name. +func (AppModuleBasic) Name() string { + return types.ModuleName +} + +// RegisterLegacyAminoCodec registers the tokenfactory module's types for the given codec. +func (AppModuleBasic) RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { + types.RegisterLegacyAminoCodec(cdc) +} + +// DefaultGenesis returns default genesis state as raw bytes for the tokenfactory module. +func (AppModuleBasic) DefaultGenesis(cdc codec.JSONCodec) json.RawMessage { + return cdc.MustMarshalJSON(types.DefaultGenesis()) +} + +// ValidateGenesis performs genesis state validation for the tokenfactory module. +func (AppModuleBasic) ValidateGenesis(cdc codec.JSONCodec, _ client.TxEncodingConfig, bz json.RawMessage) error { + var data types.GenesisState + if err := cdc.UnmarshalJSON(bz, &data); err != nil { + return fmt.Errorf("failed to unmarshal %s genesis state: %w", types.ModuleName, err) + } + return data.Validate() +} + +// RegisterGRPCGatewayRoutes registers the gRPC Gateway routes for the tokenfactory module. +func (AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *runtime.ServeMux) { + types.RegisterQueryHandlerClient(context.Background(), mux, types.NewQueryClient(clientCtx)) +} + +// GetTxCmd returns the root tx command for the tokenfactory module. +func (ab AppModuleBasic) GetTxCmd() *cobra.Command { + return cli.GetTxCmd() +} + +// GetQueryCmd returns the root query command for the tokenfactory module. +func (AppModuleBasic) GetQueryCmd() *cobra.Command { + return cli.GetQueryCmd() +} + +// RegisterInterfaces registers interfaces and implementations of the tokenfactory module. +func (AppModuleBasic) RegisterInterfaces(registry codectypes.InterfaceRegistry) { + types.RegisterInterfaces(registry) +} + +// -------------------------------------------------------------------------------------------------------------------- + +// AppModule implements an application module for the tokenfactory module. +type AppModule struct { + AppModuleBasic + + keeper keeper.Keeper + + sk types.SubspacesKeeper + ak authkeeper.AccountKeeper + bk bankkeeper.Keeper +} + +// RegisterServices registers module services. +func (am AppModule) RegisterServices(cfg module.Configurator) { + types.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(am.keeper)) + types.RegisterQueryServer(cfg.QueryServer(), am.keeper) +} + +// NewAppModule creates a new AppModule Object +func NewAppModule( + cdc codec.Codec, keeper keeper.Keeper, sk types.SubspacesKeeper, + ak authkeeper.AccountKeeper, bk bankkeeper.Keeper, +) AppModule { + return AppModule{ + AppModuleBasic: AppModuleBasic{cdc: cdc}, + keeper: keeper, + sk: sk, + ak: ak, + bk: bk, + } +} + +// Name returns the tokenfactory module's name. +func (AppModule) Name() string { + return types.ModuleName +} + +// RegisterInvariants performs a no-op. +func (am AppModule) RegisterInvariants(ir sdk.InvariantRegistry) {} + +// QuerierRoute returns the tokenfactory module's querier route name. +func (am AppModule) QuerierRoute() string { + return types.QuerierRoute +} + +// InitGenesis performs genesis initialization for the tokenfactory module. +// It returns no validator updates. +func (am AppModule) InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, data json.RawMessage) []abci.ValidatorUpdate { + var genesisState types.GenesisState + cdc.MustUnmarshalJSON(data, &genesisState) + am.keeper.InitGenesis(ctx, genesisState) + return []abci.ValidatorUpdate{} +} + +// ExportGenesis returns the exported genesis state as raw bytes for the +// tokenfactory module. +func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.RawMessage { + gs := am.keeper.ExportGenesis(ctx) + return cdc.MustMarshalJSON(gs) +} + +// ConsensusVersion implements AppModule. +func (AppModule) ConsensusVersion() uint64 { + return consensusVersion +} + +// BeginBlock returns the begin blocker for the tokenfactory module. +func (am AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) { +} + +// EndBlock returns the end blocker for the tokenfactory module. It returns no validator +// updates. +func (am AppModule) EndBlock(_ sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate { + return []abci.ValidatorUpdate{} +} + +// -------------------------------------------------------------------------------------------------------------------- + +// AppModuleSimulation defines the module simulation functions used by the tokenfactory module. +type AppModuleSimulation struct{} + +// GenerateGenesisState creates a randomized GenState of the bank module. +func (AppModule) GenerateGenesisState(simState *module.SimulationState) { + simulation.RandomizeGenState(simState) +} + +// RegisterStoreDecoder performs a no-op. +func (am AppModule) RegisterStoreDecoder(sdr sdk.StoreDecoderRegistry) { + sdr[types.ModuleName] = simulation.NewDecodeStore(am.cdc) +} + +// ProposalMsgs returns msgs used for governance proposals for simulations. +func (AppModule) ProposalMsgs(simState module.SimulationState) []simtypes.WeightedProposalMsg { + return simulation.ProposalMsgs() +} + +// WeightedOperations returns the all the tokenfactory module operations with their respective weights. +func (am AppModule) WeightedOperations(simState module.SimulationState) []simtypes.WeightedOperation { + return simulation.WeightedOperations(simState.AppParams, simState.Cdc, am.keeper, am.sk, am.ak, am.bk) +} + +// -------------------------------------------------------------------------------------------------------------------- + +// App Wiring Setup + +// IsOnePerModuleType implements the depinject.OnePerModuleType interface. +func (am AppModule) IsOnePerModuleType() {} + +// IsAppModule implements the appmodule.AppModule interface. +func (am AppModule) IsAppModule() {} + +func init() { + appmodule.Register( + &modulev1.Module{}, + appmodule.Provide( + ProvideModule, + ), + ) +} + +type ModuleInputs struct { + depinject.In + + Cdc codec.Codec + Config *modulev1.Module + Key *storetypes.KVStoreKey + + SubspacesKeeper *subspaceskeeper.Keeper + AccountKeeper authkeeper.AccountKeeper + BankKeeper bankkeeper.Keeper + CommunityPoolKeeper distrkeeper.Keeper + + LegacySubspace paramtypes.Subspace `optional:"true"` +} + +type ModuleOutputs struct { + depinject.Out + + TokenFactoryKeeper keeper.Keeper + Module appmodule.AppModule +} + +func ProvideModule(in ModuleInputs) ModuleOutputs { + + // default to governance authority if not provided + authority := authtypes.NewModuleAddress(govtypes.ModuleName) + if in.Config.Authority != "" { + authority = authtypes.NewModuleAddressOrBech32Address(in.Config.Authority) + } + + bk := in.BankKeeper.WithMintCoinsRestriction(types.NewTokenFactoryDenomMintCoinsRestriction()) + + k := keeper.NewKeeper( + in.Key, + in.Cdc, + in.SubspacesKeeper, + in.AccountKeeper, + bk, + authority.String(), + ) + + m := NewAppModule( + in.Cdc, + k, + in.SubspacesKeeper, + in.AccountKeeper, + bk, + ) + + return ModuleOutputs{TokenFactoryKeeper: k, Module: m} +} diff --git a/x/tokenfactory/simulation/decoder.go b/x/tokenfactory/simulation/decoder.go new file mode 100644 index 0000000000..b6f3bcf629 --- /dev/null +++ b/x/tokenfactory/simulation/decoder.go @@ -0,0 +1,37 @@ +package simulation + +import ( + "bytes" + "fmt" + + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/types/kv" + + "github.com/desmos-labs/desmos/v5/x/tokenfactory/types" +) + +// NewDecodeStore returns a new decoder that unmarshals the KVPair's Value +// to the corresponding tokenfactory type +func NewDecodeStore(cdc codec.Codec) func(kvA, kvB kv.Pair) string { + return func(kvA, kvB kv.Pair) string { + switch { + case bytes.HasPrefix(kvA.Key, []byte(types.DenomsPrefixKey)): + var metadataA, metadataB types.DenomAuthorityMetadata + cdc.MustUnmarshal(kvA.Value, &metadataA) + cdc.MustUnmarshal(kvB.Value, &metadataB) + return fmt.Sprintf("Authority MetadataA: %s\nAuthority MetadataB: %s\n", metadataA, metadataB) + + case bytes.HasPrefix(kvA.Key, []byte(types.CreatorPrefixKey)): + return fmt.Sprintf("DenomA: %s\nDenomB: %s\n", kvA.Value, kvB.Value) + + case bytes.HasPrefix(kvA.Key, []byte(types.ParamsPrefixKey)): + var paramA, paramB types.Params + cdc.MustUnmarshal(kvA.Value, ¶mA) + cdc.MustUnmarshal(kvA.Value, ¶mB) + return fmt.Sprintf("ParamsA: %s\nParamsB: %s\n", paramA, paramB) + + default: + panic(fmt.Sprintf("unexpected %s key %X (%s)", types.ModuleName, kvA.Key, kvA.Key)) + } + } +} diff --git a/x/tokenfactory/simulation/decoder_test.go b/x/tokenfactory/simulation/decoder_test.go new file mode 100644 index 0000000000..134087db5f --- /dev/null +++ b/x/tokenfactory/simulation/decoder_test.go @@ -0,0 +1,69 @@ +package simulation_test + +import ( + "fmt" + "testing" + + "github.com/cosmos/cosmos-sdk/types/kv" + "github.com/desmos-labs/desmos/v5/app" + "github.com/desmos-labs/desmos/v5/x/tokenfactory/simulation" + "github.com/desmos-labs/desmos/v5/x/tokenfactory/types" + "github.com/stretchr/testify/require" +) + +func TestDecodeStore(t *testing.T) { + cdc, _ := app.MakeCodecs() + decoder := simulation.NewDecodeStore(cdc) + + metadata := types.DenomAuthorityMetadata{ + Admin: "cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47", + } + + denom := "factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/uminttoken" + + params := types.DefaultParams() + + kvPairs := kv.Pairs{Pairs: []kv.Pair{ + { + Key: append(types.GetDenomPrefixStore("cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47"), []byte(types.DenomAuthorityMetadataKey)...), + Value: cdc.MustMarshal(&metadata), + }, + { + Key: append(types.GetCreatorPrefix("cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47"), []byte(denom)...), + Value: []byte(denom), + }, + { + Key: []byte(types.ParamsPrefixKey), + Value: cdc.MustMarshal(¶ms), + }, + { + Key: []byte("Unknown key"), + Value: nil, + }, + }} + + testCases := []struct { + name string + expectedLog string + }{ + {"Authority Metadata", fmt.Sprintf("Authority MetadataA: %s\nAuthority MetadataB: %s\n", + metadata, metadata)}, + {"Denom", fmt.Sprintf("DenomA: %s\nDenomB: %s\n", + denom, denom)}, + {"Params", fmt.Sprintf("ParamsA: %s\nParamsB: %s\n", + params, params)}, + {"other", ""}, + } + + for i, tc := range testCases { + i, tc := i, tc + t.Run(tc.name, func(t *testing.T) { + switch i { + case len(testCases) - 1: + require.Panics(t, func() { decoder(kvPairs.Pairs[i], kvPairs.Pairs[i]) }, tc.name) + default: + require.Equal(t, tc.expectedLog, decoder(kvPairs.Pairs[i], kvPairs.Pairs[i]), tc.name) + } + }) + } +} diff --git a/x/tokenfactory/simulation/genesis.go b/x/tokenfactory/simulation/genesis.go new file mode 100644 index 0000000000..c400940dfb --- /dev/null +++ b/x/tokenfactory/simulation/genesis.go @@ -0,0 +1,55 @@ +package simulation + +import ( + "math/rand" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + + subspacessim "github.com/desmos-labs/desmos/v5/x/subspaces/simulation" + subspacestypes "github.com/desmos-labs/desmos/v5/x/subspaces/types" + "github.com/desmos-labs/desmos/v5/x/tokenfactory/types" +) + +// RandomizeGenState generates a random GenesisState for x/tokenfactory +func RandomizeGenState(simState *module.SimulationState) { + // Read the subspaces data + subspacesGenesisBz := simState.GenState[subspacestypes.ModuleName] + var subspacesGenesis subspacestypes.GenesisState + simState.Cdc.MustUnmarshalJSON(subspacesGenesisBz, &subspacesGenesis) + + genesis := &types.GenesisState{ + Params: types.NewParams(sdk.NewCoins(sdk.NewInt64Coin(sdk.DefaultBondDenom, 10))), + FactoryDenoms: randomFactoryDenoms(simState.Rand, subspacesGenesis.Subspaces), + } + + simState.GenState[types.ModuleName] = simState.Cdc.MustMarshalJSON(genesis) +} + +// randomFactoryDenoms generates a list of random factory denoms +func randomFactoryDenoms(r *rand.Rand, subspaces []subspacestypes.Subspace) []types.GenesisDenom { + if len(subspaces) == 0 { + return nil + } + + denomsNumber := r.Intn(20) + denoms := make([]types.GenesisDenom, denomsNumber) + for i := 0; i < denomsNumber; i++ { + subspace := subspacessim.RandomSubspace(r, subspaces) + + denom, err := types.GetTokenDenom(subspace.Treasury, simtypes.RandStringOfLength(r, 6)) + if err != nil { + panic(err) + } + + denoms[i] = types.GenesisDenom{ + Denom: denom, + AuthorityMetadata: types.DenomAuthorityMetadata{ + Admin: subspace.Treasury, + }, + } + } + + return denoms +} diff --git a/x/tokenfactory/simulation/operations.go b/x/tokenfactory/simulation/operations.go new file mode 100644 index 0000000000..0d446e87fb --- /dev/null +++ b/x/tokenfactory/simulation/operations.go @@ -0,0 +1,374 @@ +package simulation + +// DONTCOVER + +import ( + "math/rand" + + "cosmossdk.io/math" + "github.com/cosmos/cosmos-sdk/baseapp" + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" + bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + sim "github.com/cosmos/cosmos-sdk/x/simulation" + + "github.com/desmos-labs/desmos/v5/testutil/simtesting" + subspacessim "github.com/desmos-labs/desmos/v5/x/subspaces/simulation" + subspacestypes "github.com/desmos-labs/desmos/v5/x/subspaces/types" + "github.com/desmos-labs/desmos/v5/x/tokenfactory/keeper" + "github.com/desmos-labs/desmos/v5/x/tokenfactory/types" +) + +// DONTCOVER + +// Simulation operation weights constants +// #nosec G101 -- This is a false positive +const ( + OpWeightMsgCreateDenom = "op_weight_msg_create_denom" + OpWeightMsgMint = "op_weight_msg_mint" + OpWeightMsgBurn = "op_weight_msg_burn" + OpWeightMsgSetDenomMetadata = "op_weight_msg_set_denom_metadata" + + DefaultWeightMsgCreateDenom = 30 + DefaultWeightMsgMint = 70 + DefaultWeightMsgBurn = 40 + DefaultWeightMsgSetDenomMetadata = 20 +) + +// WeightedOperations returns all the operations from the module with their respective weights +func WeightedOperations( + appParams simtypes.AppParams, cdc codec.JSONCodec, + k keeper.Keeper, sk types.SubspacesKeeper, ak authkeeper.AccountKeeper, bk bankkeeper.Keeper, +) sim.WeightedOperations { + + var weightMsgCreateDenom int + appParams.GetOrGenerate(cdc, OpWeightMsgCreateDenom, &weightMsgCreateDenom, nil, + func(_ *rand.Rand) { + weightMsgCreateDenom = DefaultWeightMsgCreateDenom + }, + ) + + var weightMsgMint int + appParams.GetOrGenerate(cdc, OpWeightMsgMint, &weightMsgMint, nil, + func(_ *rand.Rand) { + weightMsgMint = DefaultWeightMsgMint + }, + ) + + var weightMsgBurn int + appParams.GetOrGenerate(cdc, OpWeightMsgBurn, &weightMsgBurn, nil, + func(_ *rand.Rand) { + weightMsgBurn = DefaultWeightMsgBurn + }, + ) + + var weightMsgSetDenomMetadata int + appParams.GetOrGenerate(cdc, OpWeightMsgSetDenomMetadata, &weightMsgSetDenomMetadata, nil, + func(_ *rand.Rand) { + weightMsgSetDenomMetadata = DefaultWeightMsgSetDenomMetadata + }, + ) + + return sim.WeightedOperations{ + sim.NewWeightedOperation( + weightMsgCreateDenom, + SimulateMsgCreateDenom(k, sk, ak, bk), + ), + sim.NewWeightedOperation( + weightMsgMint, + SimulateMsgMint(k, sk, ak, bk), + ), + sim.NewWeightedOperation( + weightMsgBurn, + SimulateMsgBurn(k, sk, ak, bk), + ), + sim.NewWeightedOperation( + weightMsgSetDenomMetadata, + SimulateMsgSetDenomMetadata(k, sk, ak, bk), + ), + } +} + +// -------------------------------------------------------------------------------------------------------------------- + +// SimulateMsgCreateDenom tests and runs a single MsgCreateDenom +func SimulateMsgCreateDenom( + k keeper.Keeper, sk types.SubspacesKeeper, ak authkeeper.AccountKeeper, bk bankkeeper.Keeper, +) simtypes.Operation { + return func( + r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, + accs []simtypes.Account, _ string, + ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { + + // Get the data + subspaceID, subdenom, signer, skip := randomCreateDenomFields(r, ctx, accs, k, sk, bk) + if skip { + return simtypes.NoOpMsg(types.RouterKey, "MsgCreateDenom", "skip"), nil, nil + } + + msg := types.NewMsgCreateDenom(subspaceID, signer.Address.String(), subdenom) + + // Send the message + return simtesting.SendMsg(r, app, ak, bk, msg, ctx, signer) + } +} + +// randomCreateDenomFields returns the data used to build a random MsgCreateDenom +func randomCreateDenomFields( + r *rand.Rand, ctx sdk.Context, accs []simtypes.Account, k keeper.Keeper, sk types.SubspacesKeeper, bk bankkeeper.Keeper, +) (subspaceID uint64, subdenom string, signer simtypes.Account, skip bool) { + + // Get a subspace id + subspaces := sk.GetAllSubspaces(ctx) + if len(subspaces) == 0 { + // Skip because there are no subspaces + skip = true + return + } + subspace := subspacessim.RandomSubspace(r, subspaces) + subspaceID = subspace.ID + + // Check treasury balances + balances := bk.SpendableCoins(ctx, sdk.MustAccAddressFromBech32(subspace.Treasury)) + creationFees := k.GetParams(ctx).DenomCreationFee + if !balances.IsAllGT(creationFees) { + // Skip because treasury does not have enough coins + skip = true + return + } + + // Get a denom + subdenom = simtypes.RandStringOfLength(r, 6) + denom, _ := types.GetTokenDenom(subspace.Treasury, subdenom) + _, exists := bk.GetDenomMetaData(ctx, denom) + if exists { + // Skip because denom has already existed + skip = true + return + } + + // Get a signer + admins := sk.GetUsersWithRootPermissions(ctx, subspace.ID, subspacestypes.NewPermissions(types.PermissionManageSubspaceTokens)) + acc := subspacessim.GetAccount(subspacessim.RandomAddress(r, admins), accs) + if acc == nil { + // Skip because the account is not valid + skip = true + return + } + signer = *acc + + return subspaceID, subdenom, signer, false +} + +// -------------------------------------------------------------------------------------------------------------------- + +// SimulateMsgMint tests and runs a single MsgMint +func SimulateMsgMint( + k keeper.Keeper, sk types.SubspacesKeeper, ak authkeeper.AccountKeeper, bk bankkeeper.Keeper, +) simtypes.Operation { + return func( + r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, + accs []simtypes.Account, _ string, + ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { + + // Get the data + subspaceID, amount, signer, skip := randomMintFields(r, ctx, accs, k, sk) + if skip { + return simtypes.NoOpMsg(types.RouterKey, "MsgMint", "skip"), nil, nil + } + + msg := types.NewMsgMint(subspaceID, signer.Address.String(), amount) + + // Send the message + return simtesting.SendMsg(r, app, ak, bk, msg, ctx, signer) + } +} + +// randomMintFields returns the data used to build a random MsgMint +func randomMintFields( + r *rand.Rand, ctx sdk.Context, accs []simtypes.Account, k keeper.Keeper, sk types.SubspacesKeeper, +) (subspaceID uint64, amount sdk.Coin, signer simtypes.Account, skip bool) { + + // Get a subspace id + subspaces := sk.GetAllSubspaces(ctx) + if len(subspaces) == 0 { + // Skip because there are no subspaces + skip = true + return + } + subspace := subspacessim.RandomSubspace(r, subspaces) + subspaceID = subspace.ID + + // Get an amount + denoms := k.GetDenomsFromCreator(ctx, subspace.Treasury) + if len(denoms) == 0 { + // Skip because there are no denoms + skip = true + return + } + denom := RandomDenom(r, denoms) + amount = sdk.NewCoin(denom, simtypes.RandomAmount(r, math.NewInt(1000))) + if amount.Amount.Equal(sdk.NewInt(0)) { + // Skip because amount with zero is invalid + skip = true + return + } + + // Get a signer + admins := sk.GetUsersWithRootPermissions(ctx, subspace.ID, subspacestypes.NewPermissions(types.PermissionManageSubspaceTokens)) + acc := subspacessim.GetAccount(subspacessim.RandomAddress(r, admins), accs) + if acc == nil { + // Skip because the account is not valid + skip = true + return + } + signer = *acc + + return subspaceID, amount, signer, false +} + +// -------------------------------------------------------------------------------------------------------------------- + +// SimulateMsgBurn tests and runs a single MsgBurn +func SimulateMsgBurn( + k keeper.Keeper, sk types.SubspacesKeeper, ak authkeeper.AccountKeeper, bk bankkeeper.Keeper, +) simtypes.Operation { + return func( + r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, + accs []simtypes.Account, _ string, + ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { + + // Get the data + subspaceID, amount, signer, skip := randomBurnFields(r, ctx, accs, k, sk, bk) + if skip { + return simtypes.NoOpMsg(types.RouterKey, "MsgBurn", "skip"), nil, nil + } + + msg := types.NewMsgBurn(subspaceID, signer.Address.String(), amount) + + // Send the message + return simtesting.SendMsg(r, app, ak, bk, msg, ctx, signer) + } +} + +// randomBurnFields returns the data used to build a random MsgBurn +func randomBurnFields( + r *rand.Rand, ctx sdk.Context, accs []simtypes.Account, k keeper.Keeper, sk types.SubspacesKeeper, bk bankkeeper.ViewKeeper, +) (subspaceID uint64, amount sdk.Coin, signer simtypes.Account, skip bool) { + + // Get a subspace id + subspaces := sk.GetAllSubspaces(ctx) + if len(subspaces) == 0 { + // Skip because there are no subspaces + skip = true + return + } + subspace := subspacessim.RandomSubspace(r, subspaces) + subspaceID = subspace.ID + + // Get a denom + denoms := k.GetDenomsFromCreator(ctx, subspace.Treasury) + if len(denoms) == 0 { + // Skip because there are no denoms + skip = true + return + } + denom := RandomDenom(r, denoms) + + // Get a amount to burn + balance := bk.SpendableCoin(ctx, sdk.MustAccAddressFromBech32(subspace.Treasury), denom) + amount = sdk.NewCoin(denom, simtypes.RandomAmount(r, balance.Amount)) + if amount.Amount.Equal(sdk.NewInt(0)) { + // Skip because amount with zero is invalid + skip = true + return + } + + // Get a signer + admins := sk.GetUsersWithRootPermissions(ctx, subspace.ID, subspacestypes.NewPermissions(types.PermissionManageSubspaceTokens)) + acc := subspacessim.GetAccount(subspacessim.RandomAddress(r, admins), accs) + if acc == nil { + // Skip because the account is invalid + skip = true + return + } + signer = *acc + + return subspaceID, amount, signer, false +} + +// -------------------------------------------------------------------------------------------------------------------- + +// SimulateMsgSetDenomMetadata tests and runs a single MsgSetDenomMetadata +func SimulateMsgSetDenomMetadata( + k keeper.Keeper, sk types.SubspacesKeeper, ak authkeeper.AccountKeeper, bk bankkeeper.Keeper, +) simtypes.Operation { + return func( + r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, + accs []simtypes.Account, _ string, + ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { + + // Get the data + subspaceID, metadata, signer, skip := randomSetDenomMetadataFields(r, ctx, accs, k, sk) + if skip { + return simtypes.NoOpMsg(types.RouterKey, "MsgSetDenomMetadata", "skip"), nil, nil + } + + msg := types.NewMsgSetDenomMetadata(subspaceID, signer.Address.String(), metadata) + + // Send the message + return simtesting.SendMsg(r, app, ak, bk, msg, ctx, signer) + } +} + +// randomSetDenomMetadataFields returns the data used to build a random MsgSetDenomMetadata +func randomSetDenomMetadataFields( + r *rand.Rand, ctx sdk.Context, accs []simtypes.Account, k keeper.Keeper, sk types.SubspacesKeeper, +) (subspaceID uint64, metadata banktypes.Metadata, signer simtypes.Account, skip bool) { + + // Get a subspace id + subspaces := sk.GetAllSubspaces(ctx) + if len(subspaces) == 0 { + // Skip because there are no subspaces + skip = true + return + } + subspace := subspacessim.RandomSubspace(r, subspaces) + subspaceID = subspace.ID + + // Get an metadata + denoms := k.GetDenomsFromCreator(ctx, subspace.Treasury) + if len(denoms) == 0 { + // Skip because there are no denoms + skip = true + return + } + denom := RandomDenom(r, denoms) + display := simtypes.RandStringOfLength(r, 3) + metadata = banktypes.Metadata{ + Description: simtypes.RandStringOfLength(r, 15), + DenomUnits: []*banktypes.DenomUnit{ + {Denom: denom, Exponent: 0, Aliases: nil}, + {Denom: display, Exponent: 3, Aliases: nil}, + }, + Base: denom, + Display: display, + Name: simtypes.RandStringOfLength(r, 5), + Symbol: simtypes.RandStringOfLength(r, 5), + } + + // Get a signer + admins := sk.GetUsersWithRootPermissions(ctx, subspace.ID, subspacestypes.NewPermissions(types.PermissionManageSubspaceTokens)) + acc := subspacessim.GetAccount(subspacessim.RandomAddress(r, admins), accs) + if acc == nil { + // Skip because the account is not valid + skip = true + return + } + signer = *acc + + return subspaceID, metadata, signer, false +} diff --git a/x/tokenfactory/simulation/proposal.go b/x/tokenfactory/simulation/proposal.go new file mode 100644 index 0000000000..2473afe33d --- /dev/null +++ b/x/tokenfactory/simulation/proposal.go @@ -0,0 +1,47 @@ +package simulation + +import ( + "math/rand" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/address" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + "github.com/cosmos/cosmos-sdk/x/simulation" + + "github.com/desmos-labs/desmos/v5/x/tokenfactory/types" +) + +// DONTCOVER + +// Simulation operation weights constants +const ( + DefaultWeightMsgUpdateParams int = 50 + + OpWeightMsgUpdateParams = "op_weight_msg_update_params" //nolint:gosec +) + +// ProposalMsgs defines the module weighted proposals' contents +func ProposalMsgs() []simtypes.WeightedProposalMsg { + return []simtypes.WeightedProposalMsg{ + simulation.NewWeightedProposalMsg( + OpWeightMsgUpdateParams, + DefaultWeightMsgUpdateParams, + SimulateMsgUpdateParams, + ), + } +} + +// SimulateMsgUpdateParams returns a random MsgUpdateParams +func SimulateMsgUpdateParams(r *rand.Rand, _ sdk.Context, _ []simtypes.Account) sdk.Msg { + // use the default gov module account address as authority + var authority sdk.AccAddress = address.Module("gov") + + params := types.NewParams(sdk.NewCoins( + sdk.NewCoin(sdk.DefaultBondDenom, simtypes.RandomAmount(r, sdk.NewInt(100)))), + ) + + return &types.MsgUpdateParams{ + Authority: authority.String(), + Params: params, + } +} diff --git a/x/tokenfactory/simulation/utils.go b/x/tokenfactory/simulation/utils.go new file mode 100644 index 0000000000..427bbb7c97 --- /dev/null +++ b/x/tokenfactory/simulation/utils.go @@ -0,0 +1,10 @@ +package simulation + +import ( + "math/rand" +) + +// RandomDenom returns a random denom from the given slice +func RandomDenom(r *rand.Rand, denoms []string) string { + return denoms[r.Intn(len(denoms))] +} diff --git a/x/tokenfactory/testutil/expected_keepers_mocks.go b/x/tokenfactory/testutil/expected_keepers_mocks.go new file mode 100644 index 0000000000..af3c843af9 --- /dev/null +++ b/x/tokenfactory/testutil/expected_keepers_mocks.go @@ -0,0 +1,294 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: ./x/tokenfactory/types/expected_keepers.go + +// Package testutil is a generated GoMock package. +package testutil + +import ( + reflect "reflect" + + types "github.com/cosmos/cosmos-sdk/types" + types0 "github.com/cosmos/cosmos-sdk/x/auth/types" + types1 "github.com/cosmos/cosmos-sdk/x/bank/types" + types2 "github.com/desmos-labs/desmos/v5/x/subspaces/types" + gomock "github.com/golang/mock/gomock" +) + +// MockBankKeeper is a mock of BankKeeper interface. +type MockBankKeeper struct { + ctrl *gomock.Controller + recorder *MockBankKeeperMockRecorder +} + +// MockBankKeeperMockRecorder is the mock recorder for MockBankKeeper. +type MockBankKeeperMockRecorder struct { + mock *MockBankKeeper +} + +// NewMockBankKeeper creates a new mock instance. +func NewMockBankKeeper(ctrl *gomock.Controller) *MockBankKeeper { + mock := &MockBankKeeper{ctrl: ctrl} + mock.recorder = &MockBankKeeperMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockBankKeeper) EXPECT() *MockBankKeeperMockRecorder { + return m.recorder +} + +// BurnCoins mocks base method. +func (m *MockBankKeeper) BurnCoins(ctx types.Context, moduleName string, amt types.Coins) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "BurnCoins", ctx, moduleName, amt) + ret0, _ := ret[0].(error) + return ret0 +} + +// BurnCoins indicates an expected call of BurnCoins. +func (mr *MockBankKeeperMockRecorder) BurnCoins(ctx, moduleName, amt interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BurnCoins", reflect.TypeOf((*MockBankKeeper)(nil).BurnCoins), ctx, moduleName, amt) +} + +// GetDenomMetaData mocks base method. +func (m *MockBankKeeper) GetDenomMetaData(ctx types.Context, denom string) (types1.Metadata, bool) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetDenomMetaData", ctx, denom) + ret0, _ := ret[0].(types1.Metadata) + ret1, _ := ret[1].(bool) + return ret0, ret1 +} + +// GetDenomMetaData indicates an expected call of GetDenomMetaData. +func (mr *MockBankKeeperMockRecorder) GetDenomMetaData(ctx, denom interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetDenomMetaData", reflect.TypeOf((*MockBankKeeper)(nil).GetDenomMetaData), ctx, denom) +} + +// HasBalance mocks base method. +func (m *MockBankKeeper) HasBalance(ctx types.Context, addr types.AccAddress, amt types.Coin) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "HasBalance", ctx, addr, amt) + ret0, _ := ret[0].(bool) + return ret0 +} + +// HasBalance indicates an expected call of HasBalance. +func (mr *MockBankKeeperMockRecorder) HasBalance(ctx, addr, amt interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HasBalance", reflect.TypeOf((*MockBankKeeper)(nil).HasBalance), ctx, addr, amt) +} + +// HasSupply mocks base method. +func (m *MockBankKeeper) HasSupply(ctx types.Context, denom string) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "HasSupply", ctx, denom) + ret0, _ := ret[0].(bool) + return ret0 +} + +// HasSupply indicates an expected call of HasSupply. +func (mr *MockBankKeeperMockRecorder) HasSupply(ctx, denom interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HasSupply", reflect.TypeOf((*MockBankKeeper)(nil).HasSupply), ctx, denom) +} + +// MintCoins mocks base method. +func (m *MockBankKeeper) MintCoins(ctx types.Context, moduleName string, amt types.Coins) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "MintCoins", ctx, moduleName, amt) + ret0, _ := ret[0].(error) + return ret0 +} + +// MintCoins indicates an expected call of MintCoins. +func (mr *MockBankKeeperMockRecorder) MintCoins(ctx, moduleName, amt interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MintCoins", reflect.TypeOf((*MockBankKeeper)(nil).MintCoins), ctx, moduleName, amt) +} + +// SendCoins mocks base method. +func (m *MockBankKeeper) SendCoins(ctx types.Context, fromAddr, toAddr types.AccAddress, amt types.Coins) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SendCoins", ctx, fromAddr, toAddr, amt) + ret0, _ := ret[0].(error) + return ret0 +} + +// SendCoins indicates an expected call of SendCoins. +func (mr *MockBankKeeperMockRecorder) SendCoins(ctx, fromAddr, toAddr, amt interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendCoins", reflect.TypeOf((*MockBankKeeper)(nil).SendCoins), ctx, fromAddr, toAddr, amt) +} + +// SendCoinsFromAccountToModule mocks base method. +func (m *MockBankKeeper) SendCoinsFromAccountToModule(ctx types.Context, senderAddr types.AccAddress, recipientModule string, amt types.Coins) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SendCoinsFromAccountToModule", ctx, senderAddr, recipientModule, amt) + ret0, _ := ret[0].(error) + return ret0 +} + +// SendCoinsFromAccountToModule indicates an expected call of SendCoinsFromAccountToModule. +func (mr *MockBankKeeperMockRecorder) SendCoinsFromAccountToModule(ctx, senderAddr, recipientModule, amt interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendCoinsFromAccountToModule", reflect.TypeOf((*MockBankKeeper)(nil).SendCoinsFromAccountToModule), ctx, senderAddr, recipientModule, amt) +} + +// SendCoinsFromModuleToAccount mocks base method. +func (m *MockBankKeeper) SendCoinsFromModuleToAccount(ctx types.Context, senderModule string, recipientAddr types.AccAddress, amt types.Coins) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SendCoinsFromModuleToAccount", ctx, senderModule, recipientAddr, amt) + ret0, _ := ret[0].(error) + return ret0 +} + +// SendCoinsFromModuleToAccount indicates an expected call of SendCoinsFromModuleToAccount. +func (mr *MockBankKeeperMockRecorder) SendCoinsFromModuleToAccount(ctx, senderModule, recipientAddr, amt interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendCoinsFromModuleToAccount", reflect.TypeOf((*MockBankKeeper)(nil).SendCoinsFromModuleToAccount), ctx, senderModule, recipientAddr, amt) +} + +// SetDenomMetaData mocks base method. +func (m *MockBankKeeper) SetDenomMetaData(ctx types.Context, denomMetaData types1.Metadata) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "SetDenomMetaData", ctx, denomMetaData) +} + +// SetDenomMetaData indicates an expected call of SetDenomMetaData. +func (mr *MockBankKeeperMockRecorder) SetDenomMetaData(ctx, denomMetaData interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetDenomMetaData", reflect.TypeOf((*MockBankKeeper)(nil).SetDenomMetaData), ctx, denomMetaData) +} + +// MockAccountKeeper is a mock of AccountKeeper interface. +type MockAccountKeeper struct { + ctrl *gomock.Controller + recorder *MockAccountKeeperMockRecorder +} + +// MockAccountKeeperMockRecorder is the mock recorder for MockAccountKeeper. +type MockAccountKeeperMockRecorder struct { + mock *MockAccountKeeper +} + +// NewMockAccountKeeper creates a new mock instance. +func NewMockAccountKeeper(ctrl *gomock.Controller) *MockAccountKeeper { + mock := &MockAccountKeeper{ctrl: ctrl} + mock.recorder = &MockAccountKeeperMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockAccountKeeper) EXPECT() *MockAccountKeeperMockRecorder { + return m.recorder +} + +// GetAccount mocks base method. +func (m *MockAccountKeeper) GetAccount(arg0 types.Context, arg1 types.AccAddress) types0.AccountI { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetAccount", arg0, arg1) + ret0, _ := ret[0].(types0.AccountI) + return ret0 +} + +// GetAccount indicates an expected call of GetAccount. +func (mr *MockAccountKeeperMockRecorder) GetAccount(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAccount", reflect.TypeOf((*MockAccountKeeper)(nil).GetAccount), arg0, arg1) +} + +// GetModuleAccount mocks base method. +func (m *MockAccountKeeper) GetModuleAccount(ctx types.Context, moduleName string) types0.ModuleAccountI { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetModuleAccount", ctx, moduleName) + ret0, _ := ret[0].(types0.ModuleAccountI) + return ret0 +} + +// GetModuleAccount indicates an expected call of GetModuleAccount. +func (mr *MockAccountKeeperMockRecorder) GetModuleAccount(ctx, moduleName interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetModuleAccount", reflect.TypeOf((*MockAccountKeeper)(nil).GetModuleAccount), ctx, moduleName) +} + +// MockSubspacesKeeper is a mock of SubspacesKeeper interface. +type MockSubspacesKeeper struct { + ctrl *gomock.Controller + recorder *MockSubspacesKeeperMockRecorder +} + +// MockSubspacesKeeperMockRecorder is the mock recorder for MockSubspacesKeeper. +type MockSubspacesKeeperMockRecorder struct { + mock *MockSubspacesKeeper +} + +// NewMockSubspacesKeeper creates a new mock instance. +func NewMockSubspacesKeeper(ctrl *gomock.Controller) *MockSubspacesKeeper { + mock := &MockSubspacesKeeper{ctrl: ctrl} + mock.recorder = &MockSubspacesKeeperMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockSubspacesKeeper) EXPECT() *MockSubspacesKeeperMockRecorder { + return m.recorder +} + +// GetAllSubspaces mocks base method. +func (m *MockSubspacesKeeper) GetAllSubspaces(ctx types.Context) []types2.Subspace { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetAllSubspaces", ctx) + ret0, _ := ret[0].([]types2.Subspace) + return ret0 +} + +// GetAllSubspaces indicates an expected call of GetAllSubspaces. +func (mr *MockSubspacesKeeperMockRecorder) GetAllSubspaces(ctx interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAllSubspaces", reflect.TypeOf((*MockSubspacesKeeper)(nil).GetAllSubspaces), ctx) +} + +// GetSubspace mocks base method. +func (m *MockSubspacesKeeper) GetSubspace(ctx types.Context, subspaceID uint64) (types2.Subspace, bool) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSubspace", ctx, subspaceID) + ret0, _ := ret[0].(types2.Subspace) + ret1, _ := ret[1].(bool) + return ret0, ret1 +} + +// GetSubspace indicates an expected call of GetSubspace. +func (mr *MockSubspacesKeeperMockRecorder) GetSubspace(ctx, subspaceID interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSubspace", reflect.TypeOf((*MockSubspacesKeeper)(nil).GetSubspace), ctx, subspaceID) +} + +// GetUsersWithRootPermissions mocks base method. +func (m *MockSubspacesKeeper) GetUsersWithRootPermissions(ctx types.Context, subspaceID uint64, permission types2.Permissions) []string { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetUsersWithRootPermissions", ctx, subspaceID, permission) + ret0, _ := ret[0].([]string) + return ret0 +} + +// GetUsersWithRootPermissions indicates an expected call of GetUsersWithRootPermissions. +func (mr *MockSubspacesKeeperMockRecorder) GetUsersWithRootPermissions(ctx, subspaceID, permission interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetUsersWithRootPermissions", reflect.TypeOf((*MockSubspacesKeeper)(nil).GetUsersWithRootPermissions), ctx, subspaceID, permission) +} + +// HasPermission mocks base method. +func (m *MockSubspacesKeeper) HasPermission(ctx types.Context, subspaceID uint64, sectionID uint32, user string, permission types2.Permission) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "HasPermission", ctx, subspaceID, sectionID, user, permission) + ret0, _ := ret[0].(bool) + return ret0 +} + +// HasPermission indicates an expected call of HasPermission. +func (mr *MockSubspacesKeeperMockRecorder) HasPermission(ctx, subspaceID, sectionID, user, permission interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HasPermission", reflect.TypeOf((*MockSubspacesKeeper)(nil).HasPermission), ctx, subspaceID, sectionID, user, permission) +} diff --git a/x/tokenfactory/types/authority_metadata.go b/x/tokenfactory/types/authority_metadata.go new file mode 100644 index 0000000000..bc388c3b3c --- /dev/null +++ b/x/tokenfactory/types/authority_metadata.go @@ -0,0 +1,16 @@ +package types + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// Validate implements fmt.Validator +func (metadata DenomAuthorityMetadata) Validate() error { + if metadata.Admin != "" { + _, err := sdk.AccAddressFromBech32(metadata.Admin) + if err != nil { + return err + } + } + return nil +} diff --git a/x/tokenfactory/types/codec.go b/x/tokenfactory/types/codec.go new file mode 100644 index 0000000000..6143e5b122 --- /dev/null +++ b/x/tokenfactory/types/codec.go @@ -0,0 +1,61 @@ +package types + +import ( + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/codec/legacy" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/msgservice" + authzcodec "github.com/cosmos/cosmos-sdk/x/authz/codec" + govcodec "github.com/cosmos/cosmos-sdk/x/gov/codec" +) + +func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { + legacy.RegisterAminoMsg(cdc, &MsgCreateDenom{}, "desmos/MsgCreateDenom") + legacy.RegisterAminoMsg(cdc, &MsgMint{}, "desmos/MsgMint") + legacy.RegisterAminoMsg(cdc, &MsgBurn{}, "desmos/MsgBurn") + legacy.RegisterAminoMsg(cdc, &MsgSetDenomMetadata{}, "desmos/MsgSetDenomMetadata") + legacy.RegisterAminoMsg(cdc, &MsgUpdateParams{}, "desmos/x/tokenfactory/MsgUpdateParams") + + cdc.RegisterConcrete(&Params{}, "desmos/x/tokenfactory/Params", nil) +} + +func RegisterInterfaces(registry codectypes.InterfaceRegistry) { + registry.RegisterImplementations( + (*sdk.Msg)(nil), + &MsgCreateDenom{}, + &MsgMint{}, + &MsgBurn{}, + &MsgSetDenomMetadata{}, + &MsgUpdateParams{}, + ) + + msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) +} + +var ( + amino = codec.NewLegacyAmino() + + // AminoCdc references the global x/tokenfactory module codec. Note, the codec should + // ONLY be used in certain instances of tests and for JSON encoding as Amino is + // still used for that purpose. + // + // The actual codec used for serialization should be provided to x/tokenfactory and + // defined at the application level. + AminoCdc = codec.NewAminoCodec(amino) +) + +func init() { + RegisterLegacyAminoCodec(amino) + cryptocodec.RegisterCrypto(amino) + sdk.RegisterLegacyAminoCodec(amino) + + // Register all Amino interfaces and concrete types on the authz Amino codec so that this can later be + // used to properly serialize MsgGrant and MsgExec instances + RegisterLegacyAminoCodec(authzcodec.Amino) + + // Register all Amino interfaces and concrete types on the gov Amino codec so that this can later be + // used to properly serialize MsgSubmitProposal instances + RegisterLegacyAminoCodec(govcodec.Amino) +} diff --git a/x/tokenfactory/types/denoms.go b/x/tokenfactory/types/denoms.go new file mode 100644 index 0000000000..97929529d3 --- /dev/null +++ b/x/tokenfactory/types/denoms.go @@ -0,0 +1,84 @@ +package types + +import ( + fmt "fmt" + "strings" + + "cosmossdk.io/errors" + sdk "github.com/cosmos/cosmos-sdk/types" + bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" +) + +const ( + ModuleDenomPrefix = "factory" + // See the TokenFactory readme for a derivation of these. + // TL;DR, MaxSubdenomLength + MaxHrpLength = 60 comes from SDK max denom length = 128 + // and the structure of tokenfactory denoms. + MaxSubdenomLength = 44 + MaxHrpLength = 16 + // MaxCreatorLength = 59 + MaxHrpLength + MaxCreatorLength = 59 + MaxHrpLength +) + +// GetTokenDenom constructs a denom string for tokens created by tokenfactory +// based on an input creator address and a subdenom +// The denom constructed is factory/{creator}/{subdenom} +func GetTokenDenom(creator, subdenom string) (string, error) { + if len(subdenom) > MaxSubdenomLength { + return "", ErrSubdenomTooLong + } + if len(creator) > MaxCreatorLength { + return "", ErrCreatorTooLong + } + if strings.Contains(creator, "/") { + return "", ErrInvalidCreator + } + denom := strings.Join([]string{ModuleDenomPrefix, creator, subdenom}, "/") + return denom, sdk.ValidateDenom(denom) +} + +// DeconstructDenom takes a token denom string and verifies that it is a valid +// denom of the tokenfactory module, and is of the form `factory/{creator}/{subdenom}` +// If valid, it returns the creator address and subdenom +func DeconstructDenom(denom string) (creator string, subdenom string, err error) { + err = sdk.ValidateDenom(denom) + if err != nil { + return "", "", err + } + + strParts := strings.Split(denom, "/") + if len(strParts) < 3 { + return "", "", errors.Wrapf(ErrInvalidDenom, "not enough parts of denom %s", denom) + } + + if strParts[0] != ModuleDenomPrefix { + return "", "", errors.Wrapf(ErrInvalidDenom, "denom prefix is incorrect. Is: %s. Should be: %s", strParts[0], ModuleDenomPrefix) + } + + creator = strParts[1] + creatorAddr, err := sdk.AccAddressFromBech32(creator) + if err != nil { + return "", "", errors.Wrapf(ErrInvalidDenom, "Invalid creator address (%s)", err) + } + + // Handle the case where a denom has a slash in its subdenom. For example, + // when we did the split, we'd turn factory/accaddr/atomderivative/sikka into ["factory", "accaddr", "atomderivative", "sikka"] + // So we have to join [2:] with a "/" as the delimiter to get back the correct subdenom which should be "atomderivative/sikka" + subdenom = strings.Join(strParts[2:], "/") + + return creatorAddr.String(), subdenom, nil +} + +// NewTokenFactoryDenomMintCoinsRestriction creates and returns a MintingRestrictionFn that only allows minting of +// valid tokenfactory denoms +func NewTokenFactoryDenomMintCoinsRestriction() bankkeeper.MintingRestrictionFn { + return func(ctx sdk.Context, coinsToMint sdk.Coins) error { + for _, coin := range coinsToMint { + _, _, err := DeconstructDenom(coin.Denom) + if err != nil { + return fmt.Errorf("does not have permission to mint %s", coin.Denom) + } + } + return nil + } +} diff --git a/x/tokenfactory/types/denoms_test.go b/x/tokenfactory/types/denoms_test.go new file mode 100644 index 0000000000..0b693acab7 --- /dev/null +++ b/x/tokenfactory/types/denoms_test.go @@ -0,0 +1,122 @@ +package types_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/desmos-labs/desmos/v5/x/tokenfactory/types" +) + +func TestDeconstructDenom(t *testing.T) { + + for _, tc := range []struct { + name string + denom string + expectedSubdenom string + err error + }{ + { + name: "empty is invalid", + denom: "", + err: types.ErrInvalidDenom, + }, + { + name: "normal", + denom: "factory/cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69/bitcoin", + expectedSubdenom: "bitcoin", + }, + { + name: "multiple slashes in subdenom", + denom: "factory/cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69/bitcoin/1", + expectedSubdenom: "bitcoin/1", + }, + { + name: "no subdenom", + denom: "factory/cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69/", + expectedSubdenom: "", + }, + { + name: "incorrect prefix", + denom: "ibc/cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69/bitcoin", + err: types.ErrInvalidDenom, + }, + { + name: "subdenom of only slashes", + denom: "factory/cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69/////", + expectedSubdenom: "////", + }, + { + name: "too long name", + denom: "factory/cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69/adsfadsfadsfadsfadsfadsfadsfadsfadsfadsfadsfadsfadsfadsfadsfadsfadsfadsfadsfadsfadsfadsfadsfadsfadsfadsfadsfadsfadsfadsfadsfadsfadsfadsfadsfadsfadsfadsfadsfadsfadsf", + err: types.ErrInvalidDenom, + }, + } { + t.Run(tc.name, func(t *testing.T) { + expectedCreator := "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69" + creator, subdenom, err := types.DeconstructDenom(tc.denom) + if tc.err != nil { + require.ErrorContains(t, err, tc.err.Error()) + } else { + require.NoError(t, err) + require.Equal(t, expectedCreator, creator) + require.Equal(t, tc.expectedSubdenom, subdenom) + } + }) + } +} + +func TestGetTokenDenom(t *testing.T) { + for _, tc := range []struct { + name string + creator string + subdenom string + shouldErr bool + }{ + { + name: "normal returns no error", + creator: "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + subdenom: "bitcoin", + }, + { + name: "multiple slashes in subdenom returns no error", + creator: "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + subdenom: "bitcoin/1", + }, + { + name: "no subdenom returns no error", + creator: "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + subdenom: "", + }, + { + name: "subdenom of only slashes returns no error", + creator: "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + subdenom: "/////", + }, + { + name: "too long name returns error", + creator: "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + subdenom: "adsfadsfadsfadsfadsfadsfadsfadsfadsfadsfadsfadsfadsfadsfadsfadsfadsfadsfadsfadsfadsfadsfadsfadsfadsfadsfadsfadsfadsfadsfadsfadsfadsfadsfadsfadsfadsfadsfadsfadsfadsf", + shouldErr: true, + }, + { + name: "subdenom is exactly max length returns no error", + creator: "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + subdenom: "bitcoinfsadfsdfeadfsafwefsefsefsdfsdafasefsf", + }, + { + name: "creator is exactly max length return no error", + creator: "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69jhgjhgkhjklhkjhkjhgjhgjgjghelu", + subdenom: "bitcoin", + }, + } { + t.Run(tc.name, func(t *testing.T) { + _, err := types.GetTokenDenom(tc.creator, tc.subdenom) + if tc.shouldErr { + require.Error(t, err) + } else { + require.NoError(t, err) + } + }) + } +} diff --git a/x/tokenfactory/types/errors.go b/x/tokenfactory/types/errors.go new file mode 100644 index 0000000000..74cc8b14ae --- /dev/null +++ b/x/tokenfactory/types/errors.go @@ -0,0 +1,22 @@ +package types + +// DONTCOVER + +import ( + fmt "fmt" + + "cosmossdk.io/errors" +) + +// x/tokenfactory module sentinel errors +var ( + ErrDenomExists = errors.Register(ModuleName, 2, "attempting to create a denom that already exists (has bank metadata)") + ErrUnauthorized = errors.Register(ModuleName, 3, "unauthorized account") + ErrInvalidDenom = errors.Register(ModuleName, 4, "invalid denom") + ErrInvalidCreator = errors.Register(ModuleName, 5, "invalid creator") + ErrInvalidAuthorityMetadata = errors.Register(ModuleName, 6, "invalid authority metadata") + ErrInvalidGenesis = errors.Register(ModuleName, 7, "invalid genesis") + ErrSubdenomTooLong = errors.Register(ModuleName, 8, fmt.Sprintf("subdenom too long, max length is %d bytes", MaxSubdenomLength)) + ErrCreatorTooLong = errors.Register(ModuleName, 9, fmt.Sprintf("creator too long, max length is %d bytes", MaxCreatorLength)) + ErrDenomDoesNotExist = errors.Register(ModuleName, 10, "denom does not exist") +) diff --git a/x/tokenfactory/types/events.go b/x/tokenfactory/types/events.go new file mode 100644 index 0000000000..73ffb16896 --- /dev/null +++ b/x/tokenfactory/types/events.go @@ -0,0 +1,22 @@ +package types + +// DONTCOVER + +// #nosec G101 -- This is a false positive +const ( + EventTypeCreateDenom = "create_denom" + EventTypeMint = "tf_mint" + EventTypeBurn = "tf_burn" + EventTypeSetDenomMetadata = "set_denom_metadata" + + AttributeValueCategory = ModuleName + AttributeKeySubspaceID = "subspace_id" + AttributeAmount = "amount" + AttributeCreator = "creator" + AttributeSubdenom = "subdenom" + AttributeNewTokenDenom = "new_token_denom" + AttributeMintToAddress = "mint_to_address" + AttributeBurnFromAddress = "burn_from_address" + AttributeDenom = "denom" + AttributeDenomMetadata = "denom_metadata" +) diff --git a/x/tokenfactory/types/expected_keepers.go b/x/tokenfactory/types/expected_keepers.go new file mode 100644 index 0000000000..d615315fe8 --- /dev/null +++ b/x/tokenfactory/types/expected_keepers.go @@ -0,0 +1,40 @@ +package types + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + + subspacestypes "github.com/desmos-labs/desmos/v5/x/subspaces/types" +) + +// BankKeeper represents a keeper that deals with x/bank +type BankKeeper interface { + // Methods imported from bank should be defined here + GetDenomMetaData(ctx sdk.Context, denom string) (banktypes.Metadata, bool) + SetDenomMetaData(ctx sdk.Context, denomMetaData banktypes.Metadata) + + HasSupply(ctx sdk.Context, denom string) bool + + SendCoinsFromModuleToAccount(ctx sdk.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins) error + SendCoinsFromAccountToModule(ctx sdk.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) error + MintCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) error + BurnCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) error + + SendCoins(ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) error + HasBalance(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coin) bool +} + +// AccountKeeper represents a keeper that deals with x/auth +type AccountKeeper interface { + GetAccount(sdk.Context, sdk.AccAddress) authtypes.AccountI + GetModuleAccount(ctx sdk.Context, moduleName string) authtypes.ModuleAccountI +} + +// SubspacesKeeper represents a keeper that deals with x/subspaces +type SubspacesKeeper interface { + GetAllSubspaces(ctx sdk.Context) []subspacestypes.Subspace + GetSubspace(ctx sdk.Context, subspaceID uint64) (subspace subspacestypes.Subspace, found bool) + HasPermission(ctx sdk.Context, subspaceID uint64, sectionID uint32, user string, permission subspacestypes.Permission) bool + GetUsersWithRootPermissions(ctx sdk.Context, subspaceID uint64, permission subspacestypes.Permissions) []string +} diff --git a/x/tokenfactory/types/genesis.go b/x/tokenfactory/types/genesis.go new file mode 100644 index 0000000000..1445389fd1 --- /dev/null +++ b/x/tokenfactory/types/genesis.go @@ -0,0 +1,49 @@ +package types + +import ( + "cosmossdk.io/errors" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// DefaultIndex is the default capability global index +const DefaultIndex uint64 = 1 + +// DefaultGenesis returns the default Capability genesis state +func DefaultGenesis() *GenesisState { + return &GenesisState{ + Params: DefaultParams(), + FactoryDenoms: []GenesisDenom{}, + } +} + +// Validate performs basic genesis state validation returning an error upon any +// failure. +func (gs GenesisState) Validate() error { + err := gs.Params.Validate() + if err != nil { + return err + } + + seenDenoms := map[string]bool{} + + for _, denom := range gs.GetFactoryDenoms() { + if seenDenoms[denom.GetDenom()] { + return errors.Wrapf(ErrInvalidGenesis, "duplicate denom: %s", denom.GetDenom()) + } + seenDenoms[denom.GetDenom()] = true + + _, _, err := DeconstructDenom(denom.GetDenom()) + if err != nil { + return err + } + + if denom.AuthorityMetadata.Admin != "" { + _, err = sdk.AccAddressFromBech32(denom.AuthorityMetadata.Admin) + if err != nil { + return errors.Wrapf(ErrInvalidAuthorityMetadata, "Invalid admin address (%s)", err) + } + } + } + + return nil +} diff --git a/x/tokenfactory/types/genesis.pb.go b/x/tokenfactory/types/genesis.pb.go new file mode 100644 index 0000000000..c1f2489fd4 --- /dev/null +++ b/x/tokenfactory/types/genesis.pb.go @@ -0,0 +1,651 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: desmos/tokenfactory/v1beta1/genesis.proto + +package types + +import ( + fmt "fmt" + _ "github.com/cosmos/cosmos-sdk/types/tx/amino" + _ "github.com/cosmos/gogoproto/gogoproto" + proto "github.com/cosmos/gogoproto/proto" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// GenesisState defines the tokenfactory module's genesis state. +type GenesisState struct { + // params defines the paramaters of the module. + Params Params `protobuf:"bytes,1,opt,name=params,proto3" json:"params"` + FactoryDenoms []GenesisDenom `protobuf:"bytes,2,rep,name=factory_denoms,json=factoryDenoms,proto3" json:"factory_denoms" yaml:"factory_denoms"` +} + +func (m *GenesisState) Reset() { *m = GenesisState{} } +func (m *GenesisState) String() string { return proto.CompactTextString(m) } +func (*GenesisState) ProtoMessage() {} +func (*GenesisState) Descriptor() ([]byte, []int) { + return fileDescriptor_b001fa8c2a4a126e, []int{0} +} +func (m *GenesisState) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *GenesisState) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_GenesisState.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *GenesisState) XXX_Merge(src proto.Message) { + xxx_messageInfo_GenesisState.Merge(m, src) +} +func (m *GenesisState) XXX_Size() int { + return m.Size() +} +func (m *GenesisState) XXX_DiscardUnknown() { + xxx_messageInfo_GenesisState.DiscardUnknown(m) +} + +var xxx_messageInfo_GenesisState proto.InternalMessageInfo + +func (m *GenesisState) GetParams() Params { + if m != nil { + return m.Params + } + return Params{} +} + +func (m *GenesisState) GetFactoryDenoms() []GenesisDenom { + if m != nil { + return m.FactoryDenoms + } + return nil +} + +// GenesisDenom defines a tokenfactory denom that is defined within genesis +// state. The structure contains DenomAuthorityMetadata which defines the +// denom's admin. +type GenesisDenom struct { + Denom string `protobuf:"bytes,1,opt,name=denom,proto3" json:"denom,omitempty" yaml:"denom"` + AuthorityMetadata DenomAuthorityMetadata `protobuf:"bytes,2,opt,name=authority_metadata,json=authorityMetadata,proto3" json:"authority_metadata" yaml:"authority_metadata"` +} + +func (m *GenesisDenom) Reset() { *m = GenesisDenom{} } +func (m *GenesisDenom) String() string { return proto.CompactTextString(m) } +func (*GenesisDenom) ProtoMessage() {} +func (*GenesisDenom) Descriptor() ([]byte, []int) { + return fileDescriptor_b001fa8c2a4a126e, []int{1} +} +func (m *GenesisDenom) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *GenesisDenom) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_GenesisDenom.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *GenesisDenom) XXX_Merge(src proto.Message) { + xxx_messageInfo_GenesisDenom.Merge(m, src) +} +func (m *GenesisDenom) XXX_Size() int { + return m.Size() +} +func (m *GenesisDenom) XXX_DiscardUnknown() { + xxx_messageInfo_GenesisDenom.DiscardUnknown(m) +} + +var xxx_messageInfo_GenesisDenom proto.InternalMessageInfo + +func (m *GenesisDenom) GetDenom() string { + if m != nil { + return m.Denom + } + return "" +} + +func (m *GenesisDenom) GetAuthorityMetadata() DenomAuthorityMetadata { + if m != nil { + return m.AuthorityMetadata + } + return DenomAuthorityMetadata{} +} + +func init() { + proto.RegisterType((*GenesisState)(nil), "desmos.tokenfactory.v1beta1.GenesisState") + proto.RegisterType((*GenesisDenom)(nil), "desmos.tokenfactory.v1beta1.GenesisDenom") +} + +func init() { + proto.RegisterFile("desmos/tokenfactory/v1beta1/genesis.proto", fileDescriptor_b001fa8c2a4a126e) +} + +var fileDescriptor_b001fa8c2a4a126e = []byte{ + // 381 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xd2, 0x4c, 0x49, 0x2d, 0xce, + 0xcd, 0x2f, 0xd6, 0x2f, 0xc9, 0xcf, 0x4e, 0xcd, 0x4b, 0x4b, 0x4c, 0x2e, 0xc9, 0x2f, 0xaa, 0xd4, + 0x2f, 0x33, 0x4c, 0x4a, 0x2d, 0x49, 0x34, 0xd4, 0x4f, 0x4f, 0xcd, 0x4b, 0x2d, 0xce, 0x2c, 0xd6, + 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x92, 0x86, 0x28, 0xd5, 0x43, 0x56, 0xaa, 0x07, 0x55, 0x2a, + 0x25, 0x98, 0x98, 0x9b, 0x99, 0x97, 0xaf, 0x0f, 0x26, 0x21, 0xea, 0xa5, 0x44, 0xd2, 0xf3, 0xd3, + 0xf3, 0xc1, 0x4c, 0x7d, 0x10, 0x0b, 0x2a, 0xaa, 0x81, 0xcf, 0xc2, 0x82, 0xc4, 0xa2, 0xc4, 0xdc, + 0x62, 0x62, 0x54, 0xe6, 0xe6, 0xa7, 0xa4, 0xe6, 0x40, 0x55, 0x2a, 0x9d, 0x61, 0xe4, 0xe2, 0x71, + 0x87, 0xb8, 0x35, 0xb8, 0x24, 0xb1, 0x24, 0x55, 0xc8, 0x8d, 0x8b, 0x0d, 0x62, 0x94, 0x04, 0xa3, + 0x02, 0xa3, 0x06, 0xb7, 0x91, 0xb2, 0x1e, 0x1e, 0xb7, 0xeb, 0x05, 0x80, 0x95, 0x3a, 0x71, 0x9e, + 0xb8, 0x27, 0xcf, 0xb0, 0xe2, 0xf9, 0x06, 0x2d, 0xc6, 0x20, 0xa8, 0x6e, 0xa1, 0x12, 0x2e, 0x3e, + 0xa8, 0xe2, 0xf8, 0x94, 0xd4, 0xbc, 0xfc, 0xdc, 0x62, 0x09, 0x26, 0x05, 0x66, 0x0d, 0x6e, 0x23, + 0x4d, 0xbc, 0xe6, 0x41, 0x9d, 0xe2, 0x02, 0xd2, 0xe1, 0xa4, 0x04, 0x32, 0xf5, 0xd3, 0x3d, 0x79, + 0xd1, 0xca, 0xc4, 0xdc, 0x1c, 0x2b, 0x25, 0x54, 0xe3, 0x94, 0x20, 0xd6, 0xf1, 0x42, 0x45, 0x5d, + 0x20, 0x82, 0x27, 0x11, 0xde, 0x01, 0x8b, 0x08, 0xa9, 0x71, 0xb1, 0x82, 0xd5, 0x83, 0x7d, 0xc3, + 0xe9, 0x24, 0xf0, 0xe9, 0x9e, 0x3c, 0x0f, 0xc4, 0x38, 0xb0, 0xb0, 0x52, 0x10, 0x44, 0x5a, 0xa8, + 0x8b, 0x91, 0x4b, 0x28, 0xb1, 0xb4, 0x24, 0x23, 0xbf, 0x28, 0xb3, 0xa4, 0x32, 0x3e, 0x37, 0xb5, + 0x24, 0x31, 0x25, 0xb1, 0x24, 0x51, 0x82, 0x09, 0x1c, 0x06, 0xc6, 0x78, 0xdd, 0x0c, 0xb6, 0xc8, + 0x11, 0xa6, 0xd7, 0x17, 0xaa, 0xd5, 0x49, 0x0d, 0xea, 0x7a, 0x49, 0x88, 0x75, 0x98, 0x86, 0x43, + 0x7d, 0x20, 0x98, 0x88, 0xae, 0xd5, 0x8a, 0xe5, 0xc5, 0x02, 0x79, 0x46, 0x27, 0xff, 0x13, 0x8f, + 0xe4, 0x18, 0x2f, 0x3c, 0x92, 0x63, 0x7c, 0xf0, 0x48, 0x8e, 0x71, 0xc2, 0x63, 0x39, 0x86, 0x0b, + 0x8f, 0xe5, 0x18, 0x6e, 0x3c, 0x96, 0x63, 0x88, 0x32, 0x4d, 0xcf, 0x2c, 0xc9, 0x28, 0x4d, 0xd2, + 0x4b, 0xce, 0xcf, 0xd5, 0x87, 0xb8, 0x4c, 0x37, 0x27, 0x31, 0xa9, 0x18, 0xca, 0xd6, 0x2f, 0x33, + 0xd5, 0xaf, 0x40, 0x8d, 0xfa, 0x92, 0xca, 0x82, 0xd4, 0xe2, 0x24, 0x36, 0x70, 0x94, 0x1b, 0x03, + 0x02, 0x00, 0x00, 0xff, 0xff, 0x5e, 0x5d, 0x33, 0x24, 0xb9, 0x02, 0x00, 0x00, +} + +func (this *GenesisDenom) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*GenesisDenom) + if !ok { + that2, ok := that.(GenesisDenom) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.Denom != that1.Denom { + return false + } + if !this.AuthorityMetadata.Equal(&that1.AuthorityMetadata) { + return false + } + return true +} +func (m *GenesisState) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *GenesisState) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *GenesisState) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.FactoryDenoms) > 0 { + for iNdEx := len(m.FactoryDenoms) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.FactoryDenoms[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } + { + size, err := m.Params.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *GenesisDenom) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *GenesisDenom) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *GenesisDenom) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.AuthorityMetadata.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + if len(m.Denom) > 0 { + i -= len(m.Denom) + copy(dAtA[i:], m.Denom) + i = encodeVarintGenesis(dAtA, i, uint64(len(m.Denom))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func encodeVarintGenesis(dAtA []byte, offset int, v uint64) int { + offset -= sovGenesis(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *GenesisState) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Params.Size() + n += 1 + l + sovGenesis(uint64(l)) + if len(m.FactoryDenoms) > 0 { + for _, e := range m.FactoryDenoms { + l = e.Size() + n += 1 + l + sovGenesis(uint64(l)) + } + } + return n +} + +func (m *GenesisDenom) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Denom) + if l > 0 { + n += 1 + l + sovGenesis(uint64(l)) + } + l = m.AuthorityMetadata.Size() + n += 1 + l + sovGenesis(uint64(l)) + return n +} + +func sovGenesis(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozGenesis(x uint64) (n int) { + return sovGenesis(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *GenesisState) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: GenesisState: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GenesisState: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Params", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Params.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field FactoryDenoms", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.FactoryDenoms = append(m.FactoryDenoms, GenesisDenom{}) + if err := m.FactoryDenoms[len(m.FactoryDenoms)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenesis(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenesis + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *GenesisDenom) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: GenesisDenom: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GenesisDenom: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Denom", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Denom = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AuthorityMetadata", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.AuthorityMetadata.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenesis(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenesis + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipGenesis(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenesis + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenesis + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenesis + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthGenesis + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupGenesis + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthGenesis + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthGenesis = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowGenesis = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupGenesis = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/tokenfactory/types/genesis_test.go b/x/tokenfactory/types/genesis_test.go new file mode 100644 index 0000000000..8263ede195 --- /dev/null +++ b/x/tokenfactory/types/genesis_test.go @@ -0,0 +1,133 @@ +package types_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/desmos-labs/desmos/v5/x/tokenfactory/types" +) + +func TestGenesisState_Validate(t *testing.T) { + for _, tc := range []struct { + name string + genState *types.GenesisState + shouldErr bool + }{ + { + name: "default is valid returns no error", + genState: types.DefaultGenesis(), + }, + { + name: "valid genesis state returns no error", + genState: &types.GenesisState{ + FactoryDenoms: []types.GenesisDenom{ + { + Denom: "factory/cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69/bitcoin", + AuthorityMetadata: types.DenomAuthorityMetadata{ + Admin: "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + }, + }, + }, + }, + }, + { + name: "different admin from creator returns no error", + genState: &types.GenesisState{ + FactoryDenoms: []types.GenesisDenom{ + { + Denom: "factory/cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69/bitcoin", + AuthorityMetadata: types.DenomAuthorityMetadata{ + Admin: "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + }, + }, + }, + }, + }, + { + name: "empty admin returns no error", + genState: &types.GenesisState{ + FactoryDenoms: []types.GenesisDenom{ + { + Denom: "factory/cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69/bitcoin", + AuthorityMetadata: types.DenomAuthorityMetadata{ + Admin: "", + }, + }, + }, + }, + }, + { + name: "no admin returns no error", + genState: &types.GenesisState{ + FactoryDenoms: []types.GenesisDenom{ + { + Denom: "factory/cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69/bitcoin", + }, + }, + }, + }, + { + name: "invalid admin returns error", + genState: &types.GenesisState{ + FactoryDenoms: []types.GenesisDenom{ + { + Denom: "factory/cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69/bitcoin", + AuthorityMetadata: types.DenomAuthorityMetadata{ + Admin: "moose", + }, + }, + }, + }, + shouldErr: true, + }, + { + name: "multiple denoms returns no error", + genState: &types.GenesisState{ + FactoryDenoms: []types.GenesisDenom{ + { + Denom: "factory/cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69/bitcoin", + AuthorityMetadata: types.DenomAuthorityMetadata{ + Admin: "", + }, + }, + { + Denom: "factory/cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69/litecoin", + AuthorityMetadata: types.DenomAuthorityMetadata{ + Admin: "", + }, + }, + }, + }, + }, + { + name: "duplicate denoms returns error", + genState: &types.GenesisState{ + FactoryDenoms: []types.GenesisDenom{ + { + Denom: "factory/cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69/bitcoin", + AuthorityMetadata: types.DenomAuthorityMetadata{ + Admin: "", + }, + }, + { + Denom: "factory/cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69/bitcoin", + AuthorityMetadata: types.DenomAuthorityMetadata{ + Admin: "", + }, + }, + }, + }, + shouldErr: true, + }, + } { + t.Run(tc.name, func(t *testing.T) { + err := tc.genState.Validate() + if tc.shouldErr { + require.Error(t, err) + } else { + require.NoError(t, err) + } + }) + } +} diff --git a/x/tokenfactory/types/keys.go b/x/tokenfactory/types/keys.go new file mode 100644 index 0000000000..9334055cf3 --- /dev/null +++ b/x/tokenfactory/types/keys.go @@ -0,0 +1,43 @@ +package types + +import "strings" + +const ( + ModuleName = "tokenfactory" + StoreKey = ModuleName + RouterKey = ModuleName + QuerierRoute = ModuleName + + ActionCreateDenom = "create_denom" + ActionMint = "tf_mint" + ActionBurn = "tf_burn" + ActionSetDenomMetadata = "set_denom_metadata" + ActionUpdateParams = "update_params" +) + +// KeySeparator is used to combine parts of the keys in the store +const KeySeparator = "|" + +var ( + DenomAuthorityMetadataKey = "authoritymetadata" + DenomsPrefixKey = "denoms" + CreatorPrefixKey = "creator" + ParamsPrefixKey = "params" +) + +// GetDenomPrefixStore returns the store prefix where all the data associated with a specific denom +// is stored +func GetDenomPrefixStore(denom string) []byte { + return []byte(strings.Join([]string{DenomsPrefixKey, denom, ""}, KeySeparator)) +} + +// GetCreatorsPrefix returns the store prefix where the list of the denoms created by a specific +// creator are stored +func GetCreatorPrefix(creator string) []byte { + return []byte(strings.Join([]string{CreatorPrefixKey, creator, ""}, KeySeparator)) +} + +// GetCreatorsPrefix returns the store prefix where a list of all creator addresses are stored +func GetCreatorsPrefix() []byte { + return []byte(strings.Join([]string{CreatorPrefixKey, ""}, KeySeparator)) +} diff --git a/x/tokenfactory/types/models.pb.go b/x/tokenfactory/types/models.pb.go new file mode 100644 index 0000000000..081cea091d --- /dev/null +++ b/x/tokenfactory/types/models.pb.go @@ -0,0 +1,352 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: desmos/tokenfactory/v1beta1/models.proto + +package types + +import ( + fmt "fmt" + _ "github.com/cosmos/cosmos-proto" + _ "github.com/cosmos/gogoproto/gogoproto" + proto "github.com/cosmos/gogoproto/proto" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// DenomAuthorityMetadata specifies metadata for addresses that have specific +// capabilities over a token factory denom. Right now there is only one Admin +// permission, but is planned to be extended to the future. +type DenomAuthorityMetadata struct { + // Can be empty for no admin, or a valid osmosis address + Admin string `protobuf:"bytes,1,opt,name=admin,proto3" json:"admin,omitempty" yaml:"admin"` +} + +func (m *DenomAuthorityMetadata) Reset() { *m = DenomAuthorityMetadata{} } +func (m *DenomAuthorityMetadata) String() string { return proto.CompactTextString(m) } +func (*DenomAuthorityMetadata) ProtoMessage() {} +func (*DenomAuthorityMetadata) Descriptor() ([]byte, []int) { + return fileDescriptor_7ae908e7df623a71, []int{0} +} +func (m *DenomAuthorityMetadata) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *DenomAuthorityMetadata) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_DenomAuthorityMetadata.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *DenomAuthorityMetadata) XXX_Merge(src proto.Message) { + xxx_messageInfo_DenomAuthorityMetadata.Merge(m, src) +} +func (m *DenomAuthorityMetadata) XXX_Size() int { + return m.Size() +} +func (m *DenomAuthorityMetadata) XXX_DiscardUnknown() { + xxx_messageInfo_DenomAuthorityMetadata.DiscardUnknown(m) +} + +var xxx_messageInfo_DenomAuthorityMetadata proto.InternalMessageInfo + +func (m *DenomAuthorityMetadata) GetAdmin() string { + if m != nil { + return m.Admin + } + return "" +} + +func init() { + proto.RegisterType((*DenomAuthorityMetadata)(nil), "desmos.tokenfactory.v1beta1.DenomAuthorityMetadata") +} + +func init() { + proto.RegisterFile("desmos/tokenfactory/v1beta1/models.proto", fileDescriptor_7ae908e7df623a71) +} + +var fileDescriptor_7ae908e7df623a71 = []byte{ + // 253 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xd2, 0x48, 0x49, 0x2d, 0xce, + 0xcd, 0x2f, 0xd6, 0x2f, 0xc9, 0xcf, 0x4e, 0xcd, 0x4b, 0x4b, 0x4c, 0x2e, 0xc9, 0x2f, 0xaa, 0xd4, + 0x2f, 0x33, 0x4c, 0x4a, 0x2d, 0x49, 0x34, 0xd4, 0xcf, 0xcd, 0x4f, 0x49, 0xcd, 0x29, 0xd6, 0x2b, + 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x92, 0x86, 0xa8, 0xd4, 0x43, 0x56, 0xa9, 0x07, 0x55, 0x29, 0x25, + 0x92, 0x9e, 0x9f, 0x9e, 0x0f, 0x56, 0xa7, 0x0f, 0x62, 0x41, 0xb4, 0x48, 0x49, 0x26, 0xe7, 0x83, + 0xb4, 0xc4, 0x43, 0x24, 0x20, 0x1c, 0x88, 0x94, 0x52, 0x1c, 0x97, 0x98, 0x4b, 0x6a, 0x5e, 0x7e, + 0xae, 0x63, 0x69, 0x49, 0x46, 0x7e, 0x51, 0x66, 0x49, 0xa5, 0x6f, 0x6a, 0x49, 0x62, 0x4a, 0x62, + 0x49, 0xa2, 0x90, 0x1d, 0x17, 0x6b, 0x62, 0x4a, 0x6e, 0x66, 0x9e, 0x04, 0xa3, 0x02, 0xa3, 0x06, + 0xa7, 0x93, 0xc6, 0xa7, 0x7b, 0xf2, 0x3c, 0x95, 0x89, 0xb9, 0x39, 0x56, 0x4a, 0x60, 0x61, 0xa5, + 0x4b, 0x5b, 0x74, 0x45, 0xa0, 0x46, 0x39, 0xa6, 0xa4, 0x14, 0xa5, 0x16, 0x17, 0x07, 0x97, 0x14, + 0x65, 0xe6, 0xa5, 0x07, 0x41, 0xb4, 0x59, 0xb1, 0xbc, 0x58, 0x20, 0xcf, 0xe8, 0xe4, 0x7f, 0xe2, + 0x91, 0x1c, 0xe3, 0x85, 0x47, 0x72, 0x8c, 0x0f, 0x1e, 0xc9, 0x31, 0x4e, 0x78, 0x2c, 0xc7, 0x70, + 0xe1, 0xb1, 0x1c, 0xc3, 0x8d, 0xc7, 0x72, 0x0c, 0x51, 0xa6, 0xe9, 0x99, 0x25, 0x19, 0xa5, 0x49, + 0x7a, 0xc9, 0xf9, 0xb9, 0xfa, 0x10, 0x2f, 0xe9, 0xe6, 0x24, 0x26, 0x15, 0x43, 0xd9, 0xfa, 0x65, + 0xa6, 0xfa, 0x15, 0xa8, 0xa1, 0x51, 0x52, 0x59, 0x90, 0x5a, 0x9c, 0xc4, 0x06, 0x76, 0xb7, 0x31, + 0x20, 0x00, 0x00, 0xff, 0xff, 0xb8, 0x7d, 0xe6, 0x6f, 0x31, 0x01, 0x00, 0x00, +} + +func (this *DenomAuthorityMetadata) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*DenomAuthorityMetadata) + if !ok { + that2, ok := that.(DenomAuthorityMetadata) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.Admin != that1.Admin { + return false + } + return true +} +func (m *DenomAuthorityMetadata) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *DenomAuthorityMetadata) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *DenomAuthorityMetadata) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Admin) > 0 { + i -= len(m.Admin) + copy(dAtA[i:], m.Admin) + i = encodeVarintModels(dAtA, i, uint64(len(m.Admin))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func encodeVarintModels(dAtA []byte, offset int, v uint64) int { + offset -= sovModels(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *DenomAuthorityMetadata) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Admin) + if l > 0 { + n += 1 + l + sovModels(uint64(l)) + } + return n +} + +func sovModels(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozModels(x uint64) (n int) { + return sovModels(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *DenomAuthorityMetadata) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowModels + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: DenomAuthorityMetadata: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: DenomAuthorityMetadata: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Admin", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowModels + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthModels + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthModels + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Admin = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipModels(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthModels + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipModels(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowModels + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowModels + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowModels + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthModels + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupModels + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthModels + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthModels = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowModels = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupModels = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/tokenfactory/types/msgs.go b/x/tokenfactory/types/msgs.go new file mode 100644 index 0000000000..32cc348b4f --- /dev/null +++ b/x/tokenfactory/types/msgs.go @@ -0,0 +1,256 @@ +package types + +import ( + "cosmossdk.io/errors" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/cosmos/cosmos-sdk/x/auth/migrations/legacytx" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" +) + +var ( + _ sdk.Msg = &MsgCreateDenom{} + _ legacytx.LegacyMsg = &MsgCreateDenom{} +) + +// NewMsgCreateDenom creates a new MsgCreateDenom instance +func NewMsgCreateDenom(subspaceID uint64, sender, subdenom string) *MsgCreateDenom { + return &MsgCreateDenom{ + SubspaceID: subspaceID, + Sender: sender, + Subdenom: subdenom, + } +} + +// ValidateBasic implements sdk.Msg +func (msg MsgCreateDenom) ValidateBasic() error { + if msg.SubspaceID == 0 { + return errors.Wrapf(sdkerrors.ErrInvalidRequest, "Invalid subspace id: %d", msg.SubspaceID) + } + + _, err := sdk.AccAddressFromBech32(msg.Sender) + if err != nil { + return errors.Wrapf(sdkerrors.ErrInvalidAddress, "Invalid sender address: %s", err) + } + + _, err = GetTokenDenom(msg.Sender, msg.Subdenom) + if err != nil { + return errors.Wrap(ErrInvalidDenom, err.Error()) + } + + return nil +} + +// GetSigners implements sdk.Msg +func (msg MsgCreateDenom) GetSigners() []sdk.AccAddress { + sender, _ := sdk.AccAddressFromBech32(msg.Sender) + return []sdk.AccAddress{sender} +} + +// Route implements legacytx.LegacyMsg +func (msg MsgCreateDenom) Route() string { return RouterKey } + +// Type implements legacytx.LegacyMsg +func (msg MsgCreateDenom) Type() string { return ActionCreateDenom } + +// GetSignBytes implements legacytx.LegacyMsg +func (msg MsgCreateDenom) GetSignBytes() []byte { + return sdk.MustSortJSON(AminoCdc.MustMarshalJSON(&msg)) +} + +// -------------------------------------------------------------------------------------------------------------------- + +var ( + _ sdk.Msg = &MsgMint{} + _ legacytx.LegacyMsg = &MsgMint{} +) + +// NewMsgMint creates a new MsgMint instance +func NewMsgMint(subspaceID uint64, sender string, amount sdk.Coin) *MsgMint { + return &MsgMint{ + SubspaceID: subspaceID, + Sender: sender, + Amount: amount, + } +} + +// ValidateBasic implements sdk.Msg +func (msg MsgMint) ValidateBasic() error { + if msg.SubspaceID == 0 { + return errors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid subspace id: %d", msg.SubspaceID) + } + + _, err := sdk.AccAddressFromBech32(msg.Sender) + if err != nil { + return errors.Wrapf(sdkerrors.ErrInvalidAddress, "Invalid sender address: %s", err) + } + + if !msg.Amount.IsValid() || msg.Amount.Amount.Equal(sdk.ZeroInt()) { + return errors.Wrap(sdkerrors.ErrInvalidCoins, msg.Amount.String()) + } + + return nil +} + +// GetSigners implements sdk.Msg +func (msg MsgMint) GetSigners() []sdk.AccAddress { + sender, _ := sdk.AccAddressFromBech32(msg.Sender) + return []sdk.AccAddress{sender} +} + +// Route implements legacytx.LegacyMsg +func (msg MsgMint) Route() string { return RouterKey } + +// Type implements legacytx.LegacyMsg +func (msg MsgMint) Type() string { return ActionMint } + +// MsgMint implements legacytx.LegacyMsg +func (msg MsgMint) GetSignBytes() []byte { + return sdk.MustSortJSON(AminoCdc.MustMarshalJSON(&msg)) +} + +// -------------------------------------------------------------------------------------------------------------------- + +var ( + _ sdk.Msg = &MsgBurn{} + _ legacytx.LegacyMsg = &MsgBurn{} +) + +// NewMsgCreateDenom creates a new MsgBurn instance +func NewMsgBurn(subspaceID uint64, sender string, amount sdk.Coin) *MsgBurn { + return &MsgBurn{ + SubspaceID: subspaceID, + Sender: sender, + Amount: amount, + } +} + +// ValidateBasic implements sdk.Msg +func (msg MsgBurn) ValidateBasic() error { + if msg.SubspaceID == 0 { + return errors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid subspace id: %d", msg.SubspaceID) + } + + _, err := sdk.AccAddressFromBech32(msg.Sender) + if err != nil { + return errors.Wrapf(sdkerrors.ErrInvalidAddress, "Invalid sender address: %s", err) + } + + if !msg.Amount.IsValid() || msg.Amount.Amount.Equal(sdk.ZeroInt()) { + return errors.Wrap(sdkerrors.ErrInvalidCoins, msg.Amount.String()) + } + + return nil +} + +// GetSigners implements sdk.Msg +func (msg MsgBurn) GetSigners() []sdk.AccAddress { + sender, _ := sdk.AccAddressFromBech32(msg.Sender) + return []sdk.AccAddress{sender} +} + +// Route implements legacytx.LegacyMsg +func (msg MsgBurn) Route() string { return RouterKey } + +// Type implements legacytx.LegacyMsg +func (msg MsgBurn) Type() string { return ActionBurn } + +// GetSignBytes implements legacytx.LegacyMsg +func (msg MsgBurn) GetSignBytes() []byte { + return sdk.MustSortJSON(AminoCdc.MustMarshalJSON(&msg)) +} + +// -------------------------------------------------------------------------------------------------------------------- + +var ( + _ sdk.Msg = &MsgSetDenomMetadata{} + _ legacytx.LegacyMsg = &MsgSetDenomMetadata{} +) + +// NewMsgCreateDenom creates a new MsgSetDenomMetadata instance +func NewMsgSetDenomMetadata(subspaceID uint64, sender string, metadata banktypes.Metadata) *MsgSetDenomMetadata { + return &MsgSetDenomMetadata{ + SubspaceID: subspaceID, + Sender: sender, + Metadata: metadata, + } +} + +// ValidateBasic implements sdk.Msg +func (msg MsgSetDenomMetadata) ValidateBasic() error { + if msg.SubspaceID == 0 { + return errors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid subspace id: %d", msg.SubspaceID) + } + + _, err := sdk.AccAddressFromBech32(msg.Sender) + if err != nil { + return errors.Wrapf(sdkerrors.ErrInvalidAddress, "Invalid sender address: %s", err) + } + + err = msg.Metadata.Validate() + if err != nil { + return err + } + + _, _, err = DeconstructDenom(msg.Metadata.Base) + return err +} + +// GetSigners implements sdk.Msg +func (msg MsgSetDenomMetadata) GetSigners() []sdk.AccAddress { + sender, _ := sdk.AccAddressFromBech32(msg.Sender) + return []sdk.AccAddress{sender} +} + +// Route implements legacytx.LegacyMsg +func (msg MsgSetDenomMetadata) Route() string { return RouterKey } + +// Type implements legacytx.LegacyMsg +func (msg MsgSetDenomMetadata) Type() string { return ActionSetDenomMetadata } + +// GetSignBytes implements legacytx.LegacyMsg +func (msg MsgSetDenomMetadata) GetSignBytes() []byte { + return sdk.MustSortJSON(AminoCdc.MustMarshalJSON(&msg)) +} + +// -------------------------------------------------------------------------------------------------------------------- + +var ( + _ sdk.Msg = &MsgUpdateParams{} + _ legacytx.LegacyMsg = &MsgUpdateParams{} +) + +// NewMsgUpdateParams creates a new MsgUpdateParams instance +func NewMsgUpdateParams(params Params, authority string) *MsgUpdateParams { + return &MsgUpdateParams{ + Params: params, + Authority: authority, + } +} + +// ValidateBasic implements sdk.Msg +func (msg MsgUpdateParams) ValidateBasic() error { + _, err := sdk.AccAddressFromBech32(msg.Authority) + if err != nil { + return errors.Wrapf(sdkerrors.ErrInvalidAddress, "Invalid authority address: %s", err) + } + + return msg.Params.Validate() +} + +// GetSigners implements sdk.Msg +func (msg MsgUpdateParams) GetSigners() []sdk.AccAddress { + sender, _ := sdk.AccAddressFromBech32(msg.Authority) + return []sdk.AccAddress{sender} +} + +// Route implements legacytx.LegacyMsg +func (msg MsgUpdateParams) Route() string { return RouterKey } + +// Type implements legacytx.LegacyMsg +func (msg MsgUpdateParams) Type() string { return ActionUpdateParams } + +// GetSignBytes implements legacytx.LegacyMsg +func (msg MsgUpdateParams) GetSignBytes() []byte { + return sdk.MustSortJSON(AminoCdc.MustMarshalJSON(&msg)) +} diff --git a/x/tokenfactory/types/msgs.pb.go b/x/tokenfactory/types/msgs.pb.go new file mode 100644 index 0000000000..d3bdcac853 --- /dev/null +++ b/x/tokenfactory/types/msgs.pb.go @@ -0,0 +1,2422 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: desmos/tokenfactory/v1beta1/msgs.proto + +package types + +import ( + context "context" + fmt "fmt" + _ "github.com/cosmos/cosmos-proto" + types "github.com/cosmos/cosmos-sdk/types" + _ "github.com/cosmos/cosmos-sdk/types/msgservice" + _ "github.com/cosmos/cosmos-sdk/types/tx/amino" + types1 "github.com/cosmos/cosmos-sdk/x/bank/types" + _ "github.com/cosmos/gogoproto/gogoproto" + grpc1 "github.com/cosmos/gogoproto/grpc" + proto "github.com/cosmos/gogoproto/proto" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// MsgCreateDenom represents the message to be used to create a denom for +// subspace +// +// Since: Desmos 6.0.0 +type MsgCreateDenom struct { + // Id of the subspace which manages the denom + SubspaceID uint64 `protobuf:"varint,1,opt,name=subspace_id,json=subspaceId,proto3" json:"subspace_id,omitempty" yaml:"subspace_id"` + // Address of user having the permission to manage subspace denoms + Sender string `protobuf:"bytes,2,opt,name=sender,proto3" json:"sender,omitempty" yaml:"sender"` + // Subdenom name of the creating denom + // It can be up to 44 "alphanumeric" characters long + Subdenom string `protobuf:"bytes,3,opt,name=subdenom,proto3" json:"subdenom,omitempty" yaml:"subdenom"` +} + +func (m *MsgCreateDenom) Reset() { *m = MsgCreateDenom{} } +func (m *MsgCreateDenom) String() string { return proto.CompactTextString(m) } +func (*MsgCreateDenom) ProtoMessage() {} +func (*MsgCreateDenom) Descriptor() ([]byte, []int) { + return fileDescriptor_096696d6347c943d, []int{0} +} +func (m *MsgCreateDenom) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgCreateDenom) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgCreateDenom.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgCreateDenom) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgCreateDenom.Merge(m, src) +} +func (m *MsgCreateDenom) XXX_Size() int { + return m.Size() +} +func (m *MsgCreateDenom) XXX_DiscardUnknown() { + xxx_messageInfo_MsgCreateDenom.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgCreateDenom proto.InternalMessageInfo + +func (m *MsgCreateDenom) GetSubspaceID() uint64 { + if m != nil { + return m.SubspaceID + } + return 0 +} + +func (m *MsgCreateDenom) GetSender() string { + if m != nil { + return m.Sender + } + return "" +} + +func (m *MsgCreateDenom) GetSubdenom() string { + if m != nil { + return m.Subdenom + } + return "" +} + +// MsgCreateDenomResponse represents the Msg/CreateDenom response type +// It returns the full string of the newly created denom +type MsgCreateDenomResponse struct { + // Name of the newly created denom + NewTokenDenom string `protobuf:"bytes,1,opt,name=new_token_denom,json=newTokenDenom,proto3" json:"new_token_denom,omitempty" yaml:"new_token_denom"` +} + +func (m *MsgCreateDenomResponse) Reset() { *m = MsgCreateDenomResponse{} } +func (m *MsgCreateDenomResponse) String() string { return proto.CompactTextString(m) } +func (*MsgCreateDenomResponse) ProtoMessage() {} +func (*MsgCreateDenomResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_096696d6347c943d, []int{1} +} +func (m *MsgCreateDenomResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgCreateDenomResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgCreateDenomResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgCreateDenomResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgCreateDenomResponse.Merge(m, src) +} +func (m *MsgCreateDenomResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgCreateDenomResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgCreateDenomResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgCreateDenomResponse proto.InternalMessageInfo + +func (m *MsgCreateDenomResponse) GetNewTokenDenom() string { + if m != nil { + return m.NewTokenDenom + } + return "" +} + +// MsgMint represents the message to be used to mint subspace tokens to treasury +// account +// +// Since: Desmos 6.0.0 +type MsgMint struct { + // Id of the subspace which manages the denom + SubspaceID uint64 `protobuf:"varint,1,opt,name=subspace_id,json=subspaceId,proto3" json:"subspace_id,omitempty" yaml:"subspace_id"` + // Address of user having the permission to manage subspace denoms + Sender string `protobuf:"bytes,2,opt,name=sender,proto3" json:"sender,omitempty" yaml:"sender"` + // Amount of the minting subspace tokens + Amount types.Coin `protobuf:"bytes,3,opt,name=amount,proto3,castrepeated=github.com/cosmos/cosmos-sdk/types.Coins" json:"amount" yaml:"amount"` +} + +func (m *MsgMint) Reset() { *m = MsgMint{} } +func (m *MsgMint) String() string { return proto.CompactTextString(m) } +func (*MsgMint) ProtoMessage() {} +func (*MsgMint) Descriptor() ([]byte, []int) { + return fileDescriptor_096696d6347c943d, []int{2} +} +func (m *MsgMint) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgMint) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgMint.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgMint) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgMint.Merge(m, src) +} +func (m *MsgMint) XXX_Size() int { + return m.Size() +} +func (m *MsgMint) XXX_DiscardUnknown() { + xxx_messageInfo_MsgMint.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgMint proto.InternalMessageInfo + +func (m *MsgMint) GetSubspaceID() uint64 { + if m != nil { + return m.SubspaceID + } + return 0 +} + +func (m *MsgMint) GetSender() string { + if m != nil { + return m.Sender + } + return "" +} + +func (m *MsgMint) GetAmount() types.Coin { + if m != nil { + return m.Amount + } + return types.Coin{} +} + +// MsgMintResponse represents the Msg/Mint response type +// +// Since: Desmos 6.0.0 +type MsgMintResponse struct { +} + +func (m *MsgMintResponse) Reset() { *m = MsgMintResponse{} } +func (m *MsgMintResponse) String() string { return proto.CompactTextString(m) } +func (*MsgMintResponse) ProtoMessage() {} +func (*MsgMintResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_096696d6347c943d, []int{3} +} +func (m *MsgMintResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgMintResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgMintResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgMintResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgMintResponse.Merge(m, src) +} +func (m *MsgMintResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgMintResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgMintResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgMintResponse proto.InternalMessageInfo + +// MsgBurn represents the message to be used to burn subspace tokens from +// treasury account +// +// Since: Desmos 6.0.0 +type MsgBurn struct { + // Id of the subspace which manages the denom + SubspaceID uint64 `protobuf:"varint,1,opt,name=subspace_id,json=subspaceId,proto3" json:"subspace_id,omitempty" yaml:"subspace_id"` + // Address of user having the permission to manage subspace denoms + Sender string `protobuf:"bytes,2,opt,name=sender,proto3" json:"sender,omitempty" yaml:"sender"` + // Amount of the burning subspace tokens + Amount types.Coin `protobuf:"bytes,3,opt,name=amount,proto3,castrepeated=github.com/cosmos/cosmos-sdk/types.Coins" json:"amount" yaml:"amount"` +} + +func (m *MsgBurn) Reset() { *m = MsgBurn{} } +func (m *MsgBurn) String() string { return proto.CompactTextString(m) } +func (*MsgBurn) ProtoMessage() {} +func (*MsgBurn) Descriptor() ([]byte, []int) { + return fileDescriptor_096696d6347c943d, []int{4} +} +func (m *MsgBurn) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgBurn) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgBurn.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgBurn) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgBurn.Merge(m, src) +} +func (m *MsgBurn) XXX_Size() int { + return m.Size() +} +func (m *MsgBurn) XXX_DiscardUnknown() { + xxx_messageInfo_MsgBurn.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgBurn proto.InternalMessageInfo + +func (m *MsgBurn) GetSubspaceID() uint64 { + if m != nil { + return m.SubspaceID + } + return 0 +} + +func (m *MsgBurn) GetSender() string { + if m != nil { + return m.Sender + } + return "" +} + +func (m *MsgBurn) GetAmount() types.Coin { + if m != nil { + return m.Amount + } + return types.Coin{} +} + +// MsgBurnResponse represents the Msg/Burn response type +// +// Since: Desmos 6.0.0 +type MsgBurnResponse struct { +} + +func (m *MsgBurnResponse) Reset() { *m = MsgBurnResponse{} } +func (m *MsgBurnResponse) String() string { return proto.CompactTextString(m) } +func (*MsgBurnResponse) ProtoMessage() {} +func (*MsgBurnResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_096696d6347c943d, []int{5} +} +func (m *MsgBurnResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgBurnResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgBurnResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgBurnResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgBurnResponse.Merge(m, src) +} +func (m *MsgBurnResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgBurnResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgBurnResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgBurnResponse proto.InternalMessageInfo + +// MsgSetDenomMetadata represents the message to be used to set the subspace +// token's bank metadata +// +// Since: Desmos 6.0.0 +type MsgSetDenomMetadata struct { + // Id of the subspace which manages the denom + SubspaceID uint64 `protobuf:"varint,1,opt,name=subspace_id,json=subspaceId,proto3" json:"subspace_id,omitempty" yaml:"subspace_id"` + // Address of user having the permission to manage subspace denoms + Sender string `protobuf:"bytes,2,opt,name=sender,proto3" json:"sender,omitempty" yaml:"sender"` + // Metadata of the denom + Metadata types1.Metadata `protobuf:"bytes,3,opt,name=metadata,proto3" json:"metadata" yaml:"metadata"` +} + +func (m *MsgSetDenomMetadata) Reset() { *m = MsgSetDenomMetadata{} } +func (m *MsgSetDenomMetadata) String() string { return proto.CompactTextString(m) } +func (*MsgSetDenomMetadata) ProtoMessage() {} +func (*MsgSetDenomMetadata) Descriptor() ([]byte, []int) { + return fileDescriptor_096696d6347c943d, []int{6} +} +func (m *MsgSetDenomMetadata) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgSetDenomMetadata) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgSetDenomMetadata.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgSetDenomMetadata) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgSetDenomMetadata.Merge(m, src) +} +func (m *MsgSetDenomMetadata) XXX_Size() int { + return m.Size() +} +func (m *MsgSetDenomMetadata) XXX_DiscardUnknown() { + xxx_messageInfo_MsgSetDenomMetadata.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgSetDenomMetadata proto.InternalMessageInfo + +func (m *MsgSetDenomMetadata) GetSubspaceID() uint64 { + if m != nil { + return m.SubspaceID + } + return 0 +} + +func (m *MsgSetDenomMetadata) GetSender() string { + if m != nil { + return m.Sender + } + return "" +} + +func (m *MsgSetDenomMetadata) GetMetadata() types1.Metadata { + if m != nil { + return m.Metadata + } + return types1.Metadata{} +} + +// MsgSetDenomMetadataResponse represents the Msg/SetDenomMetadata response type +// +// Since: Desmos 6.0.0 +type MsgSetDenomMetadataResponse struct { +} + +func (m *MsgSetDenomMetadataResponse) Reset() { *m = MsgSetDenomMetadataResponse{} } +func (m *MsgSetDenomMetadataResponse) String() string { return proto.CompactTextString(m) } +func (*MsgSetDenomMetadataResponse) ProtoMessage() {} +func (*MsgSetDenomMetadataResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_096696d6347c943d, []int{7} +} +func (m *MsgSetDenomMetadataResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgSetDenomMetadataResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgSetDenomMetadataResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgSetDenomMetadataResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgSetDenomMetadataResponse.Merge(m, src) +} +func (m *MsgSetDenomMetadataResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgSetDenomMetadataResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgSetDenomMetadataResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgSetDenomMetadataResponse proto.InternalMessageInfo + +// MsgUpdateParams is the Msg/UpdateParams request type. +// +// Since: Desmos 6.0.0 +type MsgUpdateParams struct { + // authority is the address that controls the module (defaults to x/gov unless + // overwritten). + Authority string `protobuf:"bytes,1,opt,name=authority,proto3" json:"authority,omitempty" yaml:"authority"` + // params defines the parameters to update. + // + // NOTE: All parameters must be supplied. + Params Params `protobuf:"bytes,2,opt,name=params,proto3" json:"params" yaml:"params"` +} + +func (m *MsgUpdateParams) Reset() { *m = MsgUpdateParams{} } +func (m *MsgUpdateParams) String() string { return proto.CompactTextString(m) } +func (*MsgUpdateParams) ProtoMessage() {} +func (*MsgUpdateParams) Descriptor() ([]byte, []int) { + return fileDescriptor_096696d6347c943d, []int{8} +} +func (m *MsgUpdateParams) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgUpdateParams) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgUpdateParams.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgUpdateParams) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgUpdateParams.Merge(m, src) +} +func (m *MsgUpdateParams) XXX_Size() int { + return m.Size() +} +func (m *MsgUpdateParams) XXX_DiscardUnknown() { + xxx_messageInfo_MsgUpdateParams.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgUpdateParams proto.InternalMessageInfo + +func (m *MsgUpdateParams) GetAuthority() string { + if m != nil { + return m.Authority + } + return "" +} + +func (m *MsgUpdateParams) GetParams() Params { + if m != nil { + return m.Params + } + return Params{} +} + +// MsgUpdateParamsResponse represents the Msg/UpdateParams response type +// +// Since: Desmos 6.0.0 +type MsgUpdateParamsResponse struct { +} + +func (m *MsgUpdateParamsResponse) Reset() { *m = MsgUpdateParamsResponse{} } +func (m *MsgUpdateParamsResponse) String() string { return proto.CompactTextString(m) } +func (*MsgUpdateParamsResponse) ProtoMessage() {} +func (*MsgUpdateParamsResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_096696d6347c943d, []int{9} +} +func (m *MsgUpdateParamsResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgUpdateParamsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgUpdateParamsResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgUpdateParamsResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgUpdateParamsResponse.Merge(m, src) +} +func (m *MsgUpdateParamsResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgUpdateParamsResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgUpdateParamsResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgUpdateParamsResponse proto.InternalMessageInfo + +func init() { + proto.RegisterType((*MsgCreateDenom)(nil), "desmos.tokenfactory.v1beta1.MsgCreateDenom") + proto.RegisterType((*MsgCreateDenomResponse)(nil), "desmos.tokenfactory.v1beta1.MsgCreateDenomResponse") + proto.RegisterType((*MsgMint)(nil), "desmos.tokenfactory.v1beta1.MsgMint") + proto.RegisterType((*MsgMintResponse)(nil), "desmos.tokenfactory.v1beta1.MsgMintResponse") + proto.RegisterType((*MsgBurn)(nil), "desmos.tokenfactory.v1beta1.MsgBurn") + proto.RegisterType((*MsgBurnResponse)(nil), "desmos.tokenfactory.v1beta1.MsgBurnResponse") + proto.RegisterType((*MsgSetDenomMetadata)(nil), "desmos.tokenfactory.v1beta1.MsgSetDenomMetadata") + proto.RegisterType((*MsgSetDenomMetadataResponse)(nil), "desmos.tokenfactory.v1beta1.MsgSetDenomMetadataResponse") + proto.RegisterType((*MsgUpdateParams)(nil), "desmos.tokenfactory.v1beta1.MsgUpdateParams") + proto.RegisterType((*MsgUpdateParamsResponse)(nil), "desmos.tokenfactory.v1beta1.MsgUpdateParamsResponse") +} + +func init() { + proto.RegisterFile("desmos/tokenfactory/v1beta1/msgs.proto", fileDescriptor_096696d6347c943d) +} + +var fileDescriptor_096696d6347c943d = []byte{ + // 822 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x96, 0x4d, 0x4f, 0xdb, 0x48, + 0x18, 0xc7, 0x63, 0x60, 0xb3, 0x30, 0xe1, 0xd5, 0xb0, 0xbc, 0x98, 0xc5, 0x46, 0x5e, 0x76, 0x95, + 0xcd, 0x82, 0xbd, 0xc0, 0xa2, 0x5d, 0xe5, 0x86, 0x61, 0x0f, 0xac, 0x14, 0xed, 0x2a, 0x6c, 0x85, + 0x84, 0x2a, 0x45, 0x93, 0x78, 0x6a, 0xac, 0x60, 0x4f, 0xe4, 0x99, 0x40, 0x73, 0xa9, 0xaa, 0x1e, + 0x39, 0xf5, 0xdc, 0x73, 0x0f, 0x6d, 0x4f, 0x39, 0xf4, 0x03, 0xf4, 0xc8, 0x11, 0xf5, 0xd4, 0x53, + 0x5a, 0x85, 0x43, 0x8e, 0x95, 0xf2, 0x09, 0x2a, 0x8f, 0xc7, 0x8e, 0x13, 0x5a, 0xd2, 0xdc, 0x38, + 0xf4, 0x02, 0xe3, 0x79, 0xfe, 0xcf, 0xcb, 0xfc, 0xe6, 0xf1, 0xe3, 0x80, 0x5f, 0x4c, 0x44, 0x1c, + 0x4c, 0x74, 0x8a, 0xcb, 0xc8, 0x7d, 0x00, 0x4b, 0x14, 0x7b, 0x35, 0xfd, 0x6c, 0xb3, 0x88, 0x28, + 0xdc, 0xd4, 0x1d, 0x62, 0x11, 0xad, 0xe2, 0x61, 0x8a, 0xc5, 0xe5, 0x40, 0xa7, 0xc5, 0x75, 0x1a, + 0xd7, 0x49, 0x33, 0xd0, 0xb1, 0x5d, 0xac, 0xb3, 0xbf, 0x81, 0x5e, 0x9a, 0xb3, 0xb0, 0x85, 0xd9, + 0x52, 0xf7, 0x57, 0x7c, 0x57, 0x2e, 0x61, 0x96, 0xad, 0x08, 0x09, 0x8a, 0xb2, 0x94, 0xb0, 0xed, + 0xde, 0xb0, 0xbb, 0xe5, 0xc8, 0xee, 0x3f, 0x70, 0xfb, 0x52, 0x60, 0x2f, 0x04, 0x81, 0x83, 0x07, + 0x6e, 0x5a, 0xe0, 0xae, 0x0e, 0xb1, 0xf4, 0x33, 0x56, 0x3a, 0x37, 0xa4, 0x6f, 0x3b, 0x61, 0x05, + 0x7a, 0xd0, 0xe1, 0x21, 0xd4, 0xb6, 0x00, 0x26, 0x73, 0xc4, 0xda, 0xf3, 0x10, 0xa4, 0x68, 0x1f, + 0xb9, 0xd8, 0x11, 0xff, 0x06, 0x29, 0x52, 0x2d, 0x92, 0x0a, 0x2c, 0xa1, 0x82, 0x6d, 0x2e, 0x0a, + 0xab, 0x42, 0x7a, 0xc4, 0x58, 0x6b, 0x36, 0x14, 0x70, 0xc8, 0xb7, 0x0f, 0xf6, 0xdb, 0x0d, 0x45, + 0xac, 0x41, 0xe7, 0x34, 0xab, 0xc6, 0xa4, 0x6a, 0x1e, 0x84, 0x4f, 0x07, 0xa6, 0xb8, 0x0b, 0x92, + 0x04, 0xb9, 0x26, 0xf2, 0x16, 0x87, 0x56, 0x85, 0xf4, 0x98, 0xf1, 0x6b, 0xbb, 0xa1, 0x4c, 0x70, + 0x1f, 0xb6, 0xaf, 0xbe, 0x7d, 0xbd, 0x31, 0xc7, 0xcf, 0xb3, 0x6b, 0x9a, 0x1e, 0x22, 0xe4, 0x90, + 0x7a, 0xb6, 0x6b, 0xe5, 0xb9, 0xa3, 0xa8, 0x83, 0x51, 0x52, 0x2d, 0x9a, 0x7e, 0x55, 0x8b, 0xc3, + 0x2c, 0xc8, 0x6c, 0xbb, 0xa1, 0x4c, 0x45, 0x89, 0x99, 0x45, 0xcd, 0x47, 0xa2, 0xec, 0xcf, 0x4f, + 0x5a, 0xf5, 0x0c, 0xf7, 0xbe, 0x68, 0xd5, 0x33, 0x3f, 0x70, 0x0e, 0xdd, 0x27, 0x54, 0xef, 0x83, + 0xf9, 0xee, 0x9d, 0x3c, 0x22, 0x15, 0xec, 0x12, 0x24, 0x1a, 0x60, 0xca, 0x45, 0xe7, 0x05, 0xc6, + 0xad, 0x10, 0x24, 0x16, 0x58, 0x62, 0xa9, 0xdd, 0x50, 0xe6, 0x83, 0xc4, 0x3d, 0x02, 0x35, 0x3f, + 0xe1, 0xa2, 0xf3, 0xff, 0xfd, 0x8d, 0x20, 0xfa, 0x9b, 0x21, 0xf0, 0x7d, 0x8e, 0x58, 0x39, 0xdb, + 0xa5, 0x77, 0x88, 0xe5, 0x85, 0x00, 0x92, 0xd0, 0xc1, 0x55, 0x97, 0x32, 0x94, 0xa9, 0xad, 0x25, + 0x8d, 0xeb, 0xfd, 0xc6, 0x0c, 0xdb, 0x5a, 0xdb, 0xc3, 0xb6, 0x6b, 0x1c, 0x5d, 0x36, 0x94, 0x44, + 0x27, 0x45, 0xe0, 0xa6, 0xbe, 0x7a, 0xaf, 0xa4, 0x2d, 0x9b, 0x9e, 0x54, 0x8b, 0x5a, 0x09, 0x3b, + 0xbc, 0x13, 0xf9, 0xbf, 0x0d, 0x62, 0x96, 0x75, 0x5a, 0xab, 0x20, 0xc2, 0x22, 0x90, 0x67, 0xad, + 0x7a, 0x66, 0xfc, 0x14, 0x59, 0xb0, 0x54, 0x2b, 0xf8, 0xbd, 0x4e, 0x5e, 0xb4, 0xea, 0x19, 0x21, + 0xcf, 0x2b, 0xc8, 0xca, 0x3d, 0xf7, 0x34, 0xd9, 0xb9, 0x27, 0x1f, 0x9b, 0x3a, 0x03, 0xa6, 0xf8, + 0x32, 0xbc, 0x99, 0x90, 0xaa, 0x51, 0xf5, 0xdc, 0x6f, 0x54, 0x07, 0xa6, 0xea, 0x63, 0xe3, 0x54, + 0xfd, 0x65, 0x44, 0xf5, 0xf9, 0x10, 0x98, 0xcd, 0x11, 0xeb, 0x10, 0x51, 0xd6, 0xbb, 0x39, 0x44, + 0xa1, 0x09, 0x29, 0xbc, 0x43, 0x84, 0x8f, 0xc0, 0xa8, 0xc3, 0xab, 0xe2, 0x88, 0x57, 0x3a, 0x88, + 0xdd, 0x72, 0x84, 0x38, 0x2c, 0xdd, 0xf8, 0x91, 0x63, 0xe6, 0x63, 0x22, 0x74, 0x56, 0x03, 0x56, + 0x51, 0xb0, 0x6c, 0xa6, 0x87, 0x96, 0xd4, 0xa1, 0xd5, 0x8b, 0x43, 0x5d, 0x01, 0xcb, 0x9f, 0xd9, + 0x8e, 0x28, 0x7e, 0x14, 0x18, 0xd9, 0x7b, 0x15, 0x13, 0x52, 0xf4, 0x1f, 0x1b, 0xaf, 0xe2, 0x3f, + 0x60, 0x0c, 0x56, 0xe9, 0x09, 0xf6, 0x6c, 0x5a, 0xe3, 0x33, 0x64, 0xbd, 0xdd, 0x50, 0xa6, 0xf9, + 0xe5, 0x87, 0xa6, 0x2f, 0x03, 0xe8, 0xb8, 0x8b, 0x47, 0x20, 0x19, 0x0c, 0x6d, 0x86, 0x31, 0xb5, + 0xf5, 0x93, 0x76, 0xcb, 0x97, 0x49, 0x0b, 0x0a, 0x30, 0xa4, 0xee, 0x76, 0x0b, 0x02, 0x70, 0x0a, + 0x3c, 0x5c, 0xf6, 0x4f, 0x9f, 0x41, 0x27, 0x91, 0x8f, 0x61, 0x8d, 0x63, 0x78, 0x18, 0xfb, 0x78, + 0xd4, 0xf4, 0x9e, 0xd3, 0xa9, 0x4b, 0x60, 0xa1, 0x67, 0x2b, 0x84, 0xb1, 0xf5, 0x72, 0x04, 0x0c, + 0xe7, 0x88, 0x25, 0x62, 0x90, 0x8a, 0x7f, 0x55, 0x7e, 0xbb, 0xb5, 0xe6, 0xee, 0x71, 0x2c, 0x6d, + 0x0f, 0x20, 0x8e, 0x66, 0xf7, 0x31, 0x18, 0x61, 0x33, 0x77, 0xad, 0x9f, 0xb3, 0xaf, 0x92, 0xd6, + 0xbf, 0x46, 0x15, 0x8f, 0xcd, 0x26, 0x4f, 0xdf, 0xd8, 0xbe, 0xaa, 0x7f, 0xec, 0xf8, 0x3b, 0x28, + 0x3e, 0x02, 0xd3, 0x37, 0xde, 0xbf, 0xdf, 0xfb, 0x45, 0xe8, 0xf5, 0x90, 0xfe, 0x1a, 0xd4, 0x23, + 0xca, 0xef, 0x81, 0xf1, 0xae, 0xce, 0xed, 0x5b, 0x7d, 0x5c, 0x2d, 0xfd, 0x31, 0x88, 0x3a, 0xcc, + 0x29, 0x7d, 0xf7, 0xd8, 0xef, 0x43, 0xe3, 0xdf, 0xcb, 0xa6, 0x2c, 0x5c, 0x35, 0x65, 0xe1, 0x43, + 0x53, 0x16, 0x9e, 0x5e, 0xcb, 0x89, 0xab, 0x6b, 0x39, 0xf1, 0xee, 0x5a, 0x4e, 0x1c, 0xef, 0xc4, + 0x66, 0x62, 0x90, 0x60, 0xe3, 0x14, 0x16, 0x09, 0x5f, 0xeb, 0x67, 0x3b, 0x5d, 0x0d, 0xea, 0xd5, + 0x82, 0x31, 0x59, 0x4c, 0xb2, 0x5f, 0x35, 0xdb, 0x9f, 0x02, 0x00, 0x00, 0xff, 0xff, 0x1d, 0x0f, + 0xfe, 0x10, 0xe3, 0x09, 0x00, 0x00, +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// MsgClient is the client API for Msg service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type MsgClient interface { + // CreateDenom allows an account to create a new denom for subspace. It + // requires a subspace and a sub denomination. The (subspace_treasury_address, + // sub_denomination) tuple must be unique and cannot be re-used. + // + // The resulting denom created is defined as + // . The resulting denom's admin is + // originally set to be the subspace treasury account, and this can not be + // changed later. + // + // Since: Desmos 6.0.0 + CreateDenom(ctx context.Context, in *MsgCreateDenom, opts ...grpc.CallOption) (*MsgCreateDenomResponse, error) + // Mint allows subspace admins to mint more of a token. + // + // Since: Desmos 6.0.0 + Mint(ctx context.Context, in *MsgMint, opts ...grpc.CallOption) (*MsgMintResponse, error) + // Burn allows subspace admins to burn a token. + // For now, we only support burning from the treasury account. + // + // Since: Desmos 6.0.0 + Burn(ctx context.Context, in *MsgBurn, opts ...grpc.CallOption) (*MsgBurnResponse, error) + // SetDenomMetadata allows subspace admins to set the denom's bank metadata. + // + // Since: Desmos 6.0.0 + SetDenomMetadata(ctx context.Context, in *MsgSetDenomMetadata, opts ...grpc.CallOption) (*MsgSetDenomMetadataResponse, error) + // UpdateParams defines a (governance) operation for updating the module + // parameters. The authority defaults to the x/gov module account. + // + // Since: Desmos 6.0.0 + UpdateParams(ctx context.Context, in *MsgUpdateParams, opts ...grpc.CallOption) (*MsgUpdateParamsResponse, error) +} + +type msgClient struct { + cc grpc1.ClientConn +} + +func NewMsgClient(cc grpc1.ClientConn) MsgClient { + return &msgClient{cc} +} + +func (c *msgClient) CreateDenom(ctx context.Context, in *MsgCreateDenom, opts ...grpc.CallOption) (*MsgCreateDenomResponse, error) { + out := new(MsgCreateDenomResponse) + err := c.cc.Invoke(ctx, "/desmos.tokenfactory.v1beta1.Msg/CreateDenom", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *msgClient) Mint(ctx context.Context, in *MsgMint, opts ...grpc.CallOption) (*MsgMintResponse, error) { + out := new(MsgMintResponse) + err := c.cc.Invoke(ctx, "/desmos.tokenfactory.v1beta1.Msg/Mint", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *msgClient) Burn(ctx context.Context, in *MsgBurn, opts ...grpc.CallOption) (*MsgBurnResponse, error) { + out := new(MsgBurnResponse) + err := c.cc.Invoke(ctx, "/desmos.tokenfactory.v1beta1.Msg/Burn", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *msgClient) SetDenomMetadata(ctx context.Context, in *MsgSetDenomMetadata, opts ...grpc.CallOption) (*MsgSetDenomMetadataResponse, error) { + out := new(MsgSetDenomMetadataResponse) + err := c.cc.Invoke(ctx, "/desmos.tokenfactory.v1beta1.Msg/SetDenomMetadata", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *msgClient) UpdateParams(ctx context.Context, in *MsgUpdateParams, opts ...grpc.CallOption) (*MsgUpdateParamsResponse, error) { + out := new(MsgUpdateParamsResponse) + err := c.cc.Invoke(ctx, "/desmos.tokenfactory.v1beta1.Msg/UpdateParams", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// MsgServer is the server API for Msg service. +type MsgServer interface { + // CreateDenom allows an account to create a new denom for subspace. It + // requires a subspace and a sub denomination. The (subspace_treasury_address, + // sub_denomination) tuple must be unique and cannot be re-used. + // + // The resulting denom created is defined as + // . The resulting denom's admin is + // originally set to be the subspace treasury account, and this can not be + // changed later. + // + // Since: Desmos 6.0.0 + CreateDenom(context.Context, *MsgCreateDenom) (*MsgCreateDenomResponse, error) + // Mint allows subspace admins to mint more of a token. + // + // Since: Desmos 6.0.0 + Mint(context.Context, *MsgMint) (*MsgMintResponse, error) + // Burn allows subspace admins to burn a token. + // For now, we only support burning from the treasury account. + // + // Since: Desmos 6.0.0 + Burn(context.Context, *MsgBurn) (*MsgBurnResponse, error) + // SetDenomMetadata allows subspace admins to set the denom's bank metadata. + // + // Since: Desmos 6.0.0 + SetDenomMetadata(context.Context, *MsgSetDenomMetadata) (*MsgSetDenomMetadataResponse, error) + // UpdateParams defines a (governance) operation for updating the module + // parameters. The authority defaults to the x/gov module account. + // + // Since: Desmos 6.0.0 + UpdateParams(context.Context, *MsgUpdateParams) (*MsgUpdateParamsResponse, error) +} + +// UnimplementedMsgServer can be embedded to have forward compatible implementations. +type UnimplementedMsgServer struct { +} + +func (*UnimplementedMsgServer) CreateDenom(ctx context.Context, req *MsgCreateDenom) (*MsgCreateDenomResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method CreateDenom not implemented") +} +func (*UnimplementedMsgServer) Mint(ctx context.Context, req *MsgMint) (*MsgMintResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Mint not implemented") +} +func (*UnimplementedMsgServer) Burn(ctx context.Context, req *MsgBurn) (*MsgBurnResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Burn not implemented") +} +func (*UnimplementedMsgServer) SetDenomMetadata(ctx context.Context, req *MsgSetDenomMetadata) (*MsgSetDenomMetadataResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method SetDenomMetadata not implemented") +} +func (*UnimplementedMsgServer) UpdateParams(ctx context.Context, req *MsgUpdateParams) (*MsgUpdateParamsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method UpdateParams not implemented") +} + +func RegisterMsgServer(s grpc1.Server, srv MsgServer) { + s.RegisterService(&_Msg_serviceDesc, srv) +} + +func _Msg_CreateDenom_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgCreateDenom) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).CreateDenom(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/desmos.tokenfactory.v1beta1.Msg/CreateDenom", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).CreateDenom(ctx, req.(*MsgCreateDenom)) + } + return interceptor(ctx, in, info, handler) +} + +func _Msg_Mint_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgMint) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).Mint(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/desmos.tokenfactory.v1beta1.Msg/Mint", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).Mint(ctx, req.(*MsgMint)) + } + return interceptor(ctx, in, info, handler) +} + +func _Msg_Burn_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgBurn) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).Burn(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/desmos.tokenfactory.v1beta1.Msg/Burn", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).Burn(ctx, req.(*MsgBurn)) + } + return interceptor(ctx, in, info, handler) +} + +func _Msg_SetDenomMetadata_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgSetDenomMetadata) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).SetDenomMetadata(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/desmos.tokenfactory.v1beta1.Msg/SetDenomMetadata", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).SetDenomMetadata(ctx, req.(*MsgSetDenomMetadata)) + } + return interceptor(ctx, in, info, handler) +} + +func _Msg_UpdateParams_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgUpdateParams) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).UpdateParams(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/desmos.tokenfactory.v1beta1.Msg/UpdateParams", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).UpdateParams(ctx, req.(*MsgUpdateParams)) + } + return interceptor(ctx, in, info, handler) +} + +var _Msg_serviceDesc = grpc.ServiceDesc{ + ServiceName: "desmos.tokenfactory.v1beta1.Msg", + HandlerType: (*MsgServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "CreateDenom", + Handler: _Msg_CreateDenom_Handler, + }, + { + MethodName: "Mint", + Handler: _Msg_Mint_Handler, + }, + { + MethodName: "Burn", + Handler: _Msg_Burn_Handler, + }, + { + MethodName: "SetDenomMetadata", + Handler: _Msg_SetDenomMetadata_Handler, + }, + { + MethodName: "UpdateParams", + Handler: _Msg_UpdateParams_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "desmos/tokenfactory/v1beta1/msgs.proto", +} + +func (m *MsgCreateDenom) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgCreateDenom) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgCreateDenom) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Subdenom) > 0 { + i -= len(m.Subdenom) + copy(dAtA[i:], m.Subdenom) + i = encodeVarintMsgs(dAtA, i, uint64(len(m.Subdenom))) + i-- + dAtA[i] = 0x1a + } + if len(m.Sender) > 0 { + i -= len(m.Sender) + copy(dAtA[i:], m.Sender) + i = encodeVarintMsgs(dAtA, i, uint64(len(m.Sender))) + i-- + dAtA[i] = 0x12 + } + if m.SubspaceID != 0 { + i = encodeVarintMsgs(dAtA, i, uint64(m.SubspaceID)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *MsgCreateDenomResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgCreateDenomResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgCreateDenomResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.NewTokenDenom) > 0 { + i -= len(m.NewTokenDenom) + copy(dAtA[i:], m.NewTokenDenom) + i = encodeVarintMsgs(dAtA, i, uint64(len(m.NewTokenDenom))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgMint) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgMint) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgMint) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Amount.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintMsgs(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + if len(m.Sender) > 0 { + i -= len(m.Sender) + copy(dAtA[i:], m.Sender) + i = encodeVarintMsgs(dAtA, i, uint64(len(m.Sender))) + i-- + dAtA[i] = 0x12 + } + if m.SubspaceID != 0 { + i = encodeVarintMsgs(dAtA, i, uint64(m.SubspaceID)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *MsgMintResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgMintResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgMintResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *MsgBurn) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgBurn) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgBurn) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Amount.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintMsgs(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + if len(m.Sender) > 0 { + i -= len(m.Sender) + copy(dAtA[i:], m.Sender) + i = encodeVarintMsgs(dAtA, i, uint64(len(m.Sender))) + i-- + dAtA[i] = 0x12 + } + if m.SubspaceID != 0 { + i = encodeVarintMsgs(dAtA, i, uint64(m.SubspaceID)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *MsgBurnResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgBurnResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgBurnResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *MsgSetDenomMetadata) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgSetDenomMetadata) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgSetDenomMetadata) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Metadata.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintMsgs(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + if len(m.Sender) > 0 { + i -= len(m.Sender) + copy(dAtA[i:], m.Sender) + i = encodeVarintMsgs(dAtA, i, uint64(len(m.Sender))) + i-- + dAtA[i] = 0x12 + } + if m.SubspaceID != 0 { + i = encodeVarintMsgs(dAtA, i, uint64(m.SubspaceID)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *MsgSetDenomMetadataResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgSetDenomMetadataResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgSetDenomMetadataResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *MsgUpdateParams) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgUpdateParams) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgUpdateParams) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Params.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintMsgs(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + if len(m.Authority) > 0 { + i -= len(m.Authority) + copy(dAtA[i:], m.Authority) + i = encodeVarintMsgs(dAtA, i, uint64(len(m.Authority))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgUpdateParamsResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgUpdateParamsResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgUpdateParamsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func encodeVarintMsgs(dAtA []byte, offset int, v uint64) int { + offset -= sovMsgs(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *MsgCreateDenom) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.SubspaceID != 0 { + n += 1 + sovMsgs(uint64(m.SubspaceID)) + } + l = len(m.Sender) + if l > 0 { + n += 1 + l + sovMsgs(uint64(l)) + } + l = len(m.Subdenom) + if l > 0 { + n += 1 + l + sovMsgs(uint64(l)) + } + return n +} + +func (m *MsgCreateDenomResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.NewTokenDenom) + if l > 0 { + n += 1 + l + sovMsgs(uint64(l)) + } + return n +} + +func (m *MsgMint) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.SubspaceID != 0 { + n += 1 + sovMsgs(uint64(m.SubspaceID)) + } + l = len(m.Sender) + if l > 0 { + n += 1 + l + sovMsgs(uint64(l)) + } + l = m.Amount.Size() + n += 1 + l + sovMsgs(uint64(l)) + return n +} + +func (m *MsgMintResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *MsgBurn) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.SubspaceID != 0 { + n += 1 + sovMsgs(uint64(m.SubspaceID)) + } + l = len(m.Sender) + if l > 0 { + n += 1 + l + sovMsgs(uint64(l)) + } + l = m.Amount.Size() + n += 1 + l + sovMsgs(uint64(l)) + return n +} + +func (m *MsgBurnResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *MsgSetDenomMetadata) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.SubspaceID != 0 { + n += 1 + sovMsgs(uint64(m.SubspaceID)) + } + l = len(m.Sender) + if l > 0 { + n += 1 + l + sovMsgs(uint64(l)) + } + l = m.Metadata.Size() + n += 1 + l + sovMsgs(uint64(l)) + return n +} + +func (m *MsgSetDenomMetadataResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *MsgUpdateParams) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Authority) + if l > 0 { + n += 1 + l + sovMsgs(uint64(l)) + } + l = m.Params.Size() + n += 1 + l + sovMsgs(uint64(l)) + return n +} + +func (m *MsgUpdateParamsResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func sovMsgs(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozMsgs(x uint64) (n int) { + return sovMsgs(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *MsgCreateDenom) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgCreateDenom: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgCreateDenom: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field SubspaceID", wireType) + } + m.SubspaceID = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.SubspaceID |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Sender", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthMsgs + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthMsgs + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Sender = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Subdenom", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthMsgs + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthMsgs + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Subdenom = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipMsgs(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthMsgs + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgCreateDenomResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgCreateDenomResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgCreateDenomResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field NewTokenDenom", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthMsgs + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthMsgs + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.NewTokenDenom = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipMsgs(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthMsgs + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgMint) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgMint: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgMint: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field SubspaceID", wireType) + } + m.SubspaceID = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.SubspaceID |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Sender", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthMsgs + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthMsgs + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Sender = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthMsgs + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthMsgs + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Amount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipMsgs(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthMsgs + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgMintResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgMintResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgMintResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipMsgs(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthMsgs + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgBurn) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgBurn: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgBurn: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field SubspaceID", wireType) + } + m.SubspaceID = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.SubspaceID |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Sender", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthMsgs + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthMsgs + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Sender = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthMsgs + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthMsgs + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Amount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipMsgs(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthMsgs + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgBurnResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgBurnResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgBurnResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipMsgs(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthMsgs + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgSetDenomMetadata) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgSetDenomMetadata: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgSetDenomMetadata: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field SubspaceID", wireType) + } + m.SubspaceID = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.SubspaceID |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Sender", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthMsgs + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthMsgs + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Sender = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Metadata", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthMsgs + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthMsgs + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Metadata.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipMsgs(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthMsgs + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgSetDenomMetadataResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgSetDenomMetadataResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgSetDenomMetadataResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipMsgs(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthMsgs + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgUpdateParams) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgUpdateParams: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgUpdateParams: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Authority", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthMsgs + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthMsgs + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Authority = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Params", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthMsgs + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthMsgs + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Params.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipMsgs(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthMsgs + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgUpdateParamsResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgUpdateParamsResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgUpdateParamsResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipMsgs(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthMsgs + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipMsgs(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowMsgs + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowMsgs + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowMsgs + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthMsgs + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupMsgs + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthMsgs + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthMsgs = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowMsgs = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupMsgs = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/tokenfactory/types/msgs_test.go b/x/tokenfactory/types/msgs_test.go new file mode 100644 index 0000000000..e7f24c4aed --- /dev/null +++ b/x/tokenfactory/types/msgs_test.go @@ -0,0 +1,407 @@ +package types_test + +import ( + "testing" + + sdk "github.com/cosmos/cosmos-sdk/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + "github.com/stretchr/testify/require" + + "github.com/desmos-labs/desmos/v5/x/tokenfactory/types" +) + +var msgCreateDenom = types.NewMsgCreateDenom( + 1, + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + "minttoken", +) + +func TestMsgCreateDenom_Route(t *testing.T) { + require.Equal(t, types.RouterKey, msgCreateDenom.Route()) +} + +func TestMsgCreateDenom_Type(t *testing.T) { + require.Equal(t, types.ActionCreateDenom, msgCreateDenom.Type()) +} + +func TestMsgCreateDenom_ValidateBasic(t *testing.T) { + testCases := []struct { + name string + msg *types.MsgCreateDenom + shouldErr bool + }{ + { + name: "invalid subspace id returns error", + msg: types.NewMsgCreateDenom( + 0, + msgCreateDenom.Sender, + msgCreateDenom.Subdenom, + ), + shouldErr: true, + }, + { + name: "invalid sender returns error", + msg: types.NewMsgCreateDenom( + msgCreateDenom.SubspaceID, + "", + msgCreateDenom.Subdenom, + ), + shouldErr: true, + }, + { + name: "invalid subdenom returns error", + msg: types.NewMsgCreateDenom( + msgCreateDenom.SubspaceID, + msgCreateDenom.Sender, + "%invalid%", + ), + shouldErr: true, + }, + { + name: "valid message returns no error", + msg: msgCreateDenom, + }, + } + + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + err := tc.msg.ValidateBasic() + if tc.shouldErr { + require.Error(t, err) + } else { + require.NoError(t, err) + } + }) + } +} + +func TestMsgCreateDenom_GetSignBytes(t *testing.T) { + expected := `{"type":"desmos/MsgCreateDenom","value":{"sender":"cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69","subdenom":"minttoken","subspace_id":"1"}}` + require.Equal(t, expected, string(msgCreateDenom.GetSignBytes())) +} + +func TestMsgCreateDenom_GetSigners(t *testing.T) { + addr, _ := sdk.AccAddressFromBech32(msgCreateDenom.Sender) + require.Equal(t, []sdk.AccAddress{addr}, msgCreateDenom.GetSigners()) +} + +// -------------------------------------------------------------------------------------------------------------------- + +var msgMint = types.NewMsgMint( + 1, + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + sdk.NewCoin("uminttoken", sdk.NewInt(100)), +) + +func TestMsgMint_Route(t *testing.T) { + require.Equal(t, types.RouterKey, msgMint.Route()) +} + +func TestMsgMint_Type(t *testing.T) { + require.Equal(t, types.ActionMint, msgMint.Type()) +} + +func TestMsgMint_ValidateBasic(t *testing.T) { + testCases := []struct { + name string + msg *types.MsgMint + shouldErr bool + }{ + { + name: "invalid subspace id returns error", + msg: types.NewMsgMint( + 0, + msgMint.Sender, + msgMint.Amount, + ), + shouldErr: true, + }, + { + name: "invalid sender returns error", + msg: types.NewMsgMint( + msgMint.SubspaceID, + "", + msgMint.Amount, + ), + shouldErr: true, + }, + { + name: "invalid amount returns error", + msg: types.NewMsgMint( + msgMint.SubspaceID, + msgMint.Sender, + sdk.Coin{Denom: "%invalid%", Amount: sdk.NewInt(100)}, + ), + shouldErr: true, + }, + { + name: "valid message returns no error", + msg: msgMint, + }, + } + + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + err := tc.msg.ValidateBasic() + if tc.shouldErr { + require.Error(t, err) + } else { + require.NoError(t, err) + } + }) + } +} + +func TestMsgMint_GetSignBytes(t *testing.T) { + expected := `{"type":"desmos/MsgMint","value":{"amount":{"amount":"100","denom":"uminttoken"},"sender":"cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69","subspace_id":"1"}}` + require.Equal(t, expected, string(msgMint.GetSignBytes())) +} + +func TestMsgMint_GetSigners(t *testing.T) { + addr, _ := sdk.AccAddressFromBech32(msgMint.Sender) + require.Equal(t, []sdk.AccAddress{addr}, msgMint.GetSigners()) +} + +// -------------------------------------------------------------------------------------------------------------------- + +var msgBurn = types.NewMsgBurn( + 1, + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + sdk.NewCoin("uminttoken", sdk.NewInt(100)), +) + +func TestMsgBurn_Route(t *testing.T) { + require.Equal(t, types.RouterKey, msgBurn.Route()) +} + +func TestMsgBurn_Type(t *testing.T) { + require.Equal(t, types.ActionBurn, msgBurn.Type()) +} + +func TestMsgBurn_ValidateBasic(t *testing.T) { + testCases := []struct { + name string + msg *types.MsgBurn + shouldErr bool + }{ + { + name: "invalid subspace id returns error", + msg: types.NewMsgBurn( + 0, + msgBurn.Sender, + msgBurn.Amount, + ), + shouldErr: true, + }, + { + name: "invalid sender returns error", + msg: types.NewMsgBurn( + msgBurn.SubspaceID, + "", + msgBurn.Amount, + ), + shouldErr: true, + }, + { + name: "invalid amount returns error", + msg: types.NewMsgBurn( + msgBurn.SubspaceID, + msgBurn.Sender, + sdk.Coin{Denom: "%invalid%", Amount: sdk.NewInt(100)}, + ), + shouldErr: true, + }, + { + name: "valid message returns no error", + msg: msgBurn, + }, + } + + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + err := tc.msg.ValidateBasic() + if tc.shouldErr { + require.Error(t, err) + } else { + require.NoError(t, err) + } + }) + } +} + +func TestMsgBurn_GetSignBytes(t *testing.T) { + expected := `{"type":"desmos/MsgBurn","value":{"amount":{"amount":"100","denom":"uminttoken"},"sender":"cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69","subspace_id":"1"}}` + require.Equal(t, expected, string(msgBurn.GetSignBytes())) +} + +func TestMsgBurn_GetSigners(t *testing.T) { + addr, _ := sdk.AccAddressFromBech32(msgBurn.Sender) + require.Equal(t, []sdk.AccAddress{addr}, msgBurn.GetSigners()) +} + +// -------------------------------------------------------------------------------------------------------------------- + +var msgSetDenomMetadata = types.NewMsgSetDenomMetadata( + 1, + "cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69", + banktypes.Metadata{ + Name: "Mint Token", + Symbol: "MTK", + Description: "The custom token of the test subspace.", + DenomUnits: []*banktypes.DenomUnit{ + {Denom: "factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/uminttoken", Exponent: uint32(0), Aliases: nil}, + {Denom: "minttoken", Exponent: uint32(6), Aliases: []string{"minttoken"}}, + }, + Base: "factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/uminttoken", + Display: "minttoken", + }, +) + +func TestMsgSetDenomMetadata_Route(t *testing.T) { + require.Equal(t, types.RouterKey, msgSetDenomMetadata.Route()) +} + +func TestMsgSetDenomMetadata_Type(t *testing.T) { + require.Equal(t, types.ActionSetDenomMetadata, msgSetDenomMetadata.Type()) +} + +func TestMsgSetDenomMetadata_ValidateBasic(t *testing.T) { + testCases := []struct { + name string + msg *types.MsgSetDenomMetadata + shouldErr bool + }{ + { + name: "invalid subspace id returns error", + msg: types.NewMsgSetDenomMetadata( + 0, + msgSetDenomMetadata.Sender, + msgSetDenomMetadata.Metadata, + ), + shouldErr: true, + }, + { + name: "invalid sender returns error", + msg: types.NewMsgSetDenomMetadata( + msgSetDenomMetadata.SubspaceID, + "", + msgSetDenomMetadata.Metadata, + ), + shouldErr: true, + }, + { + name: "invalid metadata returns error", + msg: types.NewMsgSetDenomMetadata( + msgSetDenomMetadata.SubspaceID, + msgSetDenomMetadata.Sender, + banktypes.Metadata{}, + ), + shouldErr: true, + }, + { + name: "invalid metadata base returns error", + msg: types.NewMsgSetDenomMetadata( + msgSetDenomMetadata.SubspaceID, + msgSetDenomMetadata.Sender, + banktypes.Metadata{ + Name: "Mint Token", + Symbol: "MINTTOKEN", + Description: "The custom token of the test subspace.", + DenomUnits: []*banktypes.DenomUnit{ + {Denom: "uminttoken", Exponent: uint32(0), Aliases: nil}, + }, + Base: "uminttoken", + Display: "uminttoken", + }, + ), + shouldErr: true, + }, + { + name: "valid message returns no error", + msg: msgSetDenomMetadata, + }, + } + + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + err := tc.msg.ValidateBasic() + if tc.shouldErr { + require.Error(t, err) + } else { + require.NoError(t, err) + } + }) + } +} + +func TestMsgSetDenomMetadata_GetSignBytes(t *testing.T) { + expected := `{"type":"desmos/MsgSetDenomMetadata","value":{"metadata":{"base":"factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/uminttoken","denom_units":[{"denom":"factory/cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47/uminttoken"},{"aliases":["minttoken"],"denom":"minttoken","exponent":6}],"description":"The custom token of the test subspace.","display":"minttoken","name":"Mint Token","symbol":"MTK"},"sender":"cosmos1qzskhrcjnkdz2ln4yeafzsdwht8ch08j4wed69","subspace_id":"1"}}` + require.Equal(t, expected, string(msgSetDenomMetadata.GetSignBytes())) +} + +func TestMsgSetDenomMetadata_GetSigners(t *testing.T) { + addr, _ := sdk.AccAddressFromBech32(msgSetDenomMetadata.Sender) + require.Equal(t, []sdk.AccAddress{addr}, msgSetDenomMetadata.GetSigners()) +} + +// -------------------------------------------------------------------------------------------------------------------- + +var msgUpdateParams = types.NewMsgUpdateParams( + types.DefaultParams(), + "cosmos13t6y2nnugtshwuy0zkrq287a95lyy8vzleaxmd", +) + +func TestMsgUpdateParams_Route(t *testing.T) { + require.Equal(t, types.RouterKey, msgUpdateParams.Route()) +} + +func TestMsgUpdateParams_Type(t *testing.T) { + require.Equal(t, types.ActionUpdateParams, msgUpdateParams.Type()) +} + +func TestMsgUpdateParams_ValidateBasic(t *testing.T) { + testCases := []struct { + name string + msg *types.MsgUpdateParams + shouldErr bool + }{ + { + name: "invalid authority returns error", + msg: types.NewMsgUpdateParams( + types.DefaultParams(), + "invalid", + ), + shouldErr: true, + }, + { + name: "valid message returns no error", + msg: msgUpdateParams, + }, + } + + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + err := tc.msg.ValidateBasic() + if tc.shouldErr { + require.Error(t, err) + } else { + require.NoError(t, err) + } + }) + } +} + +func TestMsgUpdateParams_GetSignBytes(t *testing.T) { + expected := `{"type":"desmos/x/tokenfactory/MsgUpdateParams","value":{"authority":"cosmos13t6y2nnugtshwuy0zkrq287a95lyy8vzleaxmd","params":{"denom_creation_fee":[{"amount":"10000000000","denom":"stake"}]}}}` + require.Equal(t, expected, string(msgUpdateParams.GetSignBytes())) +} + +func TestMsgUpdateParams_GetSigners(t *testing.T) { + addr, _ := sdk.AccAddressFromBech32(msgUpdateParams.Authority) + require.Equal(t, []sdk.AccAddress{addr}, msgUpdateParams.GetSigners()) +} diff --git a/x/tokenfactory/types/params.go b/x/tokenfactory/types/params.go new file mode 100644 index 0000000000..263915e771 --- /dev/null +++ b/x/tokenfactory/types/params.go @@ -0,0 +1,28 @@ +package types + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// NewParams creates a new params instance +func NewParams(denomCreationFee sdk.Coins) Params { + return Params{ + DenomCreationFee: denomCreationFee, + } +} + +// DefaultParams creates a default params instance +func DefaultParams() Params { + return Params{ + DenomCreationFee: sdk.NewCoins(sdk.NewInt64Coin(sdk.DefaultBondDenom, 10_000_000_000)), // 10,000 DSM + } +} + +// Validate implements fmt.Validator +func (p Params) Validate() error { + if err := p.DenomCreationFee.Validate(); err != nil { + return err + } + + return nil +} diff --git a/x/tokenfactory/types/params.pb.go b/x/tokenfactory/types/params.pb.go new file mode 100644 index 0000000000..521549b7fb --- /dev/null +++ b/x/tokenfactory/types/params.pb.go @@ -0,0 +1,348 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: desmos/tokenfactory/v1beta1/params.proto + +package types + +import ( + fmt "fmt" + github_com_cosmos_cosmos_sdk_types "github.com/cosmos/cosmos-sdk/types" + types "github.com/cosmos/cosmos-sdk/types" + _ "github.com/cosmos/cosmos-sdk/types/tx/amino" + _ "github.com/cosmos/gogoproto/gogoproto" + proto "github.com/cosmos/gogoproto/proto" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// Params defines the parameters for the tokenfactory module. +// +// Since: Desmos 6.0.0 +type Params struct { + // DenomCreationFee defines the fee to be charged on the creation of a new + // denom. The fee is drawn from the subspace treasruy account, and + // burned. + DenomCreationFee github_com_cosmos_cosmos_sdk_types.Coins `protobuf:"bytes,1,rep,name=denom_creation_fee,json=denomCreationFee,proto3,castrepeated=github.com/cosmos/cosmos-sdk/types.Coins" json:"denom_creation_fee" yaml:"denom_creation_fee"` +} + +func (m *Params) Reset() { *m = Params{} } +func (m *Params) String() string { return proto.CompactTextString(m) } +func (*Params) ProtoMessage() {} +func (*Params) Descriptor() ([]byte, []int) { + return fileDescriptor_bc2a96561a4f8a18, []int{0} +} +func (m *Params) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Params) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Params.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *Params) XXX_Merge(src proto.Message) { + xxx_messageInfo_Params.Merge(m, src) +} +func (m *Params) XXX_Size() int { + return m.Size() +} +func (m *Params) XXX_DiscardUnknown() { + xxx_messageInfo_Params.DiscardUnknown(m) +} + +var xxx_messageInfo_Params proto.InternalMessageInfo + +func (m *Params) GetDenomCreationFee() github_com_cosmos_cosmos_sdk_types.Coins { + if m != nil { + return m.DenomCreationFee + } + return nil +} + +func init() { + proto.RegisterType((*Params)(nil), "desmos.tokenfactory.v1beta1.Params") +} + +func init() { + proto.RegisterFile("desmos/tokenfactory/v1beta1/params.proto", fileDescriptor_bc2a96561a4f8a18) +} + +var fileDescriptor_bc2a96561a4f8a18 = []byte{ + // 322 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x64, 0x90, 0x31, 0x4f, 0x02, 0x31, + 0x1c, 0xc5, 0xaf, 0x31, 0x61, 0x40, 0x07, 0x25, 0x0e, 0x82, 0xa6, 0x28, 0x13, 0x21, 0xa1, 0x0d, + 0x1a, 0x16, 0x46, 0x48, 0x5c, 0x35, 0x8e, 0x2e, 0xa4, 0x57, 0xfe, 0x9c, 0x17, 0xb8, 0xfe, 0xc9, + 0xb5, 0x12, 0xef, 0x2b, 0x38, 0x39, 0xfb, 0x09, 0x8c, 0x71, 0xe0, 0x63, 0x30, 0x32, 0x1a, 0x07, + 0x34, 0x30, 0xb0, 0xfb, 0x09, 0x0c, 0x6d, 0x35, 0xa8, 0xcb, 0xdd, 0x4b, 0xfb, 0xf2, 0x7b, 0xaf, + 0x2f, 0x5f, 0xed, 0x81, 0x4e, 0x50, 0x73, 0x83, 0x03, 0x50, 0x7d, 0x21, 0x0d, 0xa6, 0x19, 0x1f, + 0x37, 0x42, 0x30, 0xa2, 0xc1, 0x47, 0x22, 0x15, 0x89, 0x66, 0xa3, 0x14, 0x0d, 0x16, 0x0e, 0x9d, + 0x93, 0x6d, 0x3a, 0x99, 0x77, 0x96, 0xf6, 0x44, 0x12, 0x2b, 0xe4, 0xf6, 0xeb, 0xfc, 0xa5, 0xfd, + 0x08, 0x23, 0xb4, 0x92, 0xaf, 0x95, 0x3f, 0xa5, 0x12, 0x6d, 0x5e, 0x28, 0x34, 0xfc, 0xe4, 0x48, + 0x8c, 0x95, 0xbb, 0xaf, 0xbc, 0x91, 0x7c, 0xee, 0xd2, 0xc6, 0x16, 0x5e, 0x48, 0xbe, 0xd0, 0x03, + 0x85, 0x49, 0x57, 0xa6, 0x20, 0x4c, 0x8c, 0xaa, 0xdb, 0x07, 0x38, 0x20, 0xc7, 0x5b, 0xd5, 0xed, + 0xd3, 0x22, 0x73, 0x20, 0xb6, 0x06, 0x7d, 0xd7, 0x60, 0x1d, 0x8c, 0x55, 0x5b, 0x4e, 0xe7, 0xe5, + 0xe0, 0x73, 0x5e, 0x2e, 0x66, 0x22, 0x19, 0xb6, 0x2a, 0xff, 0x11, 0x95, 0xe7, 0xf7, 0x72, 0x35, + 0x8a, 0xcd, 0xcd, 0x6d, 0xc8, 0x24, 0x26, 0xdc, 0x57, 0x72, 0xbf, 0xba, 0xee, 0x0d, 0xb8, 0xc9, + 0x46, 0xa0, 0x2d, 0x4d, 0x3f, 0xae, 0x26, 0xb5, 0x9d, 0x21, 0x44, 0x42, 0x66, 0xdd, 0x75, 0x4f, + 0xfd, 0xb4, 0x9a, 0xd4, 0xc8, 0xd5, 0xae, 0xc5, 0x76, 0x3c, 0xf5, 0x1c, 0xa0, 0x75, 0x72, 0xbf, + 0x9a, 0xd4, 0x8e, 0xfc, 0x9c, 0x77, 0xbf, 0x07, 0x75, 0x2f, 0x6a, 0x5f, 0x4c, 0x17, 0x94, 0xcc, + 0x16, 0x94, 0x7c, 0x2c, 0x28, 0x79, 0x58, 0xd2, 0x60, 0xb6, 0xa4, 0xc1, 0xeb, 0x92, 0x06, 0xd7, + 0xcd, 0x8d, 0x3a, 0x0e, 0x51, 0x1f, 0x8a, 0x50, 0x7b, 0xcd, 0xc7, 0xcd, 0xbf, 0x44, 0xdb, 0x30, + 0xcc, 0xd9, 0xd1, 0xce, 0xbe, 0x02, 0x00, 0x00, 0xff, 0xff, 0x6c, 0xbc, 0xa1, 0x04, 0xc6, 0x01, + 0x00, 0x00, +} + +func (m *Params) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Params) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Params) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.DenomCreationFee) > 0 { + for iNdEx := len(m.DenomCreationFee) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.DenomCreationFee[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintParams(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func encodeVarintParams(dAtA []byte, offset int, v uint64) int { + offset -= sovParams(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *Params) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.DenomCreationFee) > 0 { + for _, e := range m.DenomCreationFee { + l = e.Size() + n += 1 + l + sovParams(uint64(l)) + } + } + return n +} + +func sovParams(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozParams(x uint64) (n int) { + return sovParams(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *Params) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Params: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Params: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field DenomCreationFee", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthParams + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthParams + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.DenomCreationFee = append(m.DenomCreationFee, types.Coin{}) + if err := m.DenomCreationFee[len(m.DenomCreationFee)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipParams(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthParams + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipParams(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowParams + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowParams + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowParams + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthParams + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupParams + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthParams + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthParams = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowParams = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupParams = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/tokenfactory/types/params_test.go b/x/tokenfactory/types/params_test.go new file mode 100644 index 0000000000..90bc0436b0 --- /dev/null +++ b/x/tokenfactory/types/params_test.go @@ -0,0 +1,47 @@ +package types_test + +import ( + "testing" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" + + "github.com/desmos-labs/desmos/v5/x/tokenfactory/types" +) + +func TestParams_Validate(t *testing.T) { + testCases := []struct { + name string + params types.Params + shouldErr bool + }{ + { + name: "invalid coins return error", + params: types.NewParams(sdk.Coins{sdk.Coin{Denom: "%invalid%", Amount: sdk.NewInt(100)}}), + shouldErr: true, + }, + { + name: "valid params return no error", + params: types.NewParams(sdk.NewCoins(sdk.Coin{Denom: "udsm", Amount: sdk.NewInt(100)})), + shouldErr: false, + }, + { + name: "default params return no error", + params: types.DefaultParams(), + shouldErr: false, + }, + } + + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + err := tc.params.Validate() + if tc.shouldErr { + require.Error(t, err) + } else { + require.NoError(t, err) + } + }) + } + +} diff --git a/x/tokenfactory/types/permissions.go b/x/tokenfactory/types/permissions.go new file mode 100644 index 0000000000..ad0f43e05f --- /dev/null +++ b/x/tokenfactory/types/permissions.go @@ -0,0 +1,12 @@ +package types + +// DONTCOVER + +import ( + subspacestypes "github.com/desmos-labs/desmos/v5/x/subspaces/types" +) + +var ( + // PermissionManageSubspaceTokens allows users to manage subspace tokens + PermissionManageSubspaceTokens = subspacestypes.RegisterPermission("manage custom subspace tokens") +) diff --git a/x/tokenfactory/types/query.go b/x/tokenfactory/types/query.go new file mode 100644 index 0000000000..f054f970ee --- /dev/null +++ b/x/tokenfactory/types/query.go @@ -0,0 +1,13 @@ +package types + +// NewQuerySubspaceDenomsRequest returns a new QuerySubspaceDenomsRequest instance +func NewQuerySubspaceDenomsRequest(subspaceID uint64) *QuerySubspaceDenomsRequest { + return &QuerySubspaceDenomsRequest{ + SubspaceId: subspaceID, + } +} + +// NewQueryParamsRequest returns a new QueryParamsRequest instance +func NewQueryParamsRequest() *QueryParamsRequest { + return &QueryParamsRequest{} +} diff --git a/x/tokenfactory/types/query.pb.go b/x/tokenfactory/types/query.pb.go new file mode 100644 index 0000000000..0e32435fac --- /dev/null +++ b/x/tokenfactory/types/query.pb.go @@ -0,0 +1,922 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: desmos/tokenfactory/v1beta1/query.proto + +package types + +import ( + context "context" + fmt "fmt" + _ "github.com/cosmos/cosmos-sdk/types/tx/amino" + _ "github.com/cosmos/gogoproto/gogoproto" + grpc1 "github.com/cosmos/gogoproto/grpc" + proto "github.com/cosmos/gogoproto/proto" + _ "google.golang.org/genproto/googleapis/api/annotations" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// QueryParamsRequest is the request type for the Query/Params RPC method. +type QueryParamsRequest struct { +} + +func (m *QueryParamsRequest) Reset() { *m = QueryParamsRequest{} } +func (m *QueryParamsRequest) String() string { return proto.CompactTextString(m) } +func (*QueryParamsRequest) ProtoMessage() {} +func (*QueryParamsRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_026c0f6cafecaba8, []int{0} +} +func (m *QueryParamsRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryParamsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryParamsRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryParamsRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryParamsRequest.Merge(m, src) +} +func (m *QueryParamsRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryParamsRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryParamsRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryParamsRequest proto.InternalMessageInfo + +// QueryParamsResponse is the response type for the Query/Params RPC method. +type QueryParamsResponse struct { + // params defines the parameters of the module. + Params Params `protobuf:"bytes,1,opt,name=params,proto3" json:"params"` +} + +func (m *QueryParamsResponse) Reset() { *m = QueryParamsResponse{} } +func (m *QueryParamsResponse) String() string { return proto.CompactTextString(m) } +func (*QueryParamsResponse) ProtoMessage() {} +func (*QueryParamsResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_026c0f6cafecaba8, []int{1} +} +func (m *QueryParamsResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryParamsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryParamsResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryParamsResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryParamsResponse.Merge(m, src) +} +func (m *QueryParamsResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryParamsResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryParamsResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryParamsResponse proto.InternalMessageInfo + +func (m *QueryParamsResponse) GetParams() Params { + if m != nil { + return m.Params + } + return Params{} +} + +// QuerySubspaceDenomsRequest defines the request structure for the +// SubspaceDenoms gRPC query. +type QuerySubspaceDenomsRequest struct { + SubspaceId uint64 `protobuf:"varint,1,opt,name=subspace_id,json=subspaceId,proto3" json:"subspace_id,omitempty" yaml:"creator"` +} + +func (m *QuerySubspaceDenomsRequest) Reset() { *m = QuerySubspaceDenomsRequest{} } +func (m *QuerySubspaceDenomsRequest) String() string { return proto.CompactTextString(m) } +func (*QuerySubspaceDenomsRequest) ProtoMessage() {} +func (*QuerySubspaceDenomsRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_026c0f6cafecaba8, []int{2} +} +func (m *QuerySubspaceDenomsRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QuerySubspaceDenomsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QuerySubspaceDenomsRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QuerySubspaceDenomsRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QuerySubspaceDenomsRequest.Merge(m, src) +} +func (m *QuerySubspaceDenomsRequest) XXX_Size() int { + return m.Size() +} +func (m *QuerySubspaceDenomsRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QuerySubspaceDenomsRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QuerySubspaceDenomsRequest proto.InternalMessageInfo + +func (m *QuerySubspaceDenomsRequest) GetSubspaceId() uint64 { + if m != nil { + return m.SubspaceId + } + return 0 +} + +// QuerySubspaceDenomsResponse defines the response structure for the +// SubspaceDenoms gRPC query. +type QuerySubspaceDenomsResponse struct { + Denoms []string `protobuf:"bytes,1,rep,name=denoms,proto3" json:"denoms,omitempty" yaml:"denoms"` +} + +func (m *QuerySubspaceDenomsResponse) Reset() { *m = QuerySubspaceDenomsResponse{} } +func (m *QuerySubspaceDenomsResponse) String() string { return proto.CompactTextString(m) } +func (*QuerySubspaceDenomsResponse) ProtoMessage() {} +func (*QuerySubspaceDenomsResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_026c0f6cafecaba8, []int{3} +} +func (m *QuerySubspaceDenomsResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QuerySubspaceDenomsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QuerySubspaceDenomsResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QuerySubspaceDenomsResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QuerySubspaceDenomsResponse.Merge(m, src) +} +func (m *QuerySubspaceDenomsResponse) XXX_Size() int { + return m.Size() +} +func (m *QuerySubspaceDenomsResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QuerySubspaceDenomsResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QuerySubspaceDenomsResponse proto.InternalMessageInfo + +func (m *QuerySubspaceDenomsResponse) GetDenoms() []string { + if m != nil { + return m.Denoms + } + return nil +} + +func init() { + proto.RegisterType((*QueryParamsRequest)(nil), "desmos.tokenfactory.v1beta1.QueryParamsRequest") + proto.RegisterType((*QueryParamsResponse)(nil), "desmos.tokenfactory.v1beta1.QueryParamsResponse") + proto.RegisterType((*QuerySubspaceDenomsRequest)(nil), "desmos.tokenfactory.v1beta1.QuerySubspaceDenomsRequest") + proto.RegisterType((*QuerySubspaceDenomsResponse)(nil), "desmos.tokenfactory.v1beta1.QuerySubspaceDenomsResponse") +} + +func init() { + proto.RegisterFile("desmos/tokenfactory/v1beta1/query.proto", fileDescriptor_026c0f6cafecaba8) +} + +var fileDescriptor_026c0f6cafecaba8 = []byte{ + // 443 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0x4f, 0x49, 0x2d, 0xce, + 0xcd, 0x2f, 0xd6, 0x2f, 0xc9, 0xcf, 0x4e, 0xcd, 0x4b, 0x4b, 0x4c, 0x2e, 0xc9, 0x2f, 0xaa, 0xd4, + 0x2f, 0x33, 0x4c, 0x4a, 0x2d, 0x49, 0x34, 0xd4, 0x2f, 0x2c, 0x4d, 0x2d, 0xaa, 0xd4, 0x2b, 0x28, + 0xca, 0x2f, 0xc9, 0x17, 0x92, 0x86, 0x28, 0xd4, 0x43, 0x56, 0xa8, 0x07, 0x55, 0x28, 0x25, 0x98, + 0x98, 0x9b, 0x99, 0x97, 0xaf, 0x0f, 0x26, 0x21, 0xea, 0xa5, 0x44, 0xd2, 0xf3, 0xd3, 0xf3, 0xc1, + 0x4c, 0x7d, 0x10, 0x0b, 0x2a, 0x2a, 0x93, 0x9e, 0x9f, 0x9f, 0x9e, 0x93, 0xaa, 0x9f, 0x58, 0x90, + 0xa9, 0x9f, 0x98, 0x97, 0x97, 0x5f, 0x92, 0x58, 0x92, 0x99, 0x9f, 0x57, 0x0c, 0x95, 0xd5, 0xc0, + 0xe7, 0x98, 0x82, 0xc4, 0xa2, 0xc4, 0x5c, 0xa8, 0x4a, 0x25, 0x11, 0x2e, 0xa1, 0x40, 0x90, 0xe3, + 0x02, 0xc0, 0x82, 0x41, 0xa9, 0x85, 0xa5, 0xa9, 0xc5, 0x25, 0x4a, 0xb1, 0x5c, 0xc2, 0x28, 0xa2, + 0xc5, 0x05, 0xf9, 0x79, 0xc5, 0xa9, 0x42, 0x6e, 0x5c, 0x6c, 0x10, 0xcd, 0x12, 0x8c, 0x0a, 0x8c, + 0x1a, 0xdc, 0x46, 0xca, 0x7a, 0x78, 0xfc, 0xa2, 0x07, 0xd1, 0xec, 0xc4, 0x79, 0xe2, 0x9e, 0x3c, + 0xc3, 0x8a, 0xe7, 0x1b, 0xb4, 0x18, 0x83, 0xa0, 0xba, 0x95, 0x02, 0xb9, 0xa4, 0xc0, 0xc6, 0x07, + 0x97, 0x26, 0x15, 0x17, 0x24, 0x26, 0xa7, 0xba, 0xa4, 0xe6, 0xe5, 0xc3, 0x2d, 0x17, 0x32, 0xe6, + 0xe2, 0x2e, 0x86, 0x4a, 0xc4, 0x67, 0xa6, 0x80, 0xad, 0x62, 0x71, 0x12, 0xfa, 0x74, 0x4f, 0x9e, + 0xaf, 0x32, 0x31, 0x37, 0xc7, 0x4a, 0x29, 0xb9, 0x28, 0x35, 0xb1, 0x24, 0xbf, 0x48, 0x29, 0x88, + 0x0b, 0xa6, 0xcc, 0x33, 0x45, 0xc9, 0x83, 0x4b, 0x1a, 0xab, 0x91, 0x50, 0x97, 0x6b, 0x72, 0xb1, + 0xa5, 0x80, 0x45, 0x24, 0x18, 0x15, 0x98, 0x35, 0x38, 0x9d, 0x04, 0x3f, 0xdd, 0x93, 0xe7, 0x85, + 0x18, 0x07, 0x11, 0x57, 0x0a, 0x82, 0x2a, 0x30, 0x7a, 0xcb, 0xc4, 0xc5, 0x0a, 0x36, 0x4a, 0x68, + 0x06, 0x23, 0x17, 0x1b, 0xc4, 0x13, 0x42, 0xfa, 0x78, 0x7d, 0x8a, 0x19, 0x82, 0x52, 0x06, 0xc4, + 0x6b, 0x80, 0x38, 0x51, 0x49, 0xbb, 0xe9, 0xf2, 0x93, 0xc9, 0x4c, 0xaa, 0x42, 0xca, 0xfa, 0x84, + 0x23, 0x4f, 0xe8, 0x04, 0x23, 0x17, 0x1f, 0xaa, 0x57, 0x85, 0xcc, 0x09, 0xdb, 0x88, 0x35, 0xbc, + 0xa5, 0x2c, 0x48, 0xd7, 0x08, 0x75, 0xb2, 0x33, 0xd8, 0xc9, 0xb6, 0x42, 0xd6, 0x78, 0x9d, 0x0c, + 0x8b, 0xa5, 0x62, 0xfd, 0x6a, 0xa4, 0x78, 0xad, 0xd5, 0x87, 0x84, 0xb7, 0x93, 0xff, 0x89, 0x47, + 0x72, 0x8c, 0x17, 0x1e, 0xc9, 0x31, 0x3e, 0x78, 0x24, 0xc7, 0x38, 0xe1, 0xb1, 0x1c, 0xc3, 0x85, + 0xc7, 0x72, 0x0c, 0x37, 0x1e, 0xcb, 0x31, 0x44, 0x99, 0xa6, 0x67, 0x96, 0x64, 0x94, 0x26, 0xe9, + 0x25, 0xe7, 0xe7, 0x42, 0x2d, 0xd0, 0xcd, 0x49, 0x4c, 0x2a, 0x86, 0x59, 0x56, 0x66, 0xaa, 0x5f, + 0x81, 0x6a, 0x63, 0x49, 0x65, 0x41, 0x6a, 0x71, 0x12, 0x1b, 0x38, 0x65, 0x1b, 0x03, 0x02, 0x00, + 0x00, 0xff, 0xff, 0x56, 0x7a, 0x98, 0x6f, 0x92, 0x03, 0x00, 0x00, +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// QueryClient is the client API for Query service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type QueryClient interface { + // Params defines a gRPC query method that returns the tokenfactory module's + // parameters. + Params(ctx context.Context, in *QueryParamsRequest, opts ...grpc.CallOption) (*QueryParamsResponse, error) + // SubspaceDenoms defines a gRPC query method for fetching all + // denominations created by a specific subspace. + SubspaceDenoms(ctx context.Context, in *QuerySubspaceDenomsRequest, opts ...grpc.CallOption) (*QuerySubspaceDenomsResponse, error) +} + +type queryClient struct { + cc grpc1.ClientConn +} + +func NewQueryClient(cc grpc1.ClientConn) QueryClient { + return &queryClient{cc} +} + +func (c *queryClient) Params(ctx context.Context, in *QueryParamsRequest, opts ...grpc.CallOption) (*QueryParamsResponse, error) { + out := new(QueryParamsResponse) + err := c.cc.Invoke(ctx, "/desmos.tokenfactory.v1beta1.Query/Params", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) SubspaceDenoms(ctx context.Context, in *QuerySubspaceDenomsRequest, opts ...grpc.CallOption) (*QuerySubspaceDenomsResponse, error) { + out := new(QuerySubspaceDenomsResponse) + err := c.cc.Invoke(ctx, "/desmos.tokenfactory.v1beta1.Query/SubspaceDenoms", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// QueryServer is the server API for Query service. +type QueryServer interface { + // Params defines a gRPC query method that returns the tokenfactory module's + // parameters. + Params(context.Context, *QueryParamsRequest) (*QueryParamsResponse, error) + // SubspaceDenoms defines a gRPC query method for fetching all + // denominations created by a specific subspace. + SubspaceDenoms(context.Context, *QuerySubspaceDenomsRequest) (*QuerySubspaceDenomsResponse, error) +} + +// UnimplementedQueryServer can be embedded to have forward compatible implementations. +type UnimplementedQueryServer struct { +} + +func (*UnimplementedQueryServer) Params(ctx context.Context, req *QueryParamsRequest) (*QueryParamsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Params not implemented") +} +func (*UnimplementedQueryServer) SubspaceDenoms(ctx context.Context, req *QuerySubspaceDenomsRequest) (*QuerySubspaceDenomsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method SubspaceDenoms not implemented") +} + +func RegisterQueryServer(s grpc1.Server, srv QueryServer) { + s.RegisterService(&_Query_serviceDesc, srv) +} + +func _Query_Params_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryParamsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).Params(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/desmos.tokenfactory.v1beta1.Query/Params", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).Params(ctx, req.(*QueryParamsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_SubspaceDenoms_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QuerySubspaceDenomsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).SubspaceDenoms(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/desmos.tokenfactory.v1beta1.Query/SubspaceDenoms", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).SubspaceDenoms(ctx, req.(*QuerySubspaceDenomsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _Query_serviceDesc = grpc.ServiceDesc{ + ServiceName: "desmos.tokenfactory.v1beta1.Query", + HandlerType: (*QueryServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Params", + Handler: _Query_Params_Handler, + }, + { + MethodName: "SubspaceDenoms", + Handler: _Query_SubspaceDenoms_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "desmos/tokenfactory/v1beta1/query.proto", +} + +func (m *QueryParamsRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryParamsRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryParamsRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *QueryParamsResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryParamsResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryParamsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Params.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *QuerySubspaceDenomsRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QuerySubspaceDenomsRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QuerySubspaceDenomsRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.SubspaceId != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.SubspaceId)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *QuerySubspaceDenomsResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QuerySubspaceDenomsResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QuerySubspaceDenomsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Denoms) > 0 { + for iNdEx := len(m.Denoms) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.Denoms[iNdEx]) + copy(dAtA[i:], m.Denoms[iNdEx]) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Denoms[iNdEx]))) + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func encodeVarintQuery(dAtA []byte, offset int, v uint64) int { + offset -= sovQuery(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *QueryParamsRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *QueryParamsResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Params.Size() + n += 1 + l + sovQuery(uint64(l)) + return n +} + +func (m *QuerySubspaceDenomsRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.SubspaceId != 0 { + n += 1 + sovQuery(uint64(m.SubspaceId)) + } + return n +} + +func (m *QuerySubspaceDenomsResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Denoms) > 0 { + for _, s := range m.Denoms { + l = len(s) + n += 1 + l + sovQuery(uint64(l)) + } + } + return n +} + +func sovQuery(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozQuery(x uint64) (n int) { + return sovQuery(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *QueryParamsRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryParamsRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryParamsRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryParamsResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryParamsResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryParamsResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Params", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Params.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QuerySubspaceDenomsRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QuerySubspaceDenomsRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QuerySubspaceDenomsRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field SubspaceId", wireType) + } + m.SubspaceId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.SubspaceId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QuerySubspaceDenomsResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QuerySubspaceDenomsResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QuerySubspaceDenomsResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Denoms", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Denoms = append(m.Denoms, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipQuery(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowQuery + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowQuery + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowQuery + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthQuery + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupQuery + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthQuery + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthQuery = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowQuery = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupQuery = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/tokenfactory/types/query.pb.gw.go b/x/tokenfactory/types/query.pb.gw.go new file mode 100644 index 0000000000..b6a4c1eb37 --- /dev/null +++ b/x/tokenfactory/types/query.pb.gw.go @@ -0,0 +1,254 @@ +// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT. +// source: desmos/tokenfactory/v1beta1/query.proto + +/* +Package types is a reverse proxy. + +It translates gRPC into RESTful JSON APIs. +*/ +package types + +import ( + "context" + "io" + "net/http" + + "github.com/golang/protobuf/descriptor" + "github.com/golang/protobuf/proto" + "github.com/grpc-ecosystem/grpc-gateway/runtime" + "github.com/grpc-ecosystem/grpc-gateway/utilities" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/grpclog" + "google.golang.org/grpc/metadata" + "google.golang.org/grpc/status" +) + +// Suppress "imported and not used" errors +var _ codes.Code +var _ io.Reader +var _ status.Status +var _ = runtime.String +var _ = utilities.NewDoubleArray +var _ = descriptor.ForMessage +var _ = metadata.Join + +func request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryParamsRequest + var metadata runtime.ServerMetadata + + msg, err := client.Params(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryParamsRequest + var metadata runtime.ServerMetadata + + msg, err := server.Params(ctx, &protoReq) + return msg, metadata, err + +} + +func request_Query_SubspaceDenoms_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QuerySubspaceDenomsRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["subspace_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "subspace_id") + } + + protoReq.SubspaceId, err = runtime.Uint64(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "subspace_id", err) + } + + msg, err := client.SubspaceDenoms(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_SubspaceDenoms_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QuerySubspaceDenomsRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["subspace_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "subspace_id") + } + + protoReq.SubspaceId, err = runtime.Uint64(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "subspace_id", err) + } + + msg, err := server.SubspaceDenoms(ctx, &protoReq) + return msg, metadata, err + +} + +// RegisterQueryHandlerServer registers the http handlers for service Query to "mux". +// UnaryRPC :call QueryServer directly. +// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. +// Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterQueryHandlerFromEndpoint instead. +func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error { + + mux.Handle("GET", pattern_Query_Params_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_Params_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Params_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_SubspaceDenoms_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_SubspaceDenoms_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_SubspaceDenoms_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + +// RegisterQueryHandlerFromEndpoint is same as RegisterQueryHandler but +// automatically dials to "endpoint" and closes the connection when "ctx" gets done. +func RegisterQueryHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { + conn, err := grpc.Dial(endpoint, opts...) + if err != nil { + return err + } + defer func() { + if err != nil { + if cerr := conn.Close(); cerr != nil { + grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) + } + return + } + go func() { + <-ctx.Done() + if cerr := conn.Close(); cerr != nil { + grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) + } + }() + }() + + return RegisterQueryHandler(ctx, mux, conn) +} + +// RegisterQueryHandler registers the http handlers for service Query to "mux". +// The handlers forward requests to the grpc endpoint over "conn". +func RegisterQueryHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error { + return RegisterQueryHandlerClient(ctx, mux, NewQueryClient(conn)) +} + +// RegisterQueryHandlerClient registers the http handlers for service Query +// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "QueryClient". +// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "QueryClient" +// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in +// "QueryClient" to call the correct interceptors. +func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, client QueryClient) error { + + mux.Handle("GET", pattern_Query_Params_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_Params_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Params_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_SubspaceDenoms_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_SubspaceDenoms_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_SubspaceDenoms_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + +var ( + pattern_Query_Params_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"desmos", "tokenfactory", "v1beta1", "params"}, "", runtime.AssumeColonVerbOpt(false))) + + pattern_Query_SubspaceDenoms_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 2, 5}, []string{"desmos", "tokenfactory", "v1beta1", "subspaces", "subspace_id", "denoms"}, "", runtime.AssumeColonVerbOpt(false))) +) + +var ( + forward_Query_Params_0 = runtime.ForwardResponseMessage + + forward_Query_SubspaceDenoms_0 = runtime.ForwardResponseMessage +)