From 293ae8a4cc3519e9cb3103d695297af51a9ed3c0 Mon Sep 17 00:00:00 2001 From: godismercilex Date: Thu, 21 Jul 2022 13:27:23 +0200 Subject: [PATCH 01/13] add: proposal proto and wiring --- app/app.go | 3 +- proto/vpool/v1/gov.proto | 43 +++ x/vpool/handler.go | 7 + x/vpool/types/codec.go | 3 + x/vpool/types/gov.pb.go | 675 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 730 insertions(+), 1 deletion(-) create mode 100644 proto/vpool/v1/gov.proto create mode 100644 x/vpool/types/gov.pb.go diff --git a/app/app.go b/app/app.go index 9ec4682a9..0645dd2ae 100644 --- a/app/app.go +++ b/app/app.go @@ -481,7 +481,8 @@ func NewNibiruApp( AddRoute(distrtypes.RouterKey, distr.NewCommunityPoolSpendProposalHandler(app.DistrKeeper)). AddRoute(upgradetypes.RouterKey, upgrade.NewSoftwareUpgradeProposalHandler(app.UpgradeKeeper)). AddRoute(ibcclienttypes.RouterKey, ibcclient.NewClientProposalHandler(app.IBCKeeper.ClientKeeper)). - AddRoute(pricefeedtypes.RouterKey, pricefeed.NewPricefeedProposalHandler(app.PricefeedKeeper)) + AddRoute(pricefeedtypes.RouterKey, pricefeed.NewPricefeedProposalHandler(app.PricefeedKeeper)). + AddRoute(vpooltypes.RouterKey, vpool.NewCreatePoolProposalHandler(app.VpoolKeeper)) app.TransferKeeper = ibctransferkeeper.NewKeeper( appCodec, diff --git a/proto/vpool/v1/gov.proto b/proto/vpool/v1/gov.proto new file mode 100644 index 000000000..c983d60d2 --- /dev/null +++ b/proto/vpool/v1/gov.proto @@ -0,0 +1,43 @@ +syntax = "proto3"; + +package nibiru.vpool.v1; + +import "gogoproto/gogo.proto"; + +option go_package = "github.com/NibiruChain/nibiru/x/vpool/types"; + +message CreatePoolProposal { + string title = 1; + string description = 2; + // pair represents the pair of the vpool. + string pair = 3; + // trade_limit_ratio represents the limit on trading amounts. + string trade_limit_ratio = 4 [ + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", + (gogoproto.nullable) = false + ]; + // quote_asset_reserve is the amount of quote asset the pool will be initialized with. + string quote_asset_reserve = 5 [ + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", + (gogoproto.nullable) = false + ]; + // base_asset_reserve is the amount of base asset the pool will be initialized with. + string base_asset_reserve = 6 [ + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", + (gogoproto.nullable) = false + ]; + + // fluctuation_limit_ratio represents the maximum price + // percentage difference a trade can create on the pool. + string fluctuation_limit_ratio = 7 [ + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", + (gogoproto.nullable) = false + ]; + + // max_oracle_spread_ratio represents the maximum price percentage + // difference that can exist between oracle price and vpool prices after a trade. + string max_oracle_spread_ratio = 8 [ + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", + (gogoproto.nullable) = false + ]; +} \ No newline at end of file diff --git a/x/vpool/handler.go b/x/vpool/handler.go index fa1c6a684..e080f20d6 100644 --- a/x/vpool/handler.go +++ b/x/vpool/handler.go @@ -2,6 +2,7 @@ package vpool import ( "fmt" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" @@ -19,3 +20,9 @@ func NewHandler(k keeper.Keeper) sdk.Handler { return nil, sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, errMsg) } } + +func NewCreatePoolProposalHandler(k keeper.Keeper) govtypes.Handler { + return func(ctx sdk.Context, content govtypes.Content) error { + panic("impl") + } +} diff --git a/x/vpool/types/codec.go b/x/vpool/types/codec.go index 4c12aafed..b24950949 100644 --- a/x/vpool/types/codec.go +++ b/x/vpool/types/codec.go @@ -4,6 +4,7 @@ import ( "github.com/cosmos/cosmos-sdk/codec" codectypes "github.com/cosmos/cosmos-sdk/codec/types" sdk "github.com/cosmos/cosmos-sdk/types" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" ) func RegisterCodec(cdc *codec.LegacyAmino) { @@ -15,6 +16,8 @@ func RegisterInterfaces(registry codectypes.InterfaceRegistry) { /* implementations */ ) + registry.RegisterImplementations((*govtypes.Content)(nil), &CreatePoolProposal{}) + // msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) } diff --git a/x/vpool/types/gov.pb.go b/x/vpool/types/gov.pb.go new file mode 100644 index 000000000..8e8148675 --- /dev/null +++ b/x/vpool/types/gov.pb.go @@ -0,0 +1,675 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: vpool/v1/gov.proto + +package types + +import ( + fmt "fmt" + github_com_cosmos_cosmos_sdk_types "github.com/cosmos/cosmos-sdk/types" + _ "github.com/gogo/protobuf/gogoproto" + proto "github.com/gogo/protobuf/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 + +type CreatePoolProposal struct { + Title string `protobuf:"bytes,1,opt,name=title,proto3" json:"title,omitempty"` + Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"` + // pair represents the pair of the vpool. + Pair string `protobuf:"bytes,3,opt,name=pair,proto3" json:"pair,omitempty"` + // trade_limit_ratio represents the limit on trading amounts. + TradeLimitRatio github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,4,opt,name=trade_limit_ratio,json=tradeLimitRatio,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"trade_limit_ratio"` + // quote_asset_reserve is the amount of quote asset the pool will be initialized with. + QuoteAssetReserve github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,5,opt,name=quote_asset_reserve,json=quoteAssetReserve,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"quote_asset_reserve"` + // base_asset_reserve is the amount of base asset the pool will be initialized with. + BaseAssetReserve github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,6,opt,name=base_asset_reserve,json=baseAssetReserve,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"base_asset_reserve"` + // fluctuation_limit_ratio represents the maximum price + // percentage difference a trade can create on the pool. + FluctuationLimitRatio github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,7,opt,name=fluctuation_limit_ratio,json=fluctuationLimitRatio,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"fluctuation_limit_ratio"` + // max_oracle_spread_ratio represents the maximum price percentage + // difference that can exist between oracle price and vpool prices after a trade. + MaxOracleSpreadRatio github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,8,opt,name=max_oracle_spread_ratio,json=maxOracleSpreadRatio,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"max_oracle_spread_ratio"` +} + +func (m *CreatePoolProposal) Reset() { *m = CreatePoolProposal{} } +func (m *CreatePoolProposal) String() string { return proto.CompactTextString(m) } +func (*CreatePoolProposal) ProtoMessage() {} +func (*CreatePoolProposal) Descriptor() ([]byte, []int) { + return fileDescriptor_8a393460ab414204, []int{0} +} +func (m *CreatePoolProposal) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *CreatePoolProposal) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_CreatePoolProposal.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 *CreatePoolProposal) XXX_Merge(src proto.Message) { + xxx_messageInfo_CreatePoolProposal.Merge(m, src) +} +func (m *CreatePoolProposal) XXX_Size() int { + return m.Size() +} +func (m *CreatePoolProposal) XXX_DiscardUnknown() { + xxx_messageInfo_CreatePoolProposal.DiscardUnknown(m) +} + +var xxx_messageInfo_CreatePoolProposal proto.InternalMessageInfo + +func (m *CreatePoolProposal) GetTitle() string { + if m != nil { + return m.Title + } + return "" +} + +func (m *CreatePoolProposal) GetDescription() string { + if m != nil { + return m.Description + } + return "" +} + +func (m *CreatePoolProposal) GetPair() string { + if m != nil { + return m.Pair + } + return "" +} + +func init() { + proto.RegisterType((*CreatePoolProposal)(nil), "nibiru.vpool.v1.CreatePoolProposal") +} + +func init() { proto.RegisterFile("vpool/v1/gov.proto", fileDescriptor_8a393460ab414204) } + +var fileDescriptor_8a393460ab414204 = []byte{ + // 377 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0xd2, 0xc1, 0x6e, 0x9b, 0x30, + 0x18, 0x07, 0x70, 0xd8, 0x92, 0x6c, 0xf3, 0x0e, 0x59, 0xbc, 0x4c, 0x41, 0x3b, 0x90, 0x68, 0x87, + 0x69, 0xd2, 0x54, 0xac, 0xa8, 0x4f, 0xd0, 0xa4, 0xbd, 0x55, 0x6d, 0x44, 0x6f, 0x51, 0x55, 0x64, + 0xc0, 0x21, 0x56, 0x81, 0x8f, 0xda, 0x06, 0xa5, 0x6f, 0xd1, 0xc7, 0x4a, 0x6f, 0x39, 0x56, 0x3d, + 0x44, 0x55, 0xf2, 0x22, 0x15, 0x26, 0x07, 0xd2, 0x23, 0x27, 0x0c, 0x9f, 0xf5, 0xfb, 0x8b, 0x4f, + 0x7f, 0x84, 0x8b, 0x0c, 0x20, 0x26, 0xc5, 0x98, 0x44, 0x50, 0x38, 0x99, 0x00, 0x05, 0xb8, 0x9b, + 0x72, 0x9f, 0x8b, 0xdc, 0xd1, 0x23, 0xa7, 0x18, 0xff, 0xee, 0x47, 0x10, 0x81, 0x9e, 0x91, 0xf2, + 0x54, 0x5d, 0xfb, 0xf3, 0xdc, 0x42, 0x78, 0x2a, 0x18, 0x55, 0x6c, 0x06, 0x10, 0xcf, 0x04, 0x64, + 0x20, 0x69, 0x8c, 0xfb, 0xa8, 0xad, 0xb8, 0x8a, 0x99, 0x65, 0x8e, 0xcc, 0x7f, 0xdf, 0xdc, 0xea, + 0x05, 0x8f, 0xd0, 0xf7, 0x90, 0xc9, 0x40, 0xf0, 0x4c, 0x71, 0x48, 0xad, 0x4f, 0x7a, 0x56, 0xff, + 0x84, 0x31, 0x6a, 0x65, 0x94, 0x0b, 0xeb, 0xb3, 0x1e, 0xe9, 0x33, 0x9e, 0xa3, 0x9e, 0x12, 0x34, + 0x64, 0x5e, 0xcc, 0x13, 0xae, 0x3c, 0x41, 0x15, 0x07, 0xab, 0x55, 0x5e, 0x98, 0x38, 0xeb, 0xed, + 0xd0, 0x78, 0xdd, 0x0e, 0xff, 0x46, 0x5c, 0x2d, 0x73, 0xdf, 0x09, 0x20, 0x21, 0x01, 0xc8, 0x04, + 0xe4, 0xe1, 0x71, 0x22, 0xc3, 0x7b, 0xa2, 0x1e, 0x33, 0x26, 0x9d, 0x73, 0x16, 0xb8, 0x5d, 0x0d, + 0x5d, 0x96, 0x8e, 0x5b, 0x32, 0xf8, 0x0e, 0xfd, 0x7c, 0xc8, 0x41, 0x31, 0x8f, 0x4a, 0xc9, 0x94, + 0x27, 0x98, 0x64, 0xa2, 0x60, 0x56, 0xbb, 0x91, 0xde, 0xd3, 0xd4, 0x59, 0x29, 0xb9, 0x15, 0x84, + 0x6f, 0x11, 0xf6, 0xa9, 0xfc, 0xc8, 0x77, 0x1a, 0xf1, 0x3f, 0x4a, 0xe9, 0x48, 0x5f, 0xa0, 0xc1, + 0x22, 0xce, 0x03, 0x95, 0x97, 0xff, 0x92, 0x1e, 0xed, 0xe7, 0x4b, 0xa3, 0x88, 0x5f, 0x35, 0xae, + 0xb6, 0x25, 0x86, 0x06, 0x09, 0x5d, 0x79, 0x20, 0x68, 0x10, 0x33, 0x4f, 0x66, 0x82, 0xd1, 0xf0, + 0x90, 0xf3, 0xb5, 0x51, 0x4e, 0x3f, 0xa1, 0xab, 0x6b, 0xad, 0xdd, 0x68, 0x4c, 0xc7, 0x4c, 0x2e, + 0xd6, 0x3b, 0xdb, 0xdc, 0xec, 0x6c, 0xf3, 0x6d, 0x67, 0x9b, 0x4f, 0x7b, 0xdb, 0xd8, 0xec, 0x6d, + 0xe3, 0x65, 0x6f, 0x1b, 0xf3, 0xff, 0x35, 0xf7, 0x4a, 0xf7, 0x72, 0xba, 0xa4, 0x3c, 0x25, 0x55, + 0x47, 0xc9, 0x8a, 0x54, 0x05, 0xd6, 0x01, 0x7e, 0x47, 0x37, 0xf3, 0xf4, 0x3d, 0x00, 0x00, 0xff, + 0xff, 0xf0, 0xd1, 0x57, 0xb4, 0xd6, 0x02, 0x00, 0x00, +} + +func (m *CreatePoolProposal) 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 *CreatePoolProposal) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *CreatePoolProposal) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size := m.MaxOracleSpreadRatio.Size() + i -= size + if _, err := m.MaxOracleSpreadRatio.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintGov(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x42 + { + size := m.FluctuationLimitRatio.Size() + i -= size + if _, err := m.FluctuationLimitRatio.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintGov(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x3a + { + size := m.BaseAssetReserve.Size() + i -= size + if _, err := m.BaseAssetReserve.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintGov(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x32 + { + size := m.QuoteAssetReserve.Size() + i -= size + if _, err := m.QuoteAssetReserve.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintGov(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x2a + { + size := m.TradeLimitRatio.Size() + i -= size + if _, err := m.TradeLimitRatio.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintGov(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + if len(m.Pair) > 0 { + i -= len(m.Pair) + copy(dAtA[i:], m.Pair) + i = encodeVarintGov(dAtA, i, uint64(len(m.Pair))) + i-- + dAtA[i] = 0x1a + } + if len(m.Description) > 0 { + i -= len(m.Description) + copy(dAtA[i:], m.Description) + i = encodeVarintGov(dAtA, i, uint64(len(m.Description))) + i-- + dAtA[i] = 0x12 + } + if len(m.Title) > 0 { + i -= len(m.Title) + copy(dAtA[i:], m.Title) + i = encodeVarintGov(dAtA, i, uint64(len(m.Title))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func encodeVarintGov(dAtA []byte, offset int, v uint64) int { + offset -= sovGov(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *CreatePoolProposal) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Title) + if l > 0 { + n += 1 + l + sovGov(uint64(l)) + } + l = len(m.Description) + if l > 0 { + n += 1 + l + sovGov(uint64(l)) + } + l = len(m.Pair) + if l > 0 { + n += 1 + l + sovGov(uint64(l)) + } + l = m.TradeLimitRatio.Size() + n += 1 + l + sovGov(uint64(l)) + l = m.QuoteAssetReserve.Size() + n += 1 + l + sovGov(uint64(l)) + l = m.BaseAssetReserve.Size() + n += 1 + l + sovGov(uint64(l)) + l = m.FluctuationLimitRatio.Size() + n += 1 + l + sovGov(uint64(l)) + l = m.MaxOracleSpreadRatio.Size() + n += 1 + l + sovGov(uint64(l)) + return n +} + +func sovGov(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozGov(x uint64) (n int) { + return sovGov(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *CreatePoolProposal) 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 ErrIntOverflowGov + } + 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: CreatePoolProposal: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: CreatePoolProposal: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Title", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGov + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGov + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGov + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Title = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Description", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGov + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGov + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGov + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Description = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pair", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGov + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGov + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGov + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Pair = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field TradeLimitRatio", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGov + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGov + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGov + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.TradeLimitRatio.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field QuoteAssetReserve", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGov + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGov + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGov + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.QuoteAssetReserve.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field BaseAssetReserve", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGov + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGov + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGov + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.BaseAssetReserve.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field FluctuationLimitRatio", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGov + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGov + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGov + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.FluctuationLimitRatio.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MaxOracleSpreadRatio", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGov + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGov + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGov + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.MaxOracleSpreadRatio.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGov(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGov + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipGov(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, ErrIntOverflowGov + } + 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, ErrIntOverflowGov + } + 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, ErrIntOverflowGov + } + 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, ErrInvalidLengthGov + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupGov + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthGov + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthGov = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowGov = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupGov = fmt.Errorf("proto: unexpected end of group") +) From 68e759d7b19e40e9d63f8541c1a666bbeae3af4d Mon Sep 17 00:00:00 2001 From: godismercilex Date: Thu, 21 Jul 2022 13:40:18 +0200 Subject: [PATCH 02/13] add: gov handler implementation --- x/vpool/handler.go | 24 +++++++++++++- x/vpool/types/gov.go | 76 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+), 1 deletion(-) create mode 100644 x/vpool/types/gov.go diff --git a/x/vpool/handler.go b/x/vpool/handler.go index e080f20d6..4bcc1fa25 100644 --- a/x/vpool/handler.go +++ b/x/vpool/handler.go @@ -2,6 +2,7 @@ package vpool import ( "fmt" + "github.com/NibiruChain/nibiru/x/common" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" sdk "github.com/cosmos/cosmos-sdk/types" @@ -23,6 +24,27 @@ func NewHandler(k keeper.Keeper) sdk.Handler { func NewCreatePoolProposalHandler(k keeper.Keeper) govtypes.Handler { return func(ctx sdk.Context, content govtypes.Content) error { - panic("impl") + switch m := content.(type) { + case *types.CreatePoolProposal: + if err := m.ValidateBasic(); err != nil { + return err + } + pair := common.MustNewAssetPair(m.Pair) + k.CreatePool( + ctx, + pair, + m.TradeLimitRatio, + m.QuoteAssetReserve, + m.BaseAssetReserve, + m.FluctuationLimitRatio, + m.MaxOracleSpreadRatio, + ) + // TODO(mercilex): oracle missing, pool should not be tradeable + return nil + default: + return sdkerrors.Wrapf( + sdkerrors.ErrUnknownRequest, + "unrecognized %s proposal content type: %T", types.ModuleName, m) + } } } diff --git a/x/vpool/types/gov.go b/x/vpool/types/gov.go new file mode 100644 index 000000000..3909d9077 --- /dev/null +++ b/x/vpool/types/gov.go @@ -0,0 +1,76 @@ +package types + +import ( + "fmt" + sdk "github.com/cosmos/cosmos-sdk/types" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" + + "github.com/NibiruChain/nibiru/x/common" +) + +const ( + ProposalTypeCreatePool = "CreatePool" +) + +var _ govtypes.Content = &CreatePoolProposal{} + +// NEVER MUTATE THESE! +// they exist for comparisons only and to avoid constant allocations of a new big int +// which is used only for reading. +var ( + oneDec = sdk.OneDec() + zeroDec = sdk.ZeroDec() +) + +func init() { + govtypes.RegisterProposalType(ProposalTypeCreatePool) + govtypes.RegisterProposalTypeCodec(&CreatePoolProposal{}, "nibiru/CreatePoolProposal") +} + +func (m *CreatePoolProposal) ProposalRoute() string { + return RouterKey +} + +func (m *CreatePoolProposal) ProposalType() string { + return ProposalTypeCreatePool +} + +func (m *CreatePoolProposal) ValidateBasic() error { + if err := govtypes.ValidateAbstract(m); err != nil { + return err + } + + if _, err := common.NewAssetPair(m.Pair); err != nil { + return err + } + + // trade limit ratio always between 0 and 1 + // TODO(mercilex): does it really make sense for this to be equal to zero? + if m.TradeLimitRatio.LT(zeroDec) || m.TradeLimitRatio.GT(oneDec) { + return fmt.Errorf("trade limit ratio must be 0 <= ratio <= 1") + } + + // quote asset reserve always > 0 + if m.QuoteAssetReserve.LTE(zeroDec) { + return fmt.Errorf("quote asset reserve must be > 0") + } + + // base asset reserve always > 0 + if m.BaseAssetReserve.LTE(zeroDec) { + return fmt.Errorf("base asset reserve must be > 0") + } + + // fluctuation limit ratio between 0 and 1 + // TODO(mercilex): does it really make sense for this to be equal to zero? + if m.FluctuationLimitRatio.LT(zeroDec) || m.FluctuationLimitRatio.GT(oneDec) { + return fmt.Errorf("fluctuation limit ratio must be 0 <= ratio <= 1") + } + + // max oracle spread ratio between 0 and 1 + // TODO(mercilex): does it really make sense for this to be equal to zero? + if m.MaxOracleSpreadRatio.LT(zeroDec) || m.MaxOracleSpreadRatio.GT(oneDec) { + return fmt.Errorf("max oracle spread ratio must be 0 <= ratio <= 1") + } + + return nil +} From bb22be4c78649237cba936601307d0dd4da1601d Mon Sep 17 00:00:00 2001 From: godismercilex Date: Thu, 21 Jul 2022 19:19:08 +0200 Subject: [PATCH 03/13] add: gov CLI handler --- app/app.go | 2 + x/vpool/client/cli/gov_client.go | 108 +++++++++++++++++++++++++++++++ 2 files changed, 110 insertions(+) create mode 100644 x/vpool/client/cli/gov_client.go diff --git a/app/app.go b/app/app.go index 0645dd2ae..f21c204d4 100644 --- a/app/app.go +++ b/app/app.go @@ -3,6 +3,7 @@ package app import ( "encoding/json" "fmt" + vpoolcli "github.com/NibiruChain/nibiru/x/vpool/client/cli" "io" "net/http" "os" @@ -154,6 +155,7 @@ var ( upgradeclient.ProposalHandler, upgradeclient.CancelProposalHandler, pricefeedcli.AddOracleProposalHandler, + vpoolcli.CreatePoolProposalHandler, // pricefeedcli.RemoveOracleProposalHandler, // TODO ibcclientclient.UpdateClientProposalHandler, ibcclientclient.UpgradeProposalHandler, diff --git a/x/vpool/client/cli/gov_client.go b/x/vpool/client/cli/gov_client.go new file mode 100644 index 000000000..7ab0fbd4d --- /dev/null +++ b/x/vpool/client/cli/gov_client.go @@ -0,0 +1,108 @@ +package cli + +import ( + "fmt" + "github.com/NibiruChain/nibiru/x/vpool/types" + govclientrest "github.com/cosmos/cosmos-sdk/x/gov/client/rest" + "io/ioutil" + "net/http" + "strings" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/tx" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/version" + govclient "github.com/cosmos/cosmos-sdk/x/gov/client" + govcli "github.com/cosmos/cosmos-sdk/x/gov/client/cli" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" + + "github.com/spf13/cobra" +) + +var ( + CreatePoolProposalHandler = govclient.NewProposalHandler( + /* govclient.CLIHandlerFn */ CmdCreatePoolProposal, + /* govclient.RESTHandlerFn */ func(context client.Context) govclientrest.ProposalRESTHandler { + return govclientrest.ProposalRESTHandler{ + SubRoute: "create_pool", + Handler: func(writer http.ResponseWriter, request *http.Request) { + _, _ = writer.Write([]byte("deprecated")) + writer.WriteHeader(http.StatusMethodNotAllowed) + }, + } + }) +) + +// CmdCreatePoolProposal implements the client command to submit a governance +// proposal to whitelist an oracle for specified asset pairs. +func CmdCreatePoolProposal() *cobra.Command { + cmd := &cobra.Command{ + Use: "create-pool [proposal-json] --deposit=[deposit]", + Args: cobra.ExactArgs(1), + Short: "Submit a proposal to whitelist an oracle", + Example: strings.TrimSpace(fmt.Sprintf(` + Example: + $ %s tx gov submit-proposal create-pool --deposit="1000unibi" --from= + `, version.AppName)), + Long: strings.TrimSpace( + `Submits a proposal to create a new vpool, which in turn create a new x/perp market + + A proposal.json for 'CreatePoolProposal' contains: + { + "title": "Create vpool for ETH:USDT", + "description": "I wanna get liquidated on ETH:USDT", + "pair": "ETH:USDT", + "trade_limit_ratio": "0.2", + ... + } + `), + RunE: func(cmd *cobra.Command, args []string) (err error) { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + from := clientCtx.GetFromAddress() + + proposal := &types.CreatePoolProposal{} + contents, err := ioutil.ReadFile(args[0]) + if err != nil { + return err + } + + // marshals the contents into the proto.Message to which 'proposal' points. + if err = clientCtx.Codec.UnmarshalJSON(contents, proposal); err != nil { + return err + } + + depositStr, err := cmd.Flags().GetString(govcli.FlagDeposit) + if err != nil { + return err + } + deposit, err := sdk.ParseCoinsNormalized(depositStr) + if err != nil { + return err + } + + msg, err := govtypes.NewMsgSubmitProposal(proposal, deposit, from) + if err != nil { + return err + } + if err = msg.ValidateBasic(); err != nil { + return err + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + cmd.Flags().String( + /*name=*/ govcli.FlagDeposit, + /*defaultValue=*/ "", + /*usage=*/ "governance deposit for proposal") + if err := cmd.MarkFlagRequired(govcli.FlagDeposit); err != nil { + panic(err) + } + + return cmd +} From bf8dfee6c32d8634efce07e67470b99a5f8b8ddb Mon Sep 17 00:00:00 2001 From: godismercilex Date: Thu, 21 Jul 2022 19:20:30 +0200 Subject: [PATCH 04/13] chore: fix comment --- x/vpool/client/cli/gov_client.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/vpool/client/cli/gov_client.go b/x/vpool/client/cli/gov_client.go index 7ab0fbd4d..ddfafdf32 100644 --- a/x/vpool/client/cli/gov_client.go +++ b/x/vpool/client/cli/gov_client.go @@ -39,7 +39,7 @@ func CmdCreatePoolProposal() *cobra.Command { cmd := &cobra.Command{ Use: "create-pool [proposal-json] --deposit=[deposit]", Args: cobra.ExactArgs(1), - Short: "Submit a proposal to whitelist an oracle", + Short: "Submit a proposal to create a new vpool", Example: strings.TrimSpace(fmt.Sprintf(` Example: $ %s tx gov submit-proposal create-pool --deposit="1000unibi" --from= From 5444ae0d494f5d746a81db48526003d0efa5ee6e Mon Sep 17 00:00:00 2001 From: godismercilex Date: Thu, 21 Jul 2022 19:22:05 +0200 Subject: [PATCH 05/13] chore: lint --- app/app.go | 3 ++- x/vpool/client/cli/gov_client.go | 6 ++++-- x/vpool/handler.go | 4 +++- x/vpool/types/gov.go | 1 + 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/app/app.go b/app/app.go index f21c204d4..0b514ef9b 100644 --- a/app/app.go +++ b/app/app.go @@ -3,12 +3,13 @@ package app import ( "encoding/json" "fmt" - vpoolcli "github.com/NibiruChain/nibiru/x/vpool/client/cli" "io" "net/http" "os" "path/filepath" + vpoolcli "github.com/NibiruChain/nibiru/x/vpool/client/cli" + pricefeedcli "github.com/NibiruChain/nibiru/x/pricefeed/client/cli" "github.com/cosmos/cosmos-sdk/baseapp" diff --git a/x/vpool/client/cli/gov_client.go b/x/vpool/client/cli/gov_client.go index ddfafdf32..a5c5ea568 100644 --- a/x/vpool/client/cli/gov_client.go +++ b/x/vpool/client/cli/gov_client.go @@ -2,12 +2,14 @@ package cli import ( "fmt" - "github.com/NibiruChain/nibiru/x/vpool/types" - govclientrest "github.com/cosmos/cosmos-sdk/x/gov/client/rest" "io/ioutil" "net/http" "strings" + govclientrest "github.com/cosmos/cosmos-sdk/x/gov/client/rest" + + "github.com/NibiruChain/nibiru/x/vpool/types" + "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/tx" sdk "github.com/cosmos/cosmos-sdk/types" diff --git a/x/vpool/handler.go b/x/vpool/handler.go index 4bcc1fa25..de8d9bb5c 100644 --- a/x/vpool/handler.go +++ b/x/vpool/handler.go @@ -2,9 +2,11 @@ package vpool import ( "fmt" - "github.com/NibiruChain/nibiru/x/common" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" + "github.com/NibiruChain/nibiru/x/common" + sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" diff --git a/x/vpool/types/gov.go b/x/vpool/types/gov.go index 3909d9077..e35842fdf 100644 --- a/x/vpool/types/gov.go +++ b/x/vpool/types/gov.go @@ -2,6 +2,7 @@ package types import ( "fmt" + sdk "github.com/cosmos/cosmos-sdk/types" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" From 1089dd7a57bf4e8f00bdb99bc2566e29b7853422 Mon Sep 17 00:00:00 2001 From: godismercilex Date: Thu, 21 Jul 2022 19:32:28 +0200 Subject: [PATCH 06/13] chore: CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8398b489b..850e25a07 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -55,7 +55,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * [#712](https://github.com/NibiruChain/nibiru/pull/712) Add funding rate calculation and `FundingRateChangedEvent`. ### Upgrades - +* [#725](https://github.com/NibiruChain/nibiru/pull/725) Add governance handler for creating new virtual pools. * [#702](https://github.com/NibiruChain/nibiru/pull/702) Add upgrade handler for v0.10.0. ## [v0.9.2](https://github.com/NibiruChain/nibiru/releases/tag/v0.9.2) - 2022-07-11 From 7994675597c7cc6539f5fb43bb5ee33028b2bf02 Mon Sep 17 00:00:00 2001 From: godismercilex Date: Sun, 24 Jul 2022 13:25:25 +0200 Subject: [PATCH 07/13] add: cli tests --- x/vpool/client/cli/cli_test.go | 229 +++++++++++++++++++++++++++++++++ 1 file changed, 229 insertions(+) create mode 100644 x/vpool/client/cli/cli_test.go diff --git a/x/vpool/client/cli/cli_test.go b/x/vpool/client/cli/cli_test.go new file mode 100644 index 000000000..f1e9b4d60 --- /dev/null +++ b/x/vpool/client/cli/cli_test.go @@ -0,0 +1,229 @@ +package cli_test + +import ( + "context" + "fmt" + "github.com/NibiruChain/nibiru/app" + "github.com/NibiruChain/nibiru/x/common" + testutilcli "github.com/NibiruChain/nibiru/x/testutil/cli" + "github.com/NibiruChain/nibiru/x/testutil/testapp" + "github.com/NibiruChain/nibiru/x/vpool/client/cli" + vpooltypes "github.com/NibiruChain/nibiru/x/vpool/types" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/crypto/hd" + "github.com/cosmos/cosmos-sdk/crypto/keyring" + sdktestutil "github.com/cosmos/cosmos-sdk/testutil" + sdktestutilcli "github.com/cosmos/cosmos-sdk/testutil/cli" + sdk "github.com/cosmos/cosmos-sdk/types" + govcli "github.com/cosmos/cosmos-sdk/x/gov/client/cli" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" + "github.com/gogo/protobuf/proto" + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" + "io/ioutil" + "testing" + "time" +) + +type IntegrationTestSuite struct { + suite.Suite + + cfg testutilcli.Config + network *testutilcli.Network +} + +func (s *IntegrationTestSuite) SetupSuite() { + if testing.Short() { + s.T().Skip("skipping integration test suite") + } + + s.T().Log("setting up integration test suite") + + app.SetPrefixes(app.AccountAddressPrefix) + + encCfg := app.MakeTestEncodingConfig() + defaultAppGenesis := app.ModuleBasics.DefaultGenesis(encCfg.Marshaler) + testAppGenesis := testapp.NewTestGenesisState(encCfg.Marshaler, defaultAppGenesis) + s.cfg = testutilcli.BuildNetworkConfig(testAppGenesis) + + s.network = testutilcli.NewNetwork(s.T(), s.cfg) + + _, err := s.network.WaitForHeight(1) + s.Require().NoError(err) + + res, err := testutilcli.QueryPrice( + s.network.Validators[0].ClientCtx, + common.PairGovStable.String(), + ) + s.Require().NoError(err) + s.Assert().Equal(sdk.NewDec(10), res.Price.Price) +} + +func (s *IntegrationTestSuite) TearDownSuite() { + s.T().Log("tearing down integration test suite") + s.network.Cleanup() +} + +func (s IntegrationTestSuite) TestX_CmdAddOracleProposalAndVote() { + s.Require().Len(s.network.Validators, 1) + val := s.network.Validators[0] + clientCtx := val.ClientCtx.WithOutputFormat("json") + proposer, _, err := val.ClientCtx.Keyring.NewMnemonic( + /* uid */ "proposer", + /* language */ keyring.English, + /* hdPath */ sdk.FullFundraiserPath, + /* bip39Passphrase */ "", + /* algo */ hd.Secp256k1, + ) + s.Require().NoError(err) + + s.T().Log("Fill proposer wallet to pay gas for prosal") + gasTokens := sdk.NewCoins(sdk.NewInt64Coin(s.cfg.BondDenom, 100_000_000)) + oracle := sdk.AccAddress(proposer.GetPubKey().Address()) + _, err = testutilcli.FillWalletFromValidator(oracle, gasTokens, val, s.cfg.BondDenom) + s.Require().NoError(err) + + s.T().Log("load example json as bytes") + proposal := &vpooltypes.CreatePoolProposal{ + Title: "Create ETH:USD pool", + Description: "Creates an ETH:USD pool", + Pair: "ETH:USD", + TradeLimitRatio: sdk.MustNewDecFromStr("0.10"), + QuoteAssetReserve: sdk.NewDec(1_000_000), + BaseAssetReserve: sdk.NewDec(1_000_000), + FluctuationLimitRatio: sdk.MustNewDecFromStr("0.05"), + MaxOracleSpreadRatio: sdk.MustNewDecFromStr("0.05"), + } + proposalJSONString := val.ClientCtx.Codec.MustMarshalJSON(proposal) + proposalJSON := sdktestutil.WriteToNewTempFile( + s.T(), string(proposalJSONString), + ) + contents, err := ioutil.ReadFile(proposalJSON.Name()) + s.Assert().NoError(err) + + s.T().Log("Unmarshal json bytes into proposal object; check validity") + proposal = &vpooltypes.CreatePoolProposal{} + val.ClientCtx.Codec.MustUnmarshalJSON(contents, proposal) + s.Require().NoError(proposal.ValidateBasic()) + + s.T().Log("Submit proposal and unmarshal tx response") + args := []string{ + proposalJSON.Name(), + fmt.Sprintf("--%s=1000unibi", govcli.FlagDeposit), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=test", flags.FlagKeyringBackend), + fmt.Sprintf("--from=%s", val.Address.String()), + } + cmd := cli.CmdCreatePoolProposal() + flags.AddTxFlagsToCmd(cmd) + out, err := sdktestutilcli.ExecTestCLICmd(clientCtx, cmd, args) + s.Require().NoError(err) + s.Assert().NotContains(out.String(), "fail") + var txRespProtoMessage proto.Message = &sdk.TxResponse{} + s.Assert().NoError( + clientCtx.Codec.UnmarshalJSON(out.Bytes(), txRespProtoMessage), + out.String()) + txResp := txRespProtoMessage.(*sdk.TxResponse) + err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), txResp) + s.Assert().NoError(err) + s.Assert().EqualValues(0, txResp.Code, out.String()) + + s.T().Log(`Check that proposal was correctly submitted with gov client + $ nibid query gov proposal 1`) + // the proposal tx won't be included until next block + s.Assert().NoError(s.network.WaitForNextBlock()) + govQueryClient := govtypes.NewQueryClient(clientCtx) + proposalsQueryResponse, err := govQueryClient.Proposals( + context.Background(), &govtypes.QueryProposalsRequest{}, + ) + s.Require().NoError(err) + s.Assert().NotEmpty(proposalsQueryResponse.Proposals) + s.Assert().EqualValues(1, proposalsQueryResponse.Proposals[0].ProposalId, + "first proposal should have proposal ID of 1") + s.Assert().Equalf( + govtypes.StatusDepositPeriod, + proposalsQueryResponse.Proposals[0].Status, + "proposal should be in deposit period as it hasn't passed min deposit") + s.Assert().EqualValues( + sdk.NewCoins(sdk.NewInt64Coin("unibi", 1_000)), + proposalsQueryResponse.Proposals[0].TotalDeposit, + ) + + s.T().Log(`Move proposal to vote status by meeting min deposit + $ nibid tx gov deposit [proposal-id] [deposit] [flags]`) + govDepositParams, err := govQueryClient.Params( + context.Background(), &govtypes.QueryParamsRequest{ParamsType: govtypes.ParamDeposit}) + s.Assert().NoError(err) + args = []string{ + /*proposal-id=*/ "1", + /*deposit=*/ govDepositParams.DepositParams.MinDeposit.String(), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=test", flags.FlagKeyringBackend), + fmt.Sprintf("--from=%s", val.Address.String()), + } + _, err = sdktestutilcli.ExecTestCLICmd(clientCtx, govcli.NewCmdDeposit(), args) + s.Assert().NoError(err) + + s.Assert().NoError(s.network.WaitForNextBlock()) + govQueryClient = govtypes.NewQueryClient(clientCtx) + proposalsQueryResponse, err = govQueryClient.Proposals( + context.Background(), &govtypes.QueryProposalsRequest{}) + s.Require().NoError(err) + s.Assert().Equalf( + govtypes.StatusVotingPeriod, + proposalsQueryResponse.Proposals[0].Status, + "proposal should be in voting period since min deposit has been met") + + s.T().Log(`Vote on the proposal. + $ nibid tx gov vote [proposal-id] [option] [flags] + e.g. $ nibid tx gov vote 1 yes`) + args = []string{ + /*proposal-id=*/ "1", + /*option=*/ "yes", + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=test", flags.FlagKeyringBackend), + fmt.Sprintf("--from=%s", val.Address.String()), + } + _, err = sdktestutilcli.ExecTestCLICmd(clientCtx, govcli.NewCmdVote(), args) + s.Assert().NoError(err) + txResp = &sdk.TxResponse{} + err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), txResp) + s.Assert().NoError(err) + s.Assert().EqualValues(0, txResp.Code, out.String()) + + s.Assert().NoError(s.network.WaitForNextBlock()) + s.Require().Eventuallyf(func() bool { + proposalsQueryResponse, err = govQueryClient.Proposals( + context.Background(), &govtypes.QueryProposalsRequest{}) + s.Require().NoError(err) + return govtypes.StatusPassed == proposalsQueryResponse.Proposals[0].Status + }, 20*time.Second, 2*time.Second, + "proposal should pass after voting period") + + s.T().Log("verify that the new proposed pool exists") + cmd = cli.CmdGetVpools() + args = []string{} + queryResp := &vpooltypes.QueryAllPoolsResponse{} + s.Require().NoError(testutilcli.ExecQuery(s.network, cmd, args, queryResp)) + + found := false + for _, pool := range queryResp.Pools { + if pool.Pair.String() == proposal.Pair { + require.Equal(s.T(), pool, &vpooltypes.Pool{ + Pair: common.MustNewAssetPair(proposal.Pair), + BaseAssetReserve: proposal.BaseAssetReserve, + QuoteAssetReserve: proposal.QuoteAssetReserve, + TradeLimitRatio: proposal.TradeLimitRatio, + FluctuationLimitRatio: proposal.FluctuationLimitRatio, + MaxOracleSpreadRatio: proposal.MaxOracleSpreadRatio, + }) + found = true + } + } + + require.True(s.T(), found, "pool does not exist") +} + +func TestIntegrationTestSuite(t *testing.T) { + suite.Run(t, new(IntegrationTestSuite)) +} From 3e4802b9ef782d081f24137ff6045778988f9880 Mon Sep 17 00:00:00 2001 From: godismercilex Date: Sun, 24 Jul 2022 13:28:01 +0200 Subject: [PATCH 08/13] chore: les lintos --- x/vpool/client/cli/cli_test.go | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/x/vpool/client/cli/cli_test.go b/x/vpool/client/cli/cli_test.go index f1e9b4d60..c0c58773f 100644 --- a/x/vpool/client/cli/cli_test.go +++ b/x/vpool/client/cli/cli_test.go @@ -3,12 +3,10 @@ package cli_test import ( "context" "fmt" - "github.com/NibiruChain/nibiru/app" - "github.com/NibiruChain/nibiru/x/common" - testutilcli "github.com/NibiruChain/nibiru/x/testutil/cli" - "github.com/NibiruChain/nibiru/x/testutil/testapp" - "github.com/NibiruChain/nibiru/x/vpool/client/cli" - vpooltypes "github.com/NibiruChain/nibiru/x/vpool/types" + "io/ioutil" + "testing" + "time" + "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/crypto/hd" "github.com/cosmos/cosmos-sdk/crypto/keyring" @@ -20,9 +18,13 @@ import ( "github.com/gogo/protobuf/proto" "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" - "io/ioutil" - "testing" - "time" + + "github.com/NibiruChain/nibiru/app" + "github.com/NibiruChain/nibiru/x/common" + testutilcli "github.com/NibiruChain/nibiru/x/testutil/cli" + "github.com/NibiruChain/nibiru/x/testutil/testapp" + "github.com/NibiruChain/nibiru/x/vpool/client/cli" + vpooltypes "github.com/NibiruChain/nibiru/x/vpool/types" ) type IntegrationTestSuite struct { From 8300af948716812cdb808f260aaed501b14fe6f4 Mon Sep 17 00:00:00 2001 From: godismercilex Date: Sun, 24 Jul 2022 13:45:35 +0200 Subject: [PATCH 09/13] add: proposal tests --- x/vpool/types/gov_test.go | 142 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 142 insertions(+) create mode 100644 x/vpool/types/gov_test.go diff --git a/x/vpool/types/gov_test.go b/x/vpool/types/gov_test.go new file mode 100644 index 000000000..2f7c400fb --- /dev/null +++ b/x/vpool/types/gov_test.go @@ -0,0 +1,142 @@ +package types + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + "testing" +) + +func TestCreatePoolProposal_ValidateBasic(t *testing.T) { + type test struct { + m *CreatePoolProposal + expectErr bool + } + + cases := map[string]test{ + "invalid pair": {&CreatePoolProposal{ + Title: "add proposal", + Description: "some weird description", + Pair: "invalidpair", + }, true}, + "invalid trade limit ratio < 0": { + m: &CreatePoolProposal{ + Title: "add proposal", + Description: "some weird description", + Pair: "valid:pair", + TradeLimitRatio: sdk.NewDec(-1), + }, + expectErr: true, + }, + + "invalid trade limit ratio > 1": { + m: &CreatePoolProposal{ + Title: "add proposal", + Description: "some weird description", + Pair: "valid:pair", + TradeLimitRatio: sdk.NewDec(2), + }, + expectErr: true, + }, + + "quote asset reserve 0": { + m: &CreatePoolProposal{ + Title: "add proposal", + Description: "some weird description", + Pair: "valid:pair", + TradeLimitRatio: sdk.MustNewDecFromStr("0.10"), + QuoteAssetReserve: sdk.ZeroDec(), + }, + expectErr: true, + }, + + "base asset reserve 0": { + m: &CreatePoolProposal{ + Title: "add proposal", + Description: "some weird description", + Pair: "valid:pair", + TradeLimitRatio: sdk.MustNewDecFromStr("0.10"), + QuoteAssetReserve: sdk.NewDec(1_000_000), + BaseAssetReserve: sdk.ZeroDec(), + }, + expectErr: true, + }, + + "fluctuation < 0": { + m: &CreatePoolProposal{ + Title: "add proposal", + Description: "some weird description", + Pair: "valid:pair", + TradeLimitRatio: sdk.MustNewDecFromStr("0.10"), + QuoteAssetReserve: sdk.NewDec(1_000_000), + BaseAssetReserve: sdk.NewDec(1_000_000), + FluctuationLimitRatio: sdk.NewDec(-1), + }, + expectErr: true, + }, + + "fluctuation > 1": { + m: &CreatePoolProposal{ + Title: "add proposal", + Description: "some weird description", + Pair: "valid:pair", + TradeLimitRatio: sdk.MustNewDecFromStr("0.10"), + QuoteAssetReserve: sdk.NewDec(1_000_000), + BaseAssetReserve: sdk.NewDec(1_000_000), + FluctuationLimitRatio: sdk.NewDec(2), + }, + expectErr: true, + }, + + "max oracle spread ratio < 0": { + m: &CreatePoolProposal{ + Title: "add proposal", + Description: "some weird description", + Pair: "valid:pair", + TradeLimitRatio: sdk.MustNewDecFromStr("0.10"), + QuoteAssetReserve: sdk.NewDec(1_000_000), + BaseAssetReserve: sdk.NewDec(1_000_000), + FluctuationLimitRatio: sdk.MustNewDecFromStr("0.10"), + MaxOracleSpreadRatio: sdk.NewDec(-1), + }, + expectErr: true, + }, + "max oracle spread ratio > 1": { + m: &CreatePoolProposal{ + Title: "add proposal", + Description: "some weird description", + Pair: "valid:pair", + TradeLimitRatio: sdk.MustNewDecFromStr("0.10"), + QuoteAssetReserve: sdk.NewDec(1_000_000), + BaseAssetReserve: sdk.NewDec(1_000_000), + FluctuationLimitRatio: sdk.MustNewDecFromStr("0.10"), + MaxOracleSpreadRatio: sdk.NewDec(2), + }, + expectErr: true, + }, + + "success": { + m: &CreatePoolProposal{ + Title: "add proposal", + Description: "some weird description", + Pair: "valid:pair", + TradeLimitRatio: sdk.MustNewDecFromStr("0.10"), + QuoteAssetReserve: sdk.NewDec(1_000_000), + BaseAssetReserve: sdk.NewDec(1_000_000), + FluctuationLimitRatio: sdk.MustNewDecFromStr("0.10"), + MaxOracleSpreadRatio: sdk.MustNewDecFromStr("0.10"), + }, + expectErr: false, + }, + } + + for name, tc := range cases { + tc := tc + t.Run(name, func(t *testing.T) { + err := tc.m.ValidateBasic() + if err == nil && tc.expectErr { + t.Fatal("error expected") + } else if err != nil && !tc.expectErr { + t.Fatal("unexpected error") + } + }) + } +} From 9999db8b9f59d391ef73145a60baac08a37bb02c Mon Sep 17 00:00:00 2001 From: godismercilex Date: Mon, 25 Jul 2022 14:33:58 +0200 Subject: [PATCH 10/13] chore: lint --- x/vpool/types/gov_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x/vpool/types/gov_test.go b/x/vpool/types/gov_test.go index 2f7c400fb..1ff814848 100644 --- a/x/vpool/types/gov_test.go +++ b/x/vpool/types/gov_test.go @@ -1,8 +1,9 @@ package types import ( - sdk "github.com/cosmos/cosmos-sdk/types" "testing" + + sdk "github.com/cosmos/cosmos-sdk/types" ) func TestCreatePoolProposal_ValidateBasic(t *testing.T) { From 43e33ec2ca784ec0cb1ead71ded4a5be96f64f2a Mon Sep 17 00:00:00 2001 From: godismercilex Date: Tue, 26 Jul 2022 11:08:34 +0200 Subject: [PATCH 11/13] change: address reviews --- x/vpool/handler.go | 1 - x/vpool/types/gov.go | 21 +++++---------------- 2 files changed, 5 insertions(+), 17 deletions(-) diff --git a/x/vpool/handler.go b/x/vpool/handler.go index de8d9bb5c..894268190 100644 --- a/x/vpool/handler.go +++ b/x/vpool/handler.go @@ -41,7 +41,6 @@ func NewCreatePoolProposalHandler(k keeper.Keeper) govtypes.Handler { m.FluctuationLimitRatio, m.MaxOracleSpreadRatio, ) - // TODO(mercilex): oracle missing, pool should not be tradeable return nil default: return sdkerrors.Wrapf( diff --git a/x/vpool/types/gov.go b/x/vpool/types/gov.go index e35842fdf..747cde314 100644 --- a/x/vpool/types/gov.go +++ b/x/vpool/types/gov.go @@ -15,14 +15,6 @@ const ( var _ govtypes.Content = &CreatePoolProposal{} -// NEVER MUTATE THESE! -// they exist for comparisons only and to avoid constant allocations of a new big int -// which is used only for reading. -var ( - oneDec = sdk.OneDec() - zeroDec = sdk.ZeroDec() -) - func init() { govtypes.RegisterProposalType(ProposalTypeCreatePool) govtypes.RegisterProposalTypeCodec(&CreatePoolProposal{}, "nibiru/CreatePoolProposal") @@ -46,30 +38,27 @@ func (m *CreatePoolProposal) ValidateBasic() error { } // trade limit ratio always between 0 and 1 - // TODO(mercilex): does it really make sense for this to be equal to zero? - if m.TradeLimitRatio.LT(zeroDec) || m.TradeLimitRatio.GT(oneDec) { + if m.TradeLimitRatio.LT(sdk.ZeroDec()) || m.TradeLimitRatio.GT(sdk.OneDec()) { return fmt.Errorf("trade limit ratio must be 0 <= ratio <= 1") } // quote asset reserve always > 0 - if m.QuoteAssetReserve.LTE(zeroDec) { + if !m.QuoteAssetReserve.IsPositive() { return fmt.Errorf("quote asset reserve must be > 0") } // base asset reserve always > 0 - if m.BaseAssetReserve.LTE(zeroDec) { + if !m.BaseAssetReserve.IsPositive() { return fmt.Errorf("base asset reserve must be > 0") } // fluctuation limit ratio between 0 and 1 - // TODO(mercilex): does it really make sense for this to be equal to zero? - if m.FluctuationLimitRatio.LT(zeroDec) || m.FluctuationLimitRatio.GT(oneDec) { + if m.FluctuationLimitRatio.LT(sdk.ZeroDec()) || m.FluctuationLimitRatio.GT(sdk.OneDec()) { return fmt.Errorf("fluctuation limit ratio must be 0 <= ratio <= 1") } // max oracle spread ratio between 0 and 1 - // TODO(mercilex): does it really make sense for this to be equal to zero? - if m.MaxOracleSpreadRatio.LT(zeroDec) || m.MaxOracleSpreadRatio.GT(oneDec) { + if m.MaxOracleSpreadRatio.LT(sdk.ZeroDec()) || m.MaxOracleSpreadRatio.GT(sdk.OneDec()) { return fmt.Errorf("max oracle spread ratio must be 0 <= ratio <= 1") } From 6b587ce69eff37dc3aa7618dc2468effd6cb9090 Mon Sep 17 00:00:00 2001 From: godismercilex Date: Tue, 26 Jul 2022 11:28:50 +0200 Subject: [PATCH 12/13] change: address merge changes --- proto/vpool/v1/gov.proto | 6 +++ x/vpool/handler.go | 1 + x/vpool/types/gov.go | 4 ++ x/vpool/types/gov.pb.go | 100 ++++++++++++++++++++++++++++---------- x/vpool/types/gov_test.go | 45 ++++++++++++++--- 5 files changed, 123 insertions(+), 33 deletions(-) diff --git a/proto/vpool/v1/gov.proto b/proto/vpool/v1/gov.proto index c983d60d2..ed9980c0d 100644 --- a/proto/vpool/v1/gov.proto +++ b/proto/vpool/v1/gov.proto @@ -40,4 +40,10 @@ message CreatePoolProposal { (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", (gogoproto.nullable) = false ]; + + // maintenance_margin_ratio + string maintenance_margin_ratio = 9 [ + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", + (gogoproto.nullable) = false + ]; } \ No newline at end of file diff --git a/x/vpool/handler.go b/x/vpool/handler.go index 894268190..2fa2b4be4 100644 --- a/x/vpool/handler.go +++ b/x/vpool/handler.go @@ -40,6 +40,7 @@ func NewCreatePoolProposalHandler(k keeper.Keeper) govtypes.Handler { m.BaseAssetReserve, m.FluctuationLimitRatio, m.MaxOracleSpreadRatio, + m.MaintenanceMarginRatio, ) return nil default: diff --git a/x/vpool/types/gov.go b/x/vpool/types/gov.go index 747cde314..1c641be81 100644 --- a/x/vpool/types/gov.go +++ b/x/vpool/types/gov.go @@ -62,5 +62,9 @@ func (m *CreatePoolProposal) ValidateBasic() error { return fmt.Errorf("max oracle spread ratio must be 0 <= ratio <= 1") } + if m.MaintenanceMarginRatio.LT(sdk.ZeroDec()) || m.MaintenanceMarginRatio.GT(sdk.OneDec()) { + return fmt.Errorf("maintainance margin ratio ratio must be 0 <= ratio <= 1") + } + return nil } diff --git a/x/vpool/types/gov.pb.go b/x/vpool/types/gov.pb.go index 8e8148675..d6a0feb02 100644 --- a/x/vpool/types/gov.pb.go +++ b/x/vpool/types/gov.pb.go @@ -41,6 +41,8 @@ type CreatePoolProposal struct { // max_oracle_spread_ratio represents the maximum price percentage // difference that can exist between oracle price and vpool prices after a trade. MaxOracleSpreadRatio github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,8,opt,name=max_oracle_spread_ratio,json=maxOracleSpreadRatio,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"max_oracle_spread_ratio"` + // maintenance_margin_ratio + MaintenanceMarginRatio github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,9,opt,name=maintenance_margin_ratio,json=maintenanceMarginRatio,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"maintenance_margin_ratio"` } func (m *CreatePoolProposal) Reset() { *m = CreatePoolProposal{} } @@ -104,31 +106,33 @@ func init() { func init() { proto.RegisterFile("vpool/v1/gov.proto", fileDescriptor_8a393460ab414204) } var fileDescriptor_8a393460ab414204 = []byte{ - // 377 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0xd2, 0xc1, 0x6e, 0x9b, 0x30, - 0x18, 0x07, 0x70, 0xd8, 0x92, 0x6c, 0xf3, 0x0e, 0x59, 0xbc, 0x4c, 0x41, 0x3b, 0x90, 0x68, 0x87, - 0x69, 0xd2, 0x54, 0xac, 0xa8, 0x4f, 0xd0, 0xa4, 0xbd, 0x55, 0x6d, 0x44, 0x6f, 0x51, 0x55, 0x64, - 0xc0, 0x21, 0x56, 0x81, 0x8f, 0xda, 0x06, 0xa5, 0x6f, 0xd1, 0xc7, 0x4a, 0x6f, 0x39, 0x56, 0x3d, - 0x44, 0x55, 0xf2, 0x22, 0x15, 0x26, 0x07, 0xd2, 0x23, 0x27, 0x0c, 0x9f, 0xf5, 0xfb, 0x8b, 0x4f, - 0x7f, 0x84, 0x8b, 0x0c, 0x20, 0x26, 0xc5, 0x98, 0x44, 0x50, 0x38, 0x99, 0x00, 0x05, 0xb8, 0x9b, - 0x72, 0x9f, 0x8b, 0xdc, 0xd1, 0x23, 0xa7, 0x18, 0xff, 0xee, 0x47, 0x10, 0x81, 0x9e, 0x91, 0xf2, - 0x54, 0x5d, 0xfb, 0xf3, 0xdc, 0x42, 0x78, 0x2a, 0x18, 0x55, 0x6c, 0x06, 0x10, 0xcf, 0x04, 0x64, - 0x20, 0x69, 0x8c, 0xfb, 0xa8, 0xad, 0xb8, 0x8a, 0x99, 0x65, 0x8e, 0xcc, 0x7f, 0xdf, 0xdc, 0xea, - 0x05, 0x8f, 0xd0, 0xf7, 0x90, 0xc9, 0x40, 0xf0, 0x4c, 0x71, 0x48, 0xad, 0x4f, 0x7a, 0x56, 0xff, - 0x84, 0x31, 0x6a, 0x65, 0x94, 0x0b, 0xeb, 0xb3, 0x1e, 0xe9, 0x33, 0x9e, 0xa3, 0x9e, 0x12, 0x34, - 0x64, 0x5e, 0xcc, 0x13, 0xae, 0x3c, 0x41, 0x15, 0x07, 0xab, 0x55, 0x5e, 0x98, 0x38, 0xeb, 0xed, - 0xd0, 0x78, 0xdd, 0x0e, 0xff, 0x46, 0x5c, 0x2d, 0x73, 0xdf, 0x09, 0x20, 0x21, 0x01, 0xc8, 0x04, - 0xe4, 0xe1, 0x71, 0x22, 0xc3, 0x7b, 0xa2, 0x1e, 0x33, 0x26, 0x9d, 0x73, 0x16, 0xb8, 0x5d, 0x0d, - 0x5d, 0x96, 0x8e, 0x5b, 0x32, 0xf8, 0x0e, 0xfd, 0x7c, 0xc8, 0x41, 0x31, 0x8f, 0x4a, 0xc9, 0x94, - 0x27, 0x98, 0x64, 0xa2, 0x60, 0x56, 0xbb, 0x91, 0xde, 0xd3, 0xd4, 0x59, 0x29, 0xb9, 0x15, 0x84, - 0x6f, 0x11, 0xf6, 0xa9, 0xfc, 0xc8, 0x77, 0x1a, 0xf1, 0x3f, 0x4a, 0xe9, 0x48, 0x5f, 0xa0, 0xc1, - 0x22, 0xce, 0x03, 0x95, 0x97, 0xff, 0x92, 0x1e, 0xed, 0xe7, 0x4b, 0xa3, 0x88, 0x5f, 0x35, 0xae, - 0xb6, 0x25, 0x86, 0x06, 0x09, 0x5d, 0x79, 0x20, 0x68, 0x10, 0x33, 0x4f, 0x66, 0x82, 0xd1, 0xf0, - 0x90, 0xf3, 0xb5, 0x51, 0x4e, 0x3f, 0xa1, 0xab, 0x6b, 0xad, 0xdd, 0x68, 0x4c, 0xc7, 0x4c, 0x2e, - 0xd6, 0x3b, 0xdb, 0xdc, 0xec, 0x6c, 0xf3, 0x6d, 0x67, 0x9b, 0x4f, 0x7b, 0xdb, 0xd8, 0xec, 0x6d, - 0xe3, 0x65, 0x6f, 0x1b, 0xf3, 0xff, 0x35, 0xf7, 0x4a, 0xf7, 0x72, 0xba, 0xa4, 0x3c, 0x25, 0x55, - 0x47, 0xc9, 0x8a, 0x54, 0x05, 0xd6, 0x01, 0x7e, 0x47, 0x37, 0xf3, 0xf4, 0x3d, 0x00, 0x00, 0xff, - 0xff, 0xf0, 0xd1, 0x57, 0xb4, 0xd6, 0x02, 0x00, 0x00, + // 404 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0xd3, 0xcf, 0xae, 0x93, 0x40, + 0x14, 0x06, 0x70, 0xd0, 0xdb, 0xab, 0x77, 0x5c, 0x5c, 0x3b, 0x56, 0x4b, 0x5c, 0xd0, 0xc6, 0x85, + 0x31, 0x31, 0x32, 0x69, 0x7c, 0x02, 0x5b, 0xdd, 0xf9, 0xa7, 0xc1, 0x5d, 0x63, 0x24, 0x03, 0x9c, + 0xd2, 0x89, 0x30, 0x07, 0x67, 0x06, 0x52, 0xdf, 0xc2, 0x77, 0xf1, 0x25, 0xba, 0xec, 0xd2, 0xb8, + 0x68, 0x4c, 0xfb, 0x22, 0x86, 0xa1, 0x0b, 0xea, 0x92, 0x15, 0x03, 0x67, 0xf2, 0xfb, 0xc2, 0x49, + 0x3e, 0x42, 0xeb, 0x12, 0x31, 0x67, 0xf5, 0x8c, 0x65, 0x58, 0x07, 0xa5, 0x42, 0x83, 0xf4, 0x56, + 0x8a, 0x58, 0xa8, 0x2a, 0xb0, 0xa3, 0xa0, 0x9e, 0x3d, 0x1d, 0x65, 0x98, 0xa1, 0x9d, 0xb1, 0xe6, + 0xd4, 0x5e, 0x7b, 0xf6, 0x6b, 0x40, 0xe8, 0x42, 0x01, 0x37, 0xb0, 0x44, 0xcc, 0x97, 0x0a, 0x4b, + 0xd4, 0x3c, 0xa7, 0x23, 0x32, 0x30, 0xc2, 0xe4, 0xe0, 0xb9, 0x53, 0xf7, 0xc5, 0x4d, 0xd8, 0xbe, + 0xd0, 0x29, 0x79, 0x90, 0x82, 0x4e, 0x94, 0x28, 0x8d, 0x40, 0xe9, 0xdd, 0xb1, 0xb3, 0xee, 0x27, + 0x4a, 0xc9, 0x55, 0xc9, 0x85, 0xf2, 0xee, 0xda, 0x91, 0x3d, 0xd3, 0x15, 0x19, 0x1a, 0xc5, 0x53, + 0x88, 0x72, 0x51, 0x08, 0x13, 0x29, 0x6e, 0x04, 0x7a, 0x57, 0xcd, 0x85, 0x79, 0xb0, 0x3b, 0x4c, + 0x9c, 0x3f, 0x87, 0xc9, 0xf3, 0x4c, 0x98, 0x4d, 0x15, 0x07, 0x09, 0x16, 0x2c, 0x41, 0x5d, 0xa0, + 0x3e, 0x3f, 0x5e, 0xe9, 0xf4, 0x1b, 0x33, 0x3f, 0x4a, 0xd0, 0xc1, 0x5b, 0x48, 0xc2, 0x5b, 0x0b, + 0xbd, 0x6f, 0x9c, 0xb0, 0x61, 0xe8, 0x57, 0xf2, 0xe8, 0x7b, 0x85, 0x06, 0x22, 0xae, 0x35, 0x98, + 0x48, 0x81, 0x06, 0x55, 0x83, 0x37, 0xe8, 0xa5, 0x0f, 0x2d, 0xf5, 0xa6, 0x91, 0xc2, 0x16, 0xa2, + 0x5f, 0x08, 0x8d, 0xb9, 0xfe, 0x9f, 0xbf, 0xee, 0xc5, 0x3f, 0x6c, 0xa4, 0x0b, 0x7d, 0x4d, 0xc6, + 0xeb, 0xbc, 0x4a, 0x4c, 0xd5, 0xfc, 0x8b, 0xbc, 0xd8, 0xcf, 0xbd, 0x5e, 0x11, 0x8f, 0x3b, 0x5c, + 0x67, 0x4b, 0x40, 0xc6, 0x05, 0xdf, 0x46, 0xa8, 0x78, 0x92, 0x43, 0xa4, 0x4b, 0x05, 0x3c, 0x3d, + 0xe7, 0xdc, 0xef, 0x95, 0x33, 0x2a, 0xf8, 0xf6, 0x93, 0xd5, 0x3e, 0x5b, 0xac, 0x8d, 0xd9, 0x10, + 0xaf, 0xe0, 0x42, 0x1a, 0x90, 0x5c, 0x26, 0x10, 0x15, 0x5c, 0x65, 0x42, 0x9e, 0x73, 0x6e, 0x7a, + 0xe5, 0x3c, 0xe9, 0x78, 0x1f, 0x2c, 0x67, 0x93, 0xe6, 0xef, 0x76, 0x47, 0xdf, 0xdd, 0x1f, 0x7d, + 0xf7, 0xef, 0xd1, 0x77, 0x7f, 0x9e, 0x7c, 0x67, 0x7f, 0xf2, 0x9d, 0xdf, 0x27, 0xdf, 0x59, 0xbd, + 0xec, 0xc8, 0x1f, 0x6d, 0x03, 0x16, 0x1b, 0x2e, 0x24, 0x6b, 0xdb, 0xc0, 0xb6, 0xac, 0xad, 0x8a, + 0x8d, 0x88, 0xaf, 0x6d, 0x07, 0x5e, 0xff, 0x0b, 0x00, 0x00, 0xff, 0xff, 0xf0, 0xea, 0x61, 0x1d, + 0x40, 0x03, 0x00, 0x00, } func (m *CreatePoolProposal) Marshal() (dAtA []byte, err error) { @@ -151,6 +155,16 @@ func (m *CreatePoolProposal) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + { + size := m.MaintenanceMarginRatio.Size() + i -= size + if _, err := m.MaintenanceMarginRatio.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintGov(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x4a { size := m.MaxOracleSpreadRatio.Size() i -= size @@ -264,6 +278,8 @@ func (m *CreatePoolProposal) Size() (n int) { n += 1 + l + sovGov(uint64(l)) l = m.MaxOracleSpreadRatio.Size() n += 1 + l + sovGov(uint64(l)) + l = m.MaintenanceMarginRatio.Size() + n += 1 + l + sovGov(uint64(l)) return n } @@ -568,6 +584,40 @@ func (m *CreatePoolProposal) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 9: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MaintenanceMarginRatio", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGov + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGov + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGov + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.MaintenanceMarginRatio.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGov(dAtA[iNdEx:]) diff --git a/x/vpool/types/gov_test.go b/x/vpool/types/gov_test.go index 1ff814848..8a0e6bd34 100644 --- a/x/vpool/types/gov_test.go +++ b/x/vpool/types/gov_test.go @@ -113,17 +113,46 @@ func TestCreatePoolProposal_ValidateBasic(t *testing.T) { }, expectErr: true, }, + "maintenance ratio < 0": { + m: &CreatePoolProposal{ + Title: "add proposal", + Description: "some weird description", + Pair: "valid:pair", + TradeLimitRatio: sdk.MustNewDecFromStr("0.10"), + QuoteAssetReserve: sdk.NewDec(1_000_000), + BaseAssetReserve: sdk.NewDec(1_000_000), + FluctuationLimitRatio: sdk.MustNewDecFromStr("0.10"), + MaxOracleSpreadRatio: sdk.MustNewDecFromStr("0.10"), + MaintenanceMarginRatio: sdk.NewDec(-1), + }, + expectErr: true, + }, + "maintenance ratio > 1": { + m: &CreatePoolProposal{ + Title: "add proposal", + Description: "some weird description", + Pair: "valid:pair", + TradeLimitRatio: sdk.MustNewDecFromStr("0.10"), + QuoteAssetReserve: sdk.NewDec(1_000_000), + BaseAssetReserve: sdk.NewDec(1_000_000), + FluctuationLimitRatio: sdk.MustNewDecFromStr("0.10"), + MaxOracleSpreadRatio: sdk.MustNewDecFromStr("0.10"), + MaintenanceMarginRatio: sdk.NewDec(2), + }, + expectErr: true, + }, "success": { m: &CreatePoolProposal{ - Title: "add proposal", - Description: "some weird description", - Pair: "valid:pair", - TradeLimitRatio: sdk.MustNewDecFromStr("0.10"), - QuoteAssetReserve: sdk.NewDec(1_000_000), - BaseAssetReserve: sdk.NewDec(1_000_000), - FluctuationLimitRatio: sdk.MustNewDecFromStr("0.10"), - MaxOracleSpreadRatio: sdk.MustNewDecFromStr("0.10"), + Title: "add proposal", + Description: "some weird description", + Pair: "valid:pair", + TradeLimitRatio: sdk.MustNewDecFromStr("0.10"), + QuoteAssetReserve: sdk.NewDec(1_000_000), + BaseAssetReserve: sdk.NewDec(1_000_000), + FluctuationLimitRatio: sdk.MustNewDecFromStr("0.10"), + MaxOracleSpreadRatio: sdk.MustNewDecFromStr("0.10"), + MaintenanceMarginRatio: sdk.MustNewDecFromStr("0.0625"), }, expectErr: false, }, From dad5e789bcc810b4562308341e261fac76747c4b Mon Sep 17 00:00:00 2001 From: godismercilex Date: Tue, 26 Jul 2022 11:35:01 +0200 Subject: [PATCH 13/13] chore: lint --- x/vpool/types/gov.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/vpool/types/gov.go b/x/vpool/types/gov.go index 1c641be81..f9ae10a7f 100644 --- a/x/vpool/types/gov.go +++ b/x/vpool/types/gov.go @@ -63,7 +63,7 @@ func (m *CreatePoolProposal) ValidateBasic() error { } if m.MaintenanceMarginRatio.LT(sdk.ZeroDec()) || m.MaintenanceMarginRatio.GT(sdk.OneDec()) { - return fmt.Errorf("maintainance margin ratio ratio must be 0 <= ratio <= 1") + return fmt.Errorf("maintenance margin ratio ratio must be 0 <= ratio <= 1") } return nil