From 2bceab44e8b68c78869dce616c99db865c9e1572 Mon Sep 17 00:00:00 2001
From: Teddy Ding <teddy@dydx.exchange>
Date: Fri, 8 Dec 2023 13:50:51 -0500
Subject: [PATCH] initial protos for x/ibcratelimit

---
 .../dydxprotocol/ibcratelimit/capacity.proto  |   20 +
 proto/dydxprotocol/ibcratelimit/genesis.proto |   13 +
 .../ibcratelimit/limit_params.proto           |   35 +
 proto/dydxprotocol/ibcratelimit/query.proto   |   46 +
 proto/dydxprotocol/ibcratelimit/tx.proto      |   42 +
 protocol/x/ibcratelimit/types/capacity.pb.go  |  384 ++++++
 protocol/x/ibcratelimit/types/genesis.pb.go   |  334 +++++
 .../x/ibcratelimit/types/limit_params.pb.go   |  640 +++++++++
 protocol/x/ibcratelimit/types/query.pb.go     | 1146 +++++++++++++++++
 protocol/x/ibcratelimit/types/tx.pb.go        |  978 ++++++++++++++
 10 files changed, 3638 insertions(+)
 create mode 100644 proto/dydxprotocol/ibcratelimit/capacity.proto
 create mode 100644 proto/dydxprotocol/ibcratelimit/genesis.proto
 create mode 100644 proto/dydxprotocol/ibcratelimit/limit_params.proto
 create mode 100644 proto/dydxprotocol/ibcratelimit/query.proto
 create mode 100644 proto/dydxprotocol/ibcratelimit/tx.proto
 create mode 100644 protocol/x/ibcratelimit/types/capacity.pb.go
 create mode 100644 protocol/x/ibcratelimit/types/genesis.pb.go
 create mode 100644 protocol/x/ibcratelimit/types/limit_params.pb.go
 create mode 100644 protocol/x/ibcratelimit/types/query.pb.go
 create mode 100644 protocol/x/ibcratelimit/types/tx.pb.go

diff --git a/proto/dydxprotocol/ibcratelimit/capacity.proto b/proto/dydxprotocol/ibcratelimit/capacity.proto
new file mode 100644
index 0000000000..2891f3ce3a
--- /dev/null
+++ b/proto/dydxprotocol/ibcratelimit/capacity.proto
@@ -0,0 +1,20 @@
+syntax = "proto3";
+package dydxprotocol.ibcratelimit;
+
+import "gogoproto/gogo.proto";
+
+option go_package = "github.com/dydxprotocol/v4-chain/protocol/x/ibcratelimit/types";
+
+// DenomCapacity stores a list of rate limit capacity for a denom.
+message DenomCapacity {
+  // denom is the denomination of the token being rate limited.
+  // e.g. ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5
+  string denom = 1; 
+  // capacity_list is a list of capacity amount tracked for each `Limiter`
+  // on the denom. This list has a 1:1 mapping to `limiter` list under `LimitParams`.
+  repeated bytes capacity_list = 2 [
+    (gogoproto.customtype) =
+        "github.com/dydxprotocol/v4-chain/protocol/dtypes.SerializableInt",
+    (gogoproto.nullable) = false
+  ];
+}
diff --git a/proto/dydxprotocol/ibcratelimit/genesis.proto b/proto/dydxprotocol/ibcratelimit/genesis.proto
new file mode 100644
index 0000000000..0c9d563fd3
--- /dev/null
+++ b/proto/dydxprotocol/ibcratelimit/genesis.proto
@@ -0,0 +1,13 @@
+syntax = "proto3";
+package dydxprotocol.ibcratelimit;
+
+import "gogoproto/gogo.proto";
+import "dydxprotocol/ibcratelimit/limit_params.proto";
+
+option go_package = "github.com/dydxprotocol/v4-chain/protocol/x/ibcratelimit/types";
+
+// GenesisState defines the ibcratelimit module's genesis state.
+message GenesisState {
+  // limit_params_list defines the list of `LimitParams` at genesis.
+  repeated LimitParams limit_params_list = 1 [ (gogoproto.nullable) = false ];
+}
diff --git a/proto/dydxprotocol/ibcratelimit/limit_params.proto b/proto/dydxprotocol/ibcratelimit/limit_params.proto
new file mode 100644
index 0000000000..a1aac69188
--- /dev/null
+++ b/proto/dydxprotocol/ibcratelimit/limit_params.proto
@@ -0,0 +1,35 @@
+syntax = "proto3";
+package dydxprotocol.ibcratelimit;
+
+import "gogoproto/gogo.proto";
+
+option go_package = "github.com/dydxprotocol/v4-chain/protocol/x/ibcratelimit/types";
+
+// LimitParams defines rate limit params on a denom.
+message LimitParams {
+  // denom is the denomination of the token being rate limited.
+  // e.g. ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5
+  string denom = 1; 
+  // limiters is a list of rate-limiters on this denom. All limiters
+  // must be satified for a withdrawal to proceed.
+  repeated Limiter limiters = 2;
+}
+
+// Limiter defines one rate-limiter on a specfic denom.
+message Limiter {
+    // period_sec is the rolling time period for which the limit applies
+  // e.g. 3600 (an hour)
+  uint32 period_sec = 2;
+  // baseline_minimum is the minimum maximum withdrawal coin amount within the
+  // time period.
+  // e.g. 100_000_000_000 uusdc for 100k USDC; 5e22 adv4tnt for 50k DV4TNT   
+  bytes baseline_minimum = 3 [
+    (gogoproto.customtype) =
+        "github.com/dydxprotocol/v4-chain/protocol/dtypes.SerializableInt",
+    (gogoproto.nullable) = false
+  ];
+  // baseline_tvl_ppm is the maximum ratio of TVL withdrawable in 
+  // the time period, in part-per-million.
+  // e.g. 100_000 (10%)
+  uint32 baseline_tvl_ppm = 4;
+}
\ No newline at end of file
diff --git a/proto/dydxprotocol/ibcratelimit/query.proto b/proto/dydxprotocol/ibcratelimit/query.proto
new file mode 100644
index 0000000000..8170725743
--- /dev/null
+++ b/proto/dydxprotocol/ibcratelimit/query.proto
@@ -0,0 +1,46 @@
+syntax = "proto3";
+package dydxprotocol.ibcratelimit;
+
+import "gogoproto/gogo.proto";
+import "dydxprotocol/ibcratelimit/limit_params.proto";
+
+option go_package = "github.com/dydxprotocol/v4-chain/protocol/x/ibcratelimit/types";
+
+// Query defines the gRPC querier service.
+service Query {
+  // List all limit params.
+	rpc ListLimitParams(ListLimitParamsRequest)
+		returns (ListLimitParamsResponse);
+
+  // Query capacity by denom.
+	rpc CapacityByDenom(QueryCapacityByDenomRequest)
+		returns (QueryCapacityByDenomResponse);
+}
+
+// ListLimitParamsRequest is a request type of the ListLimitParams RPC method.
+message ListLimitParamsRequest {}
+
+// ListLimitParamsResponse is a response type of the ListLimitParams RPC method.
+message ListLimitParamsResponse {
+	repeated LimitParams limit_params_list = 1;
+}
+
+// QueryCapacityByDenomRequest is a request type for the CapacityByDenom RPC method.
+message QueryCapacityByDenomRequest {
+  string denom = 1;
+}
+
+// CapacityResult is a specific rate limit for a denom. 
+message CapacityResult {
+  uint32 period_sec = 1;
+  bytes capacity = 2 [
+    (gogoproto.customtype) =
+        "github.com/dydxprotocol/v4-chain/protocol/dtypes.SerializableInt",
+    (gogoproto.nullable) = false
+  ];
+}
+
+// QueryCapacityByDenomResponse is a response type of the CapacityByDenom RPC method.
+message QueryCapacityByDenomResponse {
+	repeated CapacityResult results = 1;
+}
\ No newline at end of file
diff --git a/proto/dydxprotocol/ibcratelimit/tx.proto b/proto/dydxprotocol/ibcratelimit/tx.proto
new file mode 100644
index 0000000000..0a8a4f5c54
--- /dev/null
+++ b/proto/dydxprotocol/ibcratelimit/tx.proto
@@ -0,0 +1,42 @@
+syntax = "proto3";
+package dydxprotocol.ibcratelimit;
+
+option go_package = "github.com/dydxprotocol/v4-chain/protocol/x/ibcratelimit/types";
+
+import "cosmos/msg/v1/msg.proto";
+import "dydxprotocol/ibcratelimit/limit_params.proto";
+
+// Msg defines the Msg service.
+service Msg {
+  // SetLimitParams sets a `LimitParams` object in state.
+  rpc SetLimitParams(MsgSetLimitParams) returns (MsgSetLimitParamsResponse);
+  
+  // DeleteLimitParams removes a `LimitParams` object in state.
+  rpc DeleteLimitParams(MsgDeleteLimitParams) returns (MsgDeleteLimitParamsResponse);
+}
+
+// MsgSetLimitParams is the Msg/SetLimitParams request type.
+message MsgSetLimitParams {
+  // The address that controls the module.
+  option (cosmos.msg.v1.signer) = "authority";
+  string authority = 1;
+
+  // Defines the parameters to set. All parameters must be supplied.
+	LimitParams limit_params = 2;
+}
+
+// MsgSetLimitParamsResponse is the Msg/SetLimitParams response type.
+message MsgSetLimitParamsResponse {}
+
+// MsgDeleteLimitParams is the Msg/SetLimitParams request type.
+message MsgDeleteLimitParams {
+  // The address that controls the module.
+  option (cosmos.msg.v1.signer) = "authority";
+  string authority = 1;
+
+  // The denom for which the `LimitParams` should be deleted.
+	string denom = 2;
+}
+
+// MsgDeleteLimitParamsResponse is the Msg/DeleteLimitParams response type.
+message MsgDeleteLimitParamsResponse {}
\ No newline at end of file
diff --git a/protocol/x/ibcratelimit/types/capacity.pb.go b/protocol/x/ibcratelimit/types/capacity.pb.go
new file mode 100644
index 0000000000..75624aeea1
--- /dev/null
+++ b/protocol/x/ibcratelimit/types/capacity.pb.go
@@ -0,0 +1,384 @@
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: dydxprotocol/ibcratelimit/capacity.proto
+
+package types
+
+import (
+	fmt "fmt"
+	_ "github.com/cosmos/gogoproto/gogoproto"
+	proto "github.com/cosmos/gogoproto/proto"
+	github_com_dydxprotocol_v4_chain_protocol_dtypes "github.com/dydxprotocol/v4-chain/protocol/dtypes"
+	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
+
+// DenomCapacity stores a list of rate limit capacity for a denom.
+type DenomCapacity struct {
+	// denom is the denomination of the token being rate limited.
+	// e.g. ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5
+	Denom string `protobuf:"bytes,1,opt,name=denom,proto3" json:"denom,omitempty"`
+	// capacity_list is a list of capacity amount tracked for each `Limiter`
+	// on the denom. This list has a 1:1 mapping to `limiter` list under `LimitParams`.
+	CapacityList []github_com_dydxprotocol_v4_chain_protocol_dtypes.SerializableInt `protobuf:"bytes,2,rep,name=capacity_list,json=capacityList,proto3,customtype=github.com/dydxprotocol/v4-chain/protocol/dtypes.SerializableInt" json:"capacity_list"`
+}
+
+func (m *DenomCapacity) Reset()         { *m = DenomCapacity{} }
+func (m *DenomCapacity) String() string { return proto.CompactTextString(m) }
+func (*DenomCapacity) ProtoMessage()    {}
+func (*DenomCapacity) Descriptor() ([]byte, []int) {
+	return fileDescriptor_1790e9bf7712f620, []int{0}
+}
+func (m *DenomCapacity) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *DenomCapacity) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_DenomCapacity.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 *DenomCapacity) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_DenomCapacity.Merge(m, src)
+}
+func (m *DenomCapacity) XXX_Size() int {
+	return m.Size()
+}
+func (m *DenomCapacity) XXX_DiscardUnknown() {
+	xxx_messageInfo_DenomCapacity.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_DenomCapacity proto.InternalMessageInfo
+
+func (m *DenomCapacity) GetDenom() string {
+	if m != nil {
+		return m.Denom
+	}
+	return ""
+}
+
+func init() {
+	proto.RegisterType((*DenomCapacity)(nil), "dydxprotocol.ibcratelimit.DenomCapacity")
+}
+
+func init() {
+	proto.RegisterFile("dydxprotocol/ibcratelimit/capacity.proto", fileDescriptor_1790e9bf7712f620)
+}
+
+var fileDescriptor_1790e9bf7712f620 = []byte{
+	// 236 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xd2, 0x48, 0xa9, 0x4c, 0xa9,
+	0x28, 0x28, 0xca, 0x2f, 0xc9, 0x4f, 0xce, 0xcf, 0xd1, 0xcf, 0x4c, 0x4a, 0x2e, 0x4a, 0x2c, 0x49,
+	0xcd, 0xc9, 0xcc, 0xcd, 0x2c, 0xd1, 0x4f, 0x4e, 0x2c, 0x48, 0x4c, 0xce, 0x2c, 0xa9, 0xd4, 0x03,
+	0x4b, 0x0b, 0x49, 0x22, 0xab, 0xd4, 0x43, 0x56, 0x29, 0x25, 0x92, 0x9e, 0x9f, 0x9e, 0x0f, 0x96,
+	0xd2, 0x07, 0xb1, 0x20, 0x1a, 0x94, 0xa6, 0x30, 0x72, 0xf1, 0xba, 0xa4, 0xe6, 0xe5, 0xe7, 0x3a,
+	0x43, 0x0d, 0x12, 0x12, 0xe1, 0x62, 0x4d, 0x01, 0x09, 0x48, 0x30, 0x2a, 0x30, 0x6a, 0x70, 0x06,
+	0x41, 0x38, 0x42, 0xb9, 0x5c, 0xbc, 0x30, 0xab, 0xe2, 0x73, 0x32, 0x8b, 0x4b, 0x24, 0x98, 0x14,
+	0x98, 0x35, 0x78, 0x9c, 0x3c, 0x4e, 0xdc, 0x93, 0x67, 0xb8, 0x75, 0x4f, 0xde, 0x21, 0x3d, 0xb3,
+	0x24, 0xa3, 0x34, 0x49, 0x2f, 0x39, 0x3f, 0x57, 0x1f, 0xc5, 0xb1, 0x65, 0x26, 0xba, 0xc9, 0x19,
+	0x89, 0x99, 0x79, 0xfa, 0x70, 0x91, 0x94, 0x92, 0xca, 0x82, 0xd4, 0x62, 0xbd, 0xe0, 0xd4, 0xa2,
+	0xcc, 0xc4, 0x9c, 0xcc, 0xaa, 0xc4, 0xa4, 0x9c, 0x54, 0xcf, 0xbc, 0x92, 0x20, 0x1e, 0x98, 0xf1,
+	0x3e, 0x99, 0xc5, 0x25, 0x4e, 0x11, 0x27, 0x1e, 0xc9, 0x31, 0x5e, 0x78, 0x24, 0xc7, 0xf8, 0xe0,
+	0x91, 0x1c, 0xe3, 0x84, 0xc7, 0x72, 0x0c, 0x17, 0x1e, 0xcb, 0x31, 0xdc, 0x78, 0x2c, 0xc7, 0x10,
+	0x65, 0x47, 0xbc, 0x4d, 0x15, 0xa8, 0x41, 0x05, 0xb6, 0x37, 0x89, 0x0d, 0x2c, 0x6d, 0x0c, 0x08,
+	0x00, 0x00, 0xff, 0xff, 0xf2, 0x7f, 0xa7, 0xb7, 0x54, 0x01, 0x00, 0x00,
+}
+
+func (m *DenomCapacity) 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 *DenomCapacity) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *DenomCapacity) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if len(m.CapacityList) > 0 {
+		for iNdEx := len(m.CapacityList) - 1; iNdEx >= 0; iNdEx-- {
+			{
+				size := m.CapacityList[iNdEx].Size()
+				i -= size
+				if _, err := m.CapacityList[iNdEx].MarshalTo(dAtA[i:]); err != nil {
+					return 0, err
+				}
+				i = encodeVarintCapacity(dAtA, i, uint64(size))
+			}
+			i--
+			dAtA[i] = 0x12
+		}
+	}
+	if len(m.Denom) > 0 {
+		i -= len(m.Denom)
+		copy(dAtA[i:], m.Denom)
+		i = encodeVarintCapacity(dAtA, i, uint64(len(m.Denom)))
+		i--
+		dAtA[i] = 0xa
+	}
+	return len(dAtA) - i, nil
+}
+
+func encodeVarintCapacity(dAtA []byte, offset int, v uint64) int {
+	offset -= sovCapacity(v)
+	base := offset
+	for v >= 1<<7 {
+		dAtA[offset] = uint8(v&0x7f | 0x80)
+		v >>= 7
+		offset++
+	}
+	dAtA[offset] = uint8(v)
+	return base
+}
+func (m *DenomCapacity) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	l = len(m.Denom)
+	if l > 0 {
+		n += 1 + l + sovCapacity(uint64(l))
+	}
+	if len(m.CapacityList) > 0 {
+		for _, e := range m.CapacityList {
+			l = e.Size()
+			n += 1 + l + sovCapacity(uint64(l))
+		}
+	}
+	return n
+}
+
+func sovCapacity(x uint64) (n int) {
+	return (math_bits.Len64(x|1) + 6) / 7
+}
+func sozCapacity(x uint64) (n int) {
+	return sovCapacity(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+}
+func (m *DenomCapacity) 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 ErrIntOverflowCapacity
+			}
+			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: DenomCapacity: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: DenomCapacity: 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 ErrIntOverflowCapacity
+				}
+				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 ErrInvalidLengthCapacity
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex < 0 {
+				return ErrInvalidLengthCapacity
+			}
+			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 CapacityList", wireType)
+			}
+			var byteLen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowCapacity
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				byteLen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if byteLen < 0 {
+				return ErrInvalidLengthCapacity
+			}
+			postIndex := iNdEx + byteLen
+			if postIndex < 0 {
+				return ErrInvalidLengthCapacity
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			var v github_com_dydxprotocol_v4_chain_protocol_dtypes.SerializableInt
+			m.CapacityList = append(m.CapacityList, v)
+			if err := m.CapacityList[len(m.CapacityList)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipCapacity(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if (skippy < 0) || (iNdEx+skippy) < 0 {
+				return ErrInvalidLengthCapacity
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func skipCapacity(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, ErrIntOverflowCapacity
+			}
+			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, ErrIntOverflowCapacity
+				}
+				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, ErrIntOverflowCapacity
+				}
+				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, ErrInvalidLengthCapacity
+			}
+			iNdEx += length
+		case 3:
+			depth++
+		case 4:
+			if depth == 0 {
+				return 0, ErrUnexpectedEndOfGroupCapacity
+			}
+			depth--
+		case 5:
+			iNdEx += 4
+		default:
+			return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
+		}
+		if iNdEx < 0 {
+			return 0, ErrInvalidLengthCapacity
+		}
+		if depth == 0 {
+			return iNdEx, nil
+		}
+	}
+	return 0, io.ErrUnexpectedEOF
+}
+
+var (
+	ErrInvalidLengthCapacity        = fmt.Errorf("proto: negative length found during unmarshaling")
+	ErrIntOverflowCapacity          = fmt.Errorf("proto: integer overflow")
+	ErrUnexpectedEndOfGroupCapacity = fmt.Errorf("proto: unexpected end of group")
+)
diff --git a/protocol/x/ibcratelimit/types/genesis.pb.go b/protocol/x/ibcratelimit/types/genesis.pb.go
new file mode 100644
index 0000000000..92f4d23e02
--- /dev/null
+++ b/protocol/x/ibcratelimit/types/genesis.pb.go
@@ -0,0 +1,334 @@
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: dydxprotocol/ibcratelimit/genesis.proto
+
+package types
+
+import (
+	fmt "fmt"
+	_ "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 ibcratelimit module's genesis state.
+type GenesisState struct {
+	// limit_params_list defines the list of `LimitParams` at genesis.
+	LimitParamsList []LimitParams `protobuf:"bytes,1,rep,name=limit_params_list,json=limitParamsList,proto3" json:"limit_params_list"`
+}
+
+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_fa1ff5707cde3652, []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) GetLimitParamsList() []LimitParams {
+	if m != nil {
+		return m.LimitParamsList
+	}
+	return nil
+}
+
+func init() {
+	proto.RegisterType((*GenesisState)(nil), "dydxprotocol.ibcratelimit.GenesisState")
+}
+
+func init() {
+	proto.RegisterFile("dydxprotocol/ibcratelimit/genesis.proto", fileDescriptor_fa1ff5707cde3652)
+}
+
+var fileDescriptor_fa1ff5707cde3652 = []byte{
+	// 219 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0x4f, 0xa9, 0x4c, 0xa9,
+	0x28, 0x28, 0xca, 0x2f, 0xc9, 0x4f, 0xce, 0xcf, 0xd1, 0xcf, 0x4c, 0x4a, 0x2e, 0x4a, 0x2c, 0x49,
+	0xcd, 0xc9, 0xcc, 0xcd, 0x2c, 0xd1, 0x4f, 0x4f, 0xcd, 0x4b, 0x2d, 0xce, 0x2c, 0xd6, 0x03, 0xcb,
+	0x0a, 0x49, 0x22, 0x2b, 0xd4, 0x43, 0x56, 0x28, 0x25, 0x92, 0x9e, 0x9f, 0x9e, 0x0f, 0x96, 0xd2,
+	0x07, 0xb1, 0x20, 0x1a, 0xa4, 0x74, 0x70, 0x9b, 0x0c, 0x26, 0xe3, 0x0b, 0x12, 0x8b, 0x12, 0x73,
+	0xa1, 0xc6, 0x2b, 0x65, 0x70, 0xf1, 0xb8, 0x43, 0xec, 0x0b, 0x2e, 0x49, 0x2c, 0x49, 0x15, 0x8a,
+	0xe0, 0x12, 0x44, 0x56, 0x15, 0x9f, 0x93, 0x59, 0x5c, 0x22, 0xc1, 0xa8, 0xc0, 0xac, 0xc1, 0x6d,
+	0xa4, 0xa6, 0x87, 0xd3, 0x29, 0x7a, 0x3e, 0x20, 0x32, 0x00, 0xac, 0xc5, 0x89, 0xe5, 0xc4, 0x3d,
+	0x79, 0x86, 0x20, 0xfe, 0x1c, 0x84, 0x90, 0x4f, 0x66, 0x71, 0x89, 0x53, 0xc4, 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, 0xd9, 0xa5, 0x67, 0x96, 0x64, 0x94, 0x26, 0xe9, 0x25,
+	0xe7, 0xe7, 0xea, 0xa3, 0x38, 0xbe, 0xcc, 0x44, 0x37, 0x39, 0x23, 0x31, 0x33, 0x4f, 0x1f, 0x2e,
+	0x52, 0x81, 0xea, 0xa1, 0x92, 0xca, 0x82, 0xd4, 0xe2, 0x24, 0x36, 0xb0, 0xb4, 0x31, 0x20, 0x00,
+	0x00, 0xff, 0xff, 0xff, 0x02, 0xf6, 0x8a, 0x54, 0x01, 0x00, 0x00,
+}
+
+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.LimitParamsList) > 0 {
+		for iNdEx := len(m.LimitParamsList) - 1; iNdEx >= 0; iNdEx-- {
+			{
+				size, err := m.LimitParamsList[iNdEx].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 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
+	if len(m.LimitParamsList) > 0 {
+		for _, e := range m.LimitParamsList {
+			l = e.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 LimitParamsList", 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.LimitParamsList = append(m.LimitParamsList, LimitParams{})
+			if err := m.LimitParamsList[len(m.LimitParamsList)-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 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/protocol/x/ibcratelimit/types/limit_params.pb.go b/protocol/x/ibcratelimit/types/limit_params.pb.go
new file mode 100644
index 0000000000..c90d500f5c
--- /dev/null
+++ b/protocol/x/ibcratelimit/types/limit_params.pb.go
@@ -0,0 +1,640 @@
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: dydxprotocol/ibcratelimit/limit_params.proto
+
+package types
+
+import (
+	fmt "fmt"
+	_ "github.com/cosmos/gogoproto/gogoproto"
+	proto "github.com/cosmos/gogoproto/proto"
+	github_com_dydxprotocol_v4_chain_protocol_dtypes "github.com/dydxprotocol/v4-chain/protocol/dtypes"
+	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
+
+// LimitParams defines rate limit params on a denom.
+type LimitParams struct {
+	// denom is the denomination of the token being rate limited.
+	// e.g. ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5
+	Denom string `protobuf:"bytes,1,opt,name=denom,proto3" json:"denom,omitempty"`
+	// limiters is a list of rate-limiters on this denom. All limiters
+	// must be satified for a withdrawal to proceed.
+	Limiters []*Limiter `protobuf:"bytes,2,rep,name=limiters,proto3" json:"limiters,omitempty"`
+}
+
+func (m *LimitParams) Reset()         { *m = LimitParams{} }
+func (m *LimitParams) String() string { return proto.CompactTextString(m) }
+func (*LimitParams) ProtoMessage()    {}
+func (*LimitParams) Descriptor() ([]byte, []int) {
+	return fileDescriptor_9b1618a221d924d8, []int{0}
+}
+func (m *LimitParams) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *LimitParams) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_LimitParams.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 *LimitParams) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_LimitParams.Merge(m, src)
+}
+func (m *LimitParams) XXX_Size() int {
+	return m.Size()
+}
+func (m *LimitParams) XXX_DiscardUnknown() {
+	xxx_messageInfo_LimitParams.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_LimitParams proto.InternalMessageInfo
+
+func (m *LimitParams) GetDenom() string {
+	if m != nil {
+		return m.Denom
+	}
+	return ""
+}
+
+func (m *LimitParams) GetLimiters() []*Limiter {
+	if m != nil {
+		return m.Limiters
+	}
+	return nil
+}
+
+// Limiter defines one rate-limiter on a specfic denom.
+type Limiter struct {
+	// period_sec is the rolling time period for which the limit applies
+	// e.g. 3600 (an hour)
+	PeriodSec uint32 `protobuf:"varint,2,opt,name=period_sec,json=periodSec,proto3" json:"period_sec,omitempty"`
+	// baseline_minimum is the minimum maximum withdrawal coin amount within the
+	// time period.
+	// e.g. 100_000_000_000 uusdc for 100k USDC; 5e22 adv4tnt for 50k DV4TNT
+	BaselineMinimum github_com_dydxprotocol_v4_chain_protocol_dtypes.SerializableInt `protobuf:"bytes,3,opt,name=baseline_minimum,json=baselineMinimum,proto3,customtype=github.com/dydxprotocol/v4-chain/protocol/dtypes.SerializableInt" json:"baseline_minimum"`
+	// baseline_tvl_ppm is the maximum ratio of TVL withdrawable in
+	// the time period, in part-per-million.
+	// e.g. 100_000 (10%)
+	BaselineTvlPpm uint32 `protobuf:"varint,4,opt,name=baseline_tvl_ppm,json=baselineTvlPpm,proto3" json:"baseline_tvl_ppm,omitempty"`
+}
+
+func (m *Limiter) Reset()         { *m = Limiter{} }
+func (m *Limiter) String() string { return proto.CompactTextString(m) }
+func (*Limiter) ProtoMessage()    {}
+func (*Limiter) Descriptor() ([]byte, []int) {
+	return fileDescriptor_9b1618a221d924d8, []int{1}
+}
+func (m *Limiter) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *Limiter) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_Limiter.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 *Limiter) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_Limiter.Merge(m, src)
+}
+func (m *Limiter) XXX_Size() int {
+	return m.Size()
+}
+func (m *Limiter) XXX_DiscardUnknown() {
+	xxx_messageInfo_Limiter.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Limiter proto.InternalMessageInfo
+
+func (m *Limiter) GetPeriodSec() uint32 {
+	if m != nil {
+		return m.PeriodSec
+	}
+	return 0
+}
+
+func (m *Limiter) GetBaselineTvlPpm() uint32 {
+	if m != nil {
+		return m.BaselineTvlPpm
+	}
+	return 0
+}
+
+func init() {
+	proto.RegisterType((*LimitParams)(nil), "dydxprotocol.ibcratelimit.LimitParams")
+	proto.RegisterType((*Limiter)(nil), "dydxprotocol.ibcratelimit.Limiter")
+}
+
+func init() {
+	proto.RegisterFile("dydxprotocol/ibcratelimit/limit_params.proto", fileDescriptor_9b1618a221d924d8)
+}
+
+var fileDescriptor_9b1618a221d924d8 = []byte{
+	// 329 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x51, 0xcf, 0x4b, 0xfb, 0x30,
+	0x1c, 0x6d, 0xb6, 0xef, 0x57, 0x5d, 0xe6, 0x2f, 0xca, 0x0e, 0x55, 0xb0, 0x2b, 0x3b, 0xf5, 0xa0,
+	0x2d, 0xa8, 0xe7, 0x21, 0x3b, 0x29, 0x4c, 0x18, 0x9d, 0x07, 0xf1, 0x52, 0xd2, 0x34, 0x6c, 0x81,
+	0xa4, 0x09, 0x4d, 0x36, 0x36, 0xff, 0x0a, 0xff, 0x2b, 0x77, 0xdc, 0x51, 0x3c, 0x0c, 0xd9, 0xfe,
+	0x11, 0x59, 0xea, 0x46, 0x77, 0x10, 0xbc, 0x84, 0xe4, 0xbd, 0xf7, 0x79, 0xef, 0x91, 0x0f, 0xbc,
+	0x4c, 0xa7, 0xe9, 0x44, 0xe6, 0x42, 0x0b, 0x2c, 0x58, 0x48, 0x13, 0x9c, 0x23, 0x4d, 0x18, 0xe5,
+	0x54, 0x87, 0xe6, 0x8c, 0x25, 0xca, 0x11, 0x57, 0x81, 0x91, 0xd8, 0x67, 0x65, 0x75, 0x50, 0x56,
+	0x9f, 0x37, 0x06, 0x62, 0x20, 0x0c, 0x15, 0xae, 0x6f, 0xc5, 0x40, 0x0b, 0xc3, 0x7a, 0x77, 0x4d,
+	0xf7, 0x8c, 0x8b, 0xdd, 0x80, 0xff, 0x53, 0x92, 0x09, 0xee, 0x00, 0x0f, 0xf8, 0xb5, 0xa8, 0x78,
+	0xd8, 0x6d, 0x78, 0x60, 0x3c, 0x48, 0xae, 0x9c, 0x8a, 0x57, 0xf5, 0xeb, 0xd7, 0xad, 0xe0, 0xd7,
+	0xa0, 0xa0, 0x5b, 0x48, 0xa3, 0xed, 0x4c, 0xeb, 0x1d, 0xc0, 0xfd, 0x1f, 0xd4, 0xbe, 0x80, 0x50,
+	0x92, 0x9c, 0x8a, 0x34, 0x56, 0x04, 0x3b, 0x15, 0x0f, 0xf8, 0x47, 0x51, 0xad, 0x40, 0xfa, 0x04,
+	0xdb, 0x0a, 0x9e, 0x26, 0x48, 0x11, 0x46, 0x33, 0x12, 0x73, 0x9a, 0x51, 0x3e, 0xe2, 0x4e, 0xd5,
+	0x03, 0xfe, 0x61, 0xe7, 0x7e, 0xb6, 0x68, 0x5a, 0x9f, 0x8b, 0xe6, 0xdd, 0x80, 0xea, 0xe1, 0x28,
+	0x09, 0xb0, 0xe0, 0xe1, 0xce, 0xdf, 0x8c, 0x6f, 0xaf, 0xf0, 0x10, 0xd1, 0x2c, 0xdc, 0x22, 0xa9,
+	0x9e, 0x4a, 0xa2, 0x82, 0x3e, 0xc9, 0x29, 0x62, 0xf4, 0x15, 0x25, 0x8c, 0x3c, 0x64, 0x3a, 0x3a,
+	0xd9, 0x24, 0x3c, 0x16, 0x01, 0xb6, 0x5f, 0x0a, 0xd5, 0x63, 0x16, 0x4b, 0xc9, 0x9d, 0x7f, 0xa6,
+	0xd9, 0xf1, 0x06, 0x7f, 0x1a, 0xb3, 0x9e, 0xe4, 0x9d, 0xe7, 0xd9, 0xd2, 0x05, 0xf3, 0xa5, 0x0b,
+	0xbe, 0x96, 0x2e, 0x78, 0x5b, 0xb9, 0xd6, 0x7c, 0xe5, 0x5a, 0x1f, 0x2b, 0xd7, 0x7a, 0x69, 0xff,
+	0xbd, 0xd6, 0x64, 0x77, 0x8d, 0xa6, 0x64, 0xb2, 0x67, 0xe8, 0x9b, 0xef, 0x00, 0x00, 0x00, 0xff,
+	0xff, 0xc0, 0x7d, 0x29, 0xe5, 0xf0, 0x01, 0x00, 0x00,
+}
+
+func (m *LimitParams) 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 *LimitParams) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *LimitParams) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if len(m.Limiters) > 0 {
+		for iNdEx := len(m.Limiters) - 1; iNdEx >= 0; iNdEx-- {
+			{
+				size, err := m.Limiters[iNdEx].MarshalToSizedBuffer(dAtA[:i])
+				if err != nil {
+					return 0, err
+				}
+				i -= size
+				i = encodeVarintLimitParams(dAtA, i, uint64(size))
+			}
+			i--
+			dAtA[i] = 0x12
+		}
+	}
+	if len(m.Denom) > 0 {
+		i -= len(m.Denom)
+		copy(dAtA[i:], m.Denom)
+		i = encodeVarintLimitParams(dAtA, i, uint64(len(m.Denom)))
+		i--
+		dAtA[i] = 0xa
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *Limiter) 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 *Limiter) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *Limiter) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.BaselineTvlPpm != 0 {
+		i = encodeVarintLimitParams(dAtA, i, uint64(m.BaselineTvlPpm))
+		i--
+		dAtA[i] = 0x20
+	}
+	{
+		size := m.BaselineMinimum.Size()
+		i -= size
+		if _, err := m.BaselineMinimum.MarshalTo(dAtA[i:]); err != nil {
+			return 0, err
+		}
+		i = encodeVarintLimitParams(dAtA, i, uint64(size))
+	}
+	i--
+	dAtA[i] = 0x1a
+	if m.PeriodSec != 0 {
+		i = encodeVarintLimitParams(dAtA, i, uint64(m.PeriodSec))
+		i--
+		dAtA[i] = 0x10
+	}
+	return len(dAtA) - i, nil
+}
+
+func encodeVarintLimitParams(dAtA []byte, offset int, v uint64) int {
+	offset -= sovLimitParams(v)
+	base := offset
+	for v >= 1<<7 {
+		dAtA[offset] = uint8(v&0x7f | 0x80)
+		v >>= 7
+		offset++
+	}
+	dAtA[offset] = uint8(v)
+	return base
+}
+func (m *LimitParams) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	l = len(m.Denom)
+	if l > 0 {
+		n += 1 + l + sovLimitParams(uint64(l))
+	}
+	if len(m.Limiters) > 0 {
+		for _, e := range m.Limiters {
+			l = e.Size()
+			n += 1 + l + sovLimitParams(uint64(l))
+		}
+	}
+	return n
+}
+
+func (m *Limiter) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.PeriodSec != 0 {
+		n += 1 + sovLimitParams(uint64(m.PeriodSec))
+	}
+	l = m.BaselineMinimum.Size()
+	n += 1 + l + sovLimitParams(uint64(l))
+	if m.BaselineTvlPpm != 0 {
+		n += 1 + sovLimitParams(uint64(m.BaselineTvlPpm))
+	}
+	return n
+}
+
+func sovLimitParams(x uint64) (n int) {
+	return (math_bits.Len64(x|1) + 6) / 7
+}
+func sozLimitParams(x uint64) (n int) {
+	return sovLimitParams(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+}
+func (m *LimitParams) 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 ErrIntOverflowLimitParams
+			}
+			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: LimitParams: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: LimitParams: 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 ErrIntOverflowLimitParams
+				}
+				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 ErrInvalidLengthLimitParams
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex < 0 {
+				return ErrInvalidLengthLimitParams
+			}
+			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 Limiters", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowLimitParams
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthLimitParams
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthLimitParams
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Limiters = append(m.Limiters, &Limiter{})
+			if err := m.Limiters[len(m.Limiters)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipLimitParams(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if (skippy < 0) || (iNdEx+skippy) < 0 {
+				return ErrInvalidLengthLimitParams
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *Limiter) 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 ErrIntOverflowLimitParams
+			}
+			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: Limiter: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: Limiter: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 2:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field PeriodSec", wireType)
+			}
+			m.PeriodSec = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowLimitParams
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.PeriodSec |= uint32(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		case 3:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field BaselineMinimum", wireType)
+			}
+			var byteLen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowLimitParams
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				byteLen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if byteLen < 0 {
+				return ErrInvalidLengthLimitParams
+			}
+			postIndex := iNdEx + byteLen
+			if postIndex < 0 {
+				return ErrInvalidLengthLimitParams
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if err := m.BaselineMinimum.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 4:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field BaselineTvlPpm", wireType)
+			}
+			m.BaselineTvlPpm = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowLimitParams
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.BaselineTvlPpm |= uint32(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		default:
+			iNdEx = preIndex
+			skippy, err := skipLimitParams(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if (skippy < 0) || (iNdEx+skippy) < 0 {
+				return ErrInvalidLengthLimitParams
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func skipLimitParams(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, ErrIntOverflowLimitParams
+			}
+			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, ErrIntOverflowLimitParams
+				}
+				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, ErrIntOverflowLimitParams
+				}
+				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, ErrInvalidLengthLimitParams
+			}
+			iNdEx += length
+		case 3:
+			depth++
+		case 4:
+			if depth == 0 {
+				return 0, ErrUnexpectedEndOfGroupLimitParams
+			}
+			depth--
+		case 5:
+			iNdEx += 4
+		default:
+			return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
+		}
+		if iNdEx < 0 {
+			return 0, ErrInvalidLengthLimitParams
+		}
+		if depth == 0 {
+			return iNdEx, nil
+		}
+	}
+	return 0, io.ErrUnexpectedEOF
+}
+
+var (
+	ErrInvalidLengthLimitParams        = fmt.Errorf("proto: negative length found during unmarshaling")
+	ErrIntOverflowLimitParams          = fmt.Errorf("proto: integer overflow")
+	ErrUnexpectedEndOfGroupLimitParams = fmt.Errorf("proto: unexpected end of group")
+)
diff --git a/protocol/x/ibcratelimit/types/query.pb.go b/protocol/x/ibcratelimit/types/query.pb.go
new file mode 100644
index 0000000000..a4bfe3ce46
--- /dev/null
+++ b/protocol/x/ibcratelimit/types/query.pb.go
@@ -0,0 +1,1146 @@
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: dydxprotocol/ibcratelimit/query.proto
+
+package types
+
+import (
+	context "context"
+	fmt "fmt"
+	_ "github.com/cosmos/gogoproto/gogoproto"
+	grpc1 "github.com/cosmos/gogoproto/grpc"
+	proto "github.com/cosmos/gogoproto/proto"
+	github_com_dydxprotocol_v4_chain_protocol_dtypes "github.com/dydxprotocol/v4-chain/protocol/dtypes"
+	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
+
+// ListLimitParamsRequest is a request type of the ListLimitParams RPC method.
+type ListLimitParamsRequest struct {
+}
+
+func (m *ListLimitParamsRequest) Reset()         { *m = ListLimitParamsRequest{} }
+func (m *ListLimitParamsRequest) String() string { return proto.CompactTextString(m) }
+func (*ListLimitParamsRequest) ProtoMessage()    {}
+func (*ListLimitParamsRequest) Descriptor() ([]byte, []int) {
+	return fileDescriptor_e49fb82b9f3fb8a9, []int{0}
+}
+func (m *ListLimitParamsRequest) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *ListLimitParamsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_ListLimitParamsRequest.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 *ListLimitParamsRequest) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_ListLimitParamsRequest.Merge(m, src)
+}
+func (m *ListLimitParamsRequest) XXX_Size() int {
+	return m.Size()
+}
+func (m *ListLimitParamsRequest) XXX_DiscardUnknown() {
+	xxx_messageInfo_ListLimitParamsRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_ListLimitParamsRequest proto.InternalMessageInfo
+
+// ListLimitParamsResponse is a response type of the ListLimitParams RPC method.
+type ListLimitParamsResponse struct {
+	LimitParamsList []*LimitParams `protobuf:"bytes,1,rep,name=limit_params_list,json=limitParamsList,proto3" json:"limit_params_list,omitempty"`
+}
+
+func (m *ListLimitParamsResponse) Reset()         { *m = ListLimitParamsResponse{} }
+func (m *ListLimitParamsResponse) String() string { return proto.CompactTextString(m) }
+func (*ListLimitParamsResponse) ProtoMessage()    {}
+func (*ListLimitParamsResponse) Descriptor() ([]byte, []int) {
+	return fileDescriptor_e49fb82b9f3fb8a9, []int{1}
+}
+func (m *ListLimitParamsResponse) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *ListLimitParamsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_ListLimitParamsResponse.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 *ListLimitParamsResponse) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_ListLimitParamsResponse.Merge(m, src)
+}
+func (m *ListLimitParamsResponse) XXX_Size() int {
+	return m.Size()
+}
+func (m *ListLimitParamsResponse) XXX_DiscardUnknown() {
+	xxx_messageInfo_ListLimitParamsResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_ListLimitParamsResponse proto.InternalMessageInfo
+
+func (m *ListLimitParamsResponse) GetLimitParamsList() []*LimitParams {
+	if m != nil {
+		return m.LimitParamsList
+	}
+	return nil
+}
+
+// QueryCapacityByDenomRequest is a request type for the CapacityByDenom RPC method.
+type QueryCapacityByDenomRequest struct {
+	Denom string `protobuf:"bytes,1,opt,name=denom,proto3" json:"denom,omitempty"`
+}
+
+func (m *QueryCapacityByDenomRequest) Reset()         { *m = QueryCapacityByDenomRequest{} }
+func (m *QueryCapacityByDenomRequest) String() string { return proto.CompactTextString(m) }
+func (*QueryCapacityByDenomRequest) ProtoMessage()    {}
+func (*QueryCapacityByDenomRequest) Descriptor() ([]byte, []int) {
+	return fileDescriptor_e49fb82b9f3fb8a9, []int{2}
+}
+func (m *QueryCapacityByDenomRequest) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *QueryCapacityByDenomRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_QueryCapacityByDenomRequest.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 *QueryCapacityByDenomRequest) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_QueryCapacityByDenomRequest.Merge(m, src)
+}
+func (m *QueryCapacityByDenomRequest) XXX_Size() int {
+	return m.Size()
+}
+func (m *QueryCapacityByDenomRequest) XXX_DiscardUnknown() {
+	xxx_messageInfo_QueryCapacityByDenomRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_QueryCapacityByDenomRequest proto.InternalMessageInfo
+
+func (m *QueryCapacityByDenomRequest) GetDenom() string {
+	if m != nil {
+		return m.Denom
+	}
+	return ""
+}
+
+// CapacityResult is a specific rate limit for a denom.
+type CapacityResult struct {
+	PeriodSec uint32                                                           `protobuf:"varint,1,opt,name=period_sec,json=periodSec,proto3" json:"period_sec,omitempty"`
+	Capacity  github_com_dydxprotocol_v4_chain_protocol_dtypes.SerializableInt `protobuf:"bytes,2,opt,name=capacity,proto3,customtype=github.com/dydxprotocol/v4-chain/protocol/dtypes.SerializableInt" json:"capacity"`
+}
+
+func (m *CapacityResult) Reset()         { *m = CapacityResult{} }
+func (m *CapacityResult) String() string { return proto.CompactTextString(m) }
+func (*CapacityResult) ProtoMessage()    {}
+func (*CapacityResult) Descriptor() ([]byte, []int) {
+	return fileDescriptor_e49fb82b9f3fb8a9, []int{3}
+}
+func (m *CapacityResult) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *CapacityResult) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_CapacityResult.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 *CapacityResult) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_CapacityResult.Merge(m, src)
+}
+func (m *CapacityResult) XXX_Size() int {
+	return m.Size()
+}
+func (m *CapacityResult) XXX_DiscardUnknown() {
+	xxx_messageInfo_CapacityResult.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_CapacityResult proto.InternalMessageInfo
+
+func (m *CapacityResult) GetPeriodSec() uint32 {
+	if m != nil {
+		return m.PeriodSec
+	}
+	return 0
+}
+
+// QueryCapacityByDenomResponse is a response type of the CapacityByDenom RPC method.
+type QueryCapacityByDenomResponse struct {
+	Results []*CapacityResult `protobuf:"bytes,1,rep,name=results,proto3" json:"results,omitempty"`
+}
+
+func (m *QueryCapacityByDenomResponse) Reset()         { *m = QueryCapacityByDenomResponse{} }
+func (m *QueryCapacityByDenomResponse) String() string { return proto.CompactTextString(m) }
+func (*QueryCapacityByDenomResponse) ProtoMessage()    {}
+func (*QueryCapacityByDenomResponse) Descriptor() ([]byte, []int) {
+	return fileDescriptor_e49fb82b9f3fb8a9, []int{4}
+}
+func (m *QueryCapacityByDenomResponse) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *QueryCapacityByDenomResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_QueryCapacityByDenomResponse.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 *QueryCapacityByDenomResponse) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_QueryCapacityByDenomResponse.Merge(m, src)
+}
+func (m *QueryCapacityByDenomResponse) XXX_Size() int {
+	return m.Size()
+}
+func (m *QueryCapacityByDenomResponse) XXX_DiscardUnknown() {
+	xxx_messageInfo_QueryCapacityByDenomResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_QueryCapacityByDenomResponse proto.InternalMessageInfo
+
+func (m *QueryCapacityByDenomResponse) GetResults() []*CapacityResult {
+	if m != nil {
+		return m.Results
+	}
+	return nil
+}
+
+func init() {
+	proto.RegisterType((*ListLimitParamsRequest)(nil), "dydxprotocol.ibcratelimit.ListLimitParamsRequest")
+	proto.RegisterType((*ListLimitParamsResponse)(nil), "dydxprotocol.ibcratelimit.ListLimitParamsResponse")
+	proto.RegisterType((*QueryCapacityByDenomRequest)(nil), "dydxprotocol.ibcratelimit.QueryCapacityByDenomRequest")
+	proto.RegisterType((*CapacityResult)(nil), "dydxprotocol.ibcratelimit.CapacityResult")
+	proto.RegisterType((*QueryCapacityByDenomResponse)(nil), "dydxprotocol.ibcratelimit.QueryCapacityByDenomResponse")
+}
+
+func init() {
+	proto.RegisterFile("dydxprotocol/ibcratelimit/query.proto", fileDescriptor_e49fb82b9f3fb8a9)
+}
+
+var fileDescriptor_e49fb82b9f3fb8a9 = []byte{
+	// 426 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x53, 0x4d, 0xab, 0xd3, 0x40,
+	0x14, 0xcd, 0x3c, 0x79, 0xea, 0x1b, 0x3f, 0x8a, 0xc3, 0x43, 0x63, 0xd4, 0xbc, 0x12, 0x50, 0x2a,
+	0x68, 0x82, 0xad, 0xe8, 0x4e, 0xa4, 0x75, 0xa1, 0xd0, 0x85, 0xa6, 0x1b, 0x71, 0x53, 0x26, 0x93,
+	0xa1, 0x1d, 0x48, 0x32, 0x69, 0x66, 0x22, 0x8d, 0x4b, 0x17, 0xae, 0xdd, 0xf8, 0x9f, 0xba, 0xec,
+	0x52, 0x5c, 0x14, 0x69, 0xff, 0x88, 0x64, 0x92, 0xd6, 0xb4, 0xb6, 0xc1, 0x6e, 0x42, 0xee, 0x9c,
+	0x7b, 0xce, 0xdc, 0x73, 0x0f, 0x03, 0x1f, 0xfa, 0x99, 0x3f, 0x8d, 0x13, 0x2e, 0x39, 0xe1, 0x81,
+	0xc3, 0x3c, 0x92, 0x60, 0x49, 0x03, 0x16, 0x32, 0xe9, 0x4c, 0x52, 0x9a, 0x64, 0xb6, 0xc2, 0xd0,
+	0xdd, 0x6a, 0x9b, 0x5d, 0x6d, 0x33, 0xce, 0x47, 0x7c, 0xc4, 0x15, 0xe4, 0xe4, 0x7f, 0x05, 0xc1,
+	0x78, 0x72, 0x58, 0x57, 0x7d, 0x87, 0x31, 0x4e, 0x70, 0x28, 0x8a, 0x6e, 0x4b, 0x87, 0xb7, 0xfb,
+	0x4c, 0xc8, 0x7e, 0x8e, 0xbc, 0x57, 0x80, 0x4b, 0x27, 0x29, 0x15, 0xd2, 0x0a, 0xe1, 0x9d, 0x7f,
+	0x10, 0x11, 0xf3, 0x48, 0x50, 0xe4, 0xc2, 0x5b, 0x55, 0xa9, 0x61, 0xc0, 0x84, 0xd4, 0x41, 0xf3,
+	0x52, 0xeb, 0x5a, 0xfb, 0x91, 0x7d, 0x70, 0x5e, 0xbb, 0x2a, 0xd5, 0x08, 0xfe, 0x16, 0xf9, 0x35,
+	0x56, 0x07, 0xde, 0xfb, 0x90, 0xdb, 0xee, 0xe1, 0x18, 0x13, 0x26, 0xb3, 0x6e, 0xf6, 0x86, 0x46,
+	0x3c, 0x2c, 0xa7, 0x41, 0xe7, 0xf0, 0xd4, 0xcf, 0x6b, 0x1d, 0x34, 0x41, 0xeb, 0xcc, 0x2d, 0x0a,
+	0xeb, 0x07, 0x80, 0x37, 0xd7, 0x04, 0x97, 0x8a, 0x34, 0x90, 0xe8, 0x01, 0x84, 0x31, 0x4d, 0x18,
+	0xf7, 0x87, 0x82, 0x12, 0xd5, 0x7d, 0xc3, 0x3d, 0x2b, 0x4e, 0x06, 0x94, 0x20, 0x1f, 0x5e, 0x25,
+	0x25, 0x41, 0x3f, 0x69, 0x82, 0xd6, 0xf5, 0xee, 0xdb, 0xd9, 0xe2, 0x42, 0xfb, 0xb5, 0xb8, 0x78,
+	0x3d, 0x62, 0x72, 0x9c, 0x7a, 0x36, 0xe1, 0xa1, 0xb3, 0xb5, 0xc2, 0xcf, 0xcf, 0x9f, 0x92, 0x31,
+	0x66, 0x91, 0xb3, 0x39, 0xf1, 0x65, 0x16, 0x53, 0x61, 0x0f, 0x68, 0xc2, 0x70, 0xc0, 0xbe, 0x60,
+	0x2f, 0xa0, 0xef, 0x22, 0xe9, 0x6e, 0x94, 0x2d, 0x02, 0xef, 0xef, 0x37, 0x53, 0x2e, 0xb0, 0x07,
+	0xaf, 0x24, 0x6a, 0x5c, 0x51, 0xae, 0xed, 0x71, 0xcd, 0xda, 0xb6, 0x0d, 0xba, 0x6b, 0x66, 0xfb,
+	0xdb, 0x09, 0x3c, 0x55, 0xb7, 0xa0, 0x29, 0x6c, 0xec, 0x44, 0x85, 0x9e, 0xd5, 0xe6, 0xb0, 0x2f,
+	0x70, 0xa3, 0x7d, 0x0c, 0xa5, 0x34, 0xf2, 0x15, 0xc0, 0xc6, 0x8e, 0x49, 0xf4, 0xa2, 0x46, 0xa7,
+	0x26, 0x62, 0xe3, 0xe5, 0xd1, 0xbc, 0x62, 0x88, 0xee, 0xc7, 0xd9, 0xd2, 0x04, 0xf3, 0xa5, 0x09,
+	0x7e, 0x2f, 0x4d, 0xf0, 0x7d, 0x65, 0x6a, 0xf3, 0x95, 0xa9, 0xfd, 0x5c, 0x99, 0xda, 0xa7, 0x57,
+	0xff, 0x9f, 0xe9, 0x74, 0xfb, 0xa9, 0xa8, 0x84, 0xbd, 0xcb, 0x0a, 0xee, 0xfc, 0x09, 0x00, 0x00,
+	0xff, 0xff, 0x7b, 0x03, 0x31, 0xdf, 0xac, 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 {
+	// List all limit params.
+	ListLimitParams(ctx context.Context, in *ListLimitParamsRequest, opts ...grpc.CallOption) (*ListLimitParamsResponse, error)
+	// Query capacity by denom.
+	CapacityByDenom(ctx context.Context, in *QueryCapacityByDenomRequest, opts ...grpc.CallOption) (*QueryCapacityByDenomResponse, error)
+}
+
+type queryClient struct {
+	cc grpc1.ClientConn
+}
+
+func NewQueryClient(cc grpc1.ClientConn) QueryClient {
+	return &queryClient{cc}
+}
+
+func (c *queryClient) ListLimitParams(ctx context.Context, in *ListLimitParamsRequest, opts ...grpc.CallOption) (*ListLimitParamsResponse, error) {
+	out := new(ListLimitParamsResponse)
+	err := c.cc.Invoke(ctx, "/dydxprotocol.ibcratelimit.Query/ListLimitParams", in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (c *queryClient) CapacityByDenom(ctx context.Context, in *QueryCapacityByDenomRequest, opts ...grpc.CallOption) (*QueryCapacityByDenomResponse, error) {
+	out := new(QueryCapacityByDenomResponse)
+	err := c.cc.Invoke(ctx, "/dydxprotocol.ibcratelimit.Query/CapacityByDenom", in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+// QueryServer is the server API for Query service.
+type QueryServer interface {
+	// List all limit params.
+	ListLimitParams(context.Context, *ListLimitParamsRequest) (*ListLimitParamsResponse, error)
+	// Query capacity by denom.
+	CapacityByDenom(context.Context, *QueryCapacityByDenomRequest) (*QueryCapacityByDenomResponse, error)
+}
+
+// UnimplementedQueryServer can be embedded to have forward compatible implementations.
+type UnimplementedQueryServer struct {
+}
+
+func (*UnimplementedQueryServer) ListLimitParams(ctx context.Context, req *ListLimitParamsRequest) (*ListLimitParamsResponse, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method ListLimitParams not implemented")
+}
+func (*UnimplementedQueryServer) CapacityByDenom(ctx context.Context, req *QueryCapacityByDenomRequest) (*QueryCapacityByDenomResponse, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method CapacityByDenom not implemented")
+}
+
+func RegisterQueryServer(s grpc1.Server, srv QueryServer) {
+	s.RegisterService(&_Query_serviceDesc, srv)
+}
+
+func _Query_ListLimitParams_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(ListLimitParamsRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(QueryServer).ListLimitParams(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/dydxprotocol.ibcratelimit.Query/ListLimitParams",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(QueryServer).ListLimitParams(ctx, req.(*ListLimitParamsRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+func _Query_CapacityByDenom_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(QueryCapacityByDenomRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(QueryServer).CapacityByDenom(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/dydxprotocol.ibcratelimit.Query/CapacityByDenom",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(QueryServer).CapacityByDenom(ctx, req.(*QueryCapacityByDenomRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+var _Query_serviceDesc = grpc.ServiceDesc{
+	ServiceName: "dydxprotocol.ibcratelimit.Query",
+	HandlerType: (*QueryServer)(nil),
+	Methods: []grpc.MethodDesc{
+		{
+			MethodName: "ListLimitParams",
+			Handler:    _Query_ListLimitParams_Handler,
+		},
+		{
+			MethodName: "CapacityByDenom",
+			Handler:    _Query_CapacityByDenom_Handler,
+		},
+	},
+	Streams:  []grpc.StreamDesc{},
+	Metadata: "dydxprotocol/ibcratelimit/query.proto",
+}
+
+func (m *ListLimitParamsRequest) 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 *ListLimitParamsRequest) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *ListLimitParamsRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	return len(dAtA) - i, nil
+}
+
+func (m *ListLimitParamsResponse) 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 *ListLimitParamsResponse) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *ListLimitParamsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if len(m.LimitParamsList) > 0 {
+		for iNdEx := len(m.LimitParamsList) - 1; iNdEx >= 0; iNdEx-- {
+			{
+				size, err := m.LimitParamsList[iNdEx].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 *QueryCapacityByDenomRequest) 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 *QueryCapacityByDenomRequest) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *QueryCapacityByDenomRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if len(m.Denom) > 0 {
+		i -= len(m.Denom)
+		copy(dAtA[i:], m.Denom)
+		i = encodeVarintQuery(dAtA, i, uint64(len(m.Denom)))
+		i--
+		dAtA[i] = 0xa
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *CapacityResult) 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 *CapacityResult) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *CapacityResult) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	{
+		size := m.Capacity.Size()
+		i -= size
+		if _, err := m.Capacity.MarshalTo(dAtA[i:]); err != nil {
+			return 0, err
+		}
+		i = encodeVarintQuery(dAtA, i, uint64(size))
+	}
+	i--
+	dAtA[i] = 0x12
+	if m.PeriodSec != 0 {
+		i = encodeVarintQuery(dAtA, i, uint64(m.PeriodSec))
+		i--
+		dAtA[i] = 0x8
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *QueryCapacityByDenomResponse) 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 *QueryCapacityByDenomResponse) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *QueryCapacityByDenomResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if len(m.Results) > 0 {
+		for iNdEx := len(m.Results) - 1; iNdEx >= 0; iNdEx-- {
+			{
+				size, err := m.Results[iNdEx].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 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 *ListLimitParamsRequest) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	return n
+}
+
+func (m *ListLimitParamsResponse) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if len(m.LimitParamsList) > 0 {
+		for _, e := range m.LimitParamsList {
+			l = e.Size()
+			n += 1 + l + sovQuery(uint64(l))
+		}
+	}
+	return n
+}
+
+func (m *QueryCapacityByDenomRequest) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	l = len(m.Denom)
+	if l > 0 {
+		n += 1 + l + sovQuery(uint64(l))
+	}
+	return n
+}
+
+func (m *CapacityResult) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.PeriodSec != 0 {
+		n += 1 + sovQuery(uint64(m.PeriodSec))
+	}
+	l = m.Capacity.Size()
+	n += 1 + l + sovQuery(uint64(l))
+	return n
+}
+
+func (m *QueryCapacityByDenomResponse) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if len(m.Results) > 0 {
+		for _, e := range m.Results {
+			l = e.Size()
+			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 *ListLimitParamsRequest) 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: ListLimitParamsRequest: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: ListLimitParamsRequest: 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 *ListLimitParamsResponse) 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: ListLimitParamsResponse: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: ListLimitParamsResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field LimitParamsList", 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
+			}
+			m.LimitParamsList = append(m.LimitParamsList, &LimitParams{})
+			if err := m.LimitParamsList[len(m.LimitParamsList)-1].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 *QueryCapacityByDenomRequest) 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: QueryCapacityByDenomRequest: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: QueryCapacityByDenomRequest: 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 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.Denom = 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 (m *CapacityResult) 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: CapacityResult: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: CapacityResult: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field PeriodSec", wireType)
+			}
+			m.PeriodSec = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowQuery
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.PeriodSec |= uint32(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Capacity", wireType)
+			}
+			var byteLen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowQuery
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				byteLen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if byteLen < 0 {
+				return ErrInvalidLengthQuery
+			}
+			postIndex := iNdEx + byteLen
+			if postIndex < 0 {
+				return ErrInvalidLengthQuery
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if err := m.Capacity.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 *QueryCapacityByDenomResponse) 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: QueryCapacityByDenomResponse: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: QueryCapacityByDenomResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Results", 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
+			}
+			m.Results = append(m.Results, &CapacityResult{})
+			if err := m.Results[len(m.Results)-1].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 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/protocol/x/ibcratelimit/types/tx.pb.go b/protocol/x/ibcratelimit/types/tx.pb.go
new file mode 100644
index 0000000000..ca123aa4d0
--- /dev/null
+++ b/protocol/x/ibcratelimit/types/tx.pb.go
@@ -0,0 +1,978 @@
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: dydxprotocol/ibcratelimit/tx.proto
+
+package types
+
+import (
+	context "context"
+	fmt "fmt"
+	_ "github.com/cosmos/cosmos-sdk/types/msgservice"
+	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
+
+// MsgSetLimitParams is the Msg/SetLimitParams request type.
+type MsgSetLimitParams struct {
+	Authority string `protobuf:"bytes,1,opt,name=authority,proto3" json:"authority,omitempty"`
+	// Defines the parameters to set. All parameters must be supplied.
+	LimitParams *LimitParams `protobuf:"bytes,2,opt,name=limit_params,json=limitParams,proto3" json:"limit_params,omitempty"`
+}
+
+func (m *MsgSetLimitParams) Reset()         { *m = MsgSetLimitParams{} }
+func (m *MsgSetLimitParams) String() string { return proto.CompactTextString(m) }
+func (*MsgSetLimitParams) ProtoMessage()    {}
+func (*MsgSetLimitParams) Descriptor() ([]byte, []int) {
+	return fileDescriptor_a419c53765e30c3b, []int{0}
+}
+func (m *MsgSetLimitParams) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *MsgSetLimitParams) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_MsgSetLimitParams.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 *MsgSetLimitParams) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_MsgSetLimitParams.Merge(m, src)
+}
+func (m *MsgSetLimitParams) XXX_Size() int {
+	return m.Size()
+}
+func (m *MsgSetLimitParams) XXX_DiscardUnknown() {
+	xxx_messageInfo_MsgSetLimitParams.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_MsgSetLimitParams proto.InternalMessageInfo
+
+func (m *MsgSetLimitParams) GetAuthority() string {
+	if m != nil {
+		return m.Authority
+	}
+	return ""
+}
+
+func (m *MsgSetLimitParams) GetLimitParams() *LimitParams {
+	if m != nil {
+		return m.LimitParams
+	}
+	return nil
+}
+
+// MsgSetLimitParamsResponse is the Msg/SetLimitParams response type.
+type MsgSetLimitParamsResponse struct {
+}
+
+func (m *MsgSetLimitParamsResponse) Reset()         { *m = MsgSetLimitParamsResponse{} }
+func (m *MsgSetLimitParamsResponse) String() string { return proto.CompactTextString(m) }
+func (*MsgSetLimitParamsResponse) ProtoMessage()    {}
+func (*MsgSetLimitParamsResponse) Descriptor() ([]byte, []int) {
+	return fileDescriptor_a419c53765e30c3b, []int{1}
+}
+func (m *MsgSetLimitParamsResponse) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *MsgSetLimitParamsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_MsgSetLimitParamsResponse.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 *MsgSetLimitParamsResponse) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_MsgSetLimitParamsResponse.Merge(m, src)
+}
+func (m *MsgSetLimitParamsResponse) XXX_Size() int {
+	return m.Size()
+}
+func (m *MsgSetLimitParamsResponse) XXX_DiscardUnknown() {
+	xxx_messageInfo_MsgSetLimitParamsResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_MsgSetLimitParamsResponse proto.InternalMessageInfo
+
+// MsgDeleteLimitParams is the Msg/SetLimitParams request type.
+type MsgDeleteLimitParams struct {
+	Authority string `protobuf:"bytes,1,opt,name=authority,proto3" json:"authority,omitempty"`
+	// The denom for which the `LimitParams` should be deleted.
+	Denom string `protobuf:"bytes,2,opt,name=denom,proto3" json:"denom,omitempty"`
+}
+
+func (m *MsgDeleteLimitParams) Reset()         { *m = MsgDeleteLimitParams{} }
+func (m *MsgDeleteLimitParams) String() string { return proto.CompactTextString(m) }
+func (*MsgDeleteLimitParams) ProtoMessage()    {}
+func (*MsgDeleteLimitParams) Descriptor() ([]byte, []int) {
+	return fileDescriptor_a419c53765e30c3b, []int{2}
+}
+func (m *MsgDeleteLimitParams) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *MsgDeleteLimitParams) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_MsgDeleteLimitParams.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 *MsgDeleteLimitParams) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_MsgDeleteLimitParams.Merge(m, src)
+}
+func (m *MsgDeleteLimitParams) XXX_Size() int {
+	return m.Size()
+}
+func (m *MsgDeleteLimitParams) XXX_DiscardUnknown() {
+	xxx_messageInfo_MsgDeleteLimitParams.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_MsgDeleteLimitParams proto.InternalMessageInfo
+
+func (m *MsgDeleteLimitParams) GetAuthority() string {
+	if m != nil {
+		return m.Authority
+	}
+	return ""
+}
+
+func (m *MsgDeleteLimitParams) GetDenom() string {
+	if m != nil {
+		return m.Denom
+	}
+	return ""
+}
+
+// MsgDeleteLimitParamsResponse is the Msg/DeleteLimitParams response type.
+type MsgDeleteLimitParamsResponse struct {
+}
+
+func (m *MsgDeleteLimitParamsResponse) Reset()         { *m = MsgDeleteLimitParamsResponse{} }
+func (m *MsgDeleteLimitParamsResponse) String() string { return proto.CompactTextString(m) }
+func (*MsgDeleteLimitParamsResponse) ProtoMessage()    {}
+func (*MsgDeleteLimitParamsResponse) Descriptor() ([]byte, []int) {
+	return fileDescriptor_a419c53765e30c3b, []int{3}
+}
+func (m *MsgDeleteLimitParamsResponse) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *MsgDeleteLimitParamsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_MsgDeleteLimitParamsResponse.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 *MsgDeleteLimitParamsResponse) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_MsgDeleteLimitParamsResponse.Merge(m, src)
+}
+func (m *MsgDeleteLimitParamsResponse) XXX_Size() int {
+	return m.Size()
+}
+func (m *MsgDeleteLimitParamsResponse) XXX_DiscardUnknown() {
+	xxx_messageInfo_MsgDeleteLimitParamsResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_MsgDeleteLimitParamsResponse proto.InternalMessageInfo
+
+func init() {
+	proto.RegisterType((*MsgSetLimitParams)(nil), "dydxprotocol.ibcratelimit.MsgSetLimitParams")
+	proto.RegisterType((*MsgSetLimitParamsResponse)(nil), "dydxprotocol.ibcratelimit.MsgSetLimitParamsResponse")
+	proto.RegisterType((*MsgDeleteLimitParams)(nil), "dydxprotocol.ibcratelimit.MsgDeleteLimitParams")
+	proto.RegisterType((*MsgDeleteLimitParamsResponse)(nil), "dydxprotocol.ibcratelimit.MsgDeleteLimitParamsResponse")
+}
+
+func init() {
+	proto.RegisterFile("dydxprotocol/ibcratelimit/tx.proto", fileDescriptor_a419c53765e30c3b)
+}
+
+var fileDescriptor_a419c53765e30c3b = []byte{
+	// 336 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0x4a, 0xa9, 0x4c, 0xa9,
+	0x28, 0x28, 0xca, 0x2f, 0xc9, 0x4f, 0xce, 0xcf, 0xd1, 0xcf, 0x4c, 0x4a, 0x2e, 0x4a, 0x2c, 0x49,
+	0xcd, 0xc9, 0xcc, 0xcd, 0x2c, 0xd1, 0x2f, 0xa9, 0xd0, 0x03, 0x4b, 0x08, 0x49, 0x22, 0xab, 0xd1,
+	0x43, 0x56, 0x23, 0x25, 0x9e, 0x9c, 0x5f, 0x9c, 0x9b, 0x5f, 0xac, 0x9f, 0x5b, 0x9c, 0xae, 0x5f,
+	0x66, 0x08, 0xa2, 0x20, 0x7a, 0xa4, 0x74, 0x70, 0x9b, 0x0b, 0x26, 0xe3, 0x0b, 0x12, 0x8b, 0x12,
+	0x73, 0x8b, 0x21, 0xaa, 0x95, 0x7a, 0x18, 0xb9, 0x04, 0x7d, 0x8b, 0xd3, 0x83, 0x53, 0x4b, 0x7c,
+	0x40, 0x92, 0x01, 0x60, 0x39, 0x21, 0x19, 0x2e, 0xce, 0xc4, 0xd2, 0x92, 0x8c, 0xfc, 0xa2, 0xcc,
+	0x92, 0x4a, 0x09, 0x46, 0x05, 0x46, 0x0d, 0xce, 0x20, 0x84, 0x80, 0x90, 0x27, 0x17, 0x0f, 0xb2,
+	0x49, 0x12, 0x4c, 0x0a, 0x8c, 0x1a, 0xdc, 0x46, 0x6a, 0x7a, 0x38, 0x1d, 0xab, 0x87, 0x64, 0x76,
+	0x10, 0x77, 0x0e, 0x82, 0x63, 0xc5, 0xd7, 0xf4, 0x7c, 0x83, 0x16, 0xc2, 0x68, 0x25, 0x69, 0x2e,
+	0x49, 0x0c, 0xd7, 0x04, 0xa5, 0x16, 0x17, 0xe4, 0xe7, 0x15, 0xa7, 0x2a, 0x45, 0x71, 0x89, 0xf8,
+	0x16, 0xa7, 0xbb, 0xa4, 0xe6, 0xa4, 0x96, 0xa4, 0x12, 0xef, 0x5a, 0x11, 0x2e, 0xd6, 0x94, 0xd4,
+	0xbc, 0xfc, 0x5c, 0xb0, 0x33, 0x39, 0x83, 0x20, 0x1c, 0x0c, 0x8b, 0xe5, 0xb8, 0x64, 0xb0, 0x99,
+	0x0d, 0xb3, 0xdb, 0xe8, 0x17, 0x23, 0x17, 0xb3, 0x6f, 0x71, 0xba, 0x50, 0x09, 0x17, 0x1f, 0x5a,
+	0x58, 0xe9, 0xe0, 0xf1, 0x37, 0x86, 0x5f, 0xa4, 0x4c, 0x48, 0x51, 0x0d, 0xb3, 0x5d, 0xa8, 0x96,
+	0x4b, 0x10, 0xd3, 0xdb, 0xfa, 0xf8, 0x8d, 0xc2, 0xd0, 0x20, 0x65, 0x4e, 0xa2, 0x06, 0x98, 0xf5,
+	0x4e, 0x11, 0x27, 0x1e, 0xc9, 0x31, 0x5e, 0x78, 0x24, 0xc7, 0xf8, 0xe0, 0x91, 0x1c, 0xe3, 0x84,
+	0xc7, 0x72, 0x0c, 0x17, 0x1e, 0xcb, 0x31, 0xdc, 0x78, 0x2c, 0xc7, 0x10, 0x65, 0x97, 0x9e, 0x59,
+	0x92, 0x51, 0x9a, 0xa4, 0x97, 0x9c, 0x9f, 0xab, 0x8f, 0x92, 0xee, 0xca, 0x4c, 0x74, 0x93, 0x33,
+	0x12, 0x33, 0xf3, 0xf4, 0xe1, 0x22, 0x15, 0x68, 0x69, 0xbc, 0xb2, 0x20, 0xb5, 0x38, 0x89, 0x0d,
+	0x2c, 0x6d, 0x0c, 0x08, 0x00, 0x00, 0xff, 0xff, 0x57, 0x42, 0x04, 0xf6, 0x0d, 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
+
+// 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 {
+	// SetLimitParams sets a `LimitParams` object in state.
+	SetLimitParams(ctx context.Context, in *MsgSetLimitParams, opts ...grpc.CallOption) (*MsgSetLimitParamsResponse, error)
+	// DeleteLimitParams removes a `LimitParams` object in state.
+	DeleteLimitParams(ctx context.Context, in *MsgDeleteLimitParams, opts ...grpc.CallOption) (*MsgDeleteLimitParamsResponse, error)
+}
+
+type msgClient struct {
+	cc grpc1.ClientConn
+}
+
+func NewMsgClient(cc grpc1.ClientConn) MsgClient {
+	return &msgClient{cc}
+}
+
+func (c *msgClient) SetLimitParams(ctx context.Context, in *MsgSetLimitParams, opts ...grpc.CallOption) (*MsgSetLimitParamsResponse, error) {
+	out := new(MsgSetLimitParamsResponse)
+	err := c.cc.Invoke(ctx, "/dydxprotocol.ibcratelimit.Msg/SetLimitParams", in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (c *msgClient) DeleteLimitParams(ctx context.Context, in *MsgDeleteLimitParams, opts ...grpc.CallOption) (*MsgDeleteLimitParamsResponse, error) {
+	out := new(MsgDeleteLimitParamsResponse)
+	err := c.cc.Invoke(ctx, "/dydxprotocol.ibcratelimit.Msg/DeleteLimitParams", in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+// MsgServer is the server API for Msg service.
+type MsgServer interface {
+	// SetLimitParams sets a `LimitParams` object in state.
+	SetLimitParams(context.Context, *MsgSetLimitParams) (*MsgSetLimitParamsResponse, error)
+	// DeleteLimitParams removes a `LimitParams` object in state.
+	DeleteLimitParams(context.Context, *MsgDeleteLimitParams) (*MsgDeleteLimitParamsResponse, error)
+}
+
+// UnimplementedMsgServer can be embedded to have forward compatible implementations.
+type UnimplementedMsgServer struct {
+}
+
+func (*UnimplementedMsgServer) SetLimitParams(ctx context.Context, req *MsgSetLimitParams) (*MsgSetLimitParamsResponse, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method SetLimitParams not implemented")
+}
+func (*UnimplementedMsgServer) DeleteLimitParams(ctx context.Context, req *MsgDeleteLimitParams) (*MsgDeleteLimitParamsResponse, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method DeleteLimitParams not implemented")
+}
+
+func RegisterMsgServer(s grpc1.Server, srv MsgServer) {
+	s.RegisterService(&_Msg_serviceDesc, srv)
+}
+
+func _Msg_SetLimitParams_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(MsgSetLimitParams)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(MsgServer).SetLimitParams(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/dydxprotocol.ibcratelimit.Msg/SetLimitParams",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(MsgServer).SetLimitParams(ctx, req.(*MsgSetLimitParams))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+func _Msg_DeleteLimitParams_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(MsgDeleteLimitParams)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(MsgServer).DeleteLimitParams(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/dydxprotocol.ibcratelimit.Msg/DeleteLimitParams",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(MsgServer).DeleteLimitParams(ctx, req.(*MsgDeleteLimitParams))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+var _Msg_serviceDesc = grpc.ServiceDesc{
+	ServiceName: "dydxprotocol.ibcratelimit.Msg",
+	HandlerType: (*MsgServer)(nil),
+	Methods: []grpc.MethodDesc{
+		{
+			MethodName: "SetLimitParams",
+			Handler:    _Msg_SetLimitParams_Handler,
+		},
+		{
+			MethodName: "DeleteLimitParams",
+			Handler:    _Msg_DeleteLimitParams_Handler,
+		},
+	},
+	Streams:  []grpc.StreamDesc{},
+	Metadata: "dydxprotocol/ibcratelimit/tx.proto",
+}
+
+func (m *MsgSetLimitParams) 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 *MsgSetLimitParams) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *MsgSetLimitParams) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.LimitParams != nil {
+		{
+			size, err := m.LimitParams.MarshalToSizedBuffer(dAtA[:i])
+			if err != nil {
+				return 0, err
+			}
+			i -= size
+			i = encodeVarintTx(dAtA, i, uint64(size))
+		}
+		i--
+		dAtA[i] = 0x12
+	}
+	if len(m.Authority) > 0 {
+		i -= len(m.Authority)
+		copy(dAtA[i:], m.Authority)
+		i = encodeVarintTx(dAtA, i, uint64(len(m.Authority)))
+		i--
+		dAtA[i] = 0xa
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *MsgSetLimitParamsResponse) 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 *MsgSetLimitParamsResponse) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *MsgSetLimitParamsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	return len(dAtA) - i, nil
+}
+
+func (m *MsgDeleteLimitParams) 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 *MsgDeleteLimitParams) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *MsgDeleteLimitParams) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if len(m.Denom) > 0 {
+		i -= len(m.Denom)
+		copy(dAtA[i:], m.Denom)
+		i = encodeVarintTx(dAtA, i, uint64(len(m.Denom)))
+		i--
+		dAtA[i] = 0x12
+	}
+	if len(m.Authority) > 0 {
+		i -= len(m.Authority)
+		copy(dAtA[i:], m.Authority)
+		i = encodeVarintTx(dAtA, i, uint64(len(m.Authority)))
+		i--
+		dAtA[i] = 0xa
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *MsgDeleteLimitParamsResponse) 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 *MsgDeleteLimitParamsResponse) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *MsgDeleteLimitParamsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	return len(dAtA) - i, nil
+}
+
+func encodeVarintTx(dAtA []byte, offset int, v uint64) int {
+	offset -= sovTx(v)
+	base := offset
+	for v >= 1<<7 {
+		dAtA[offset] = uint8(v&0x7f | 0x80)
+		v >>= 7
+		offset++
+	}
+	dAtA[offset] = uint8(v)
+	return base
+}
+func (m *MsgSetLimitParams) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	l = len(m.Authority)
+	if l > 0 {
+		n += 1 + l + sovTx(uint64(l))
+	}
+	if m.LimitParams != nil {
+		l = m.LimitParams.Size()
+		n += 1 + l + sovTx(uint64(l))
+	}
+	return n
+}
+
+func (m *MsgSetLimitParamsResponse) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	return n
+}
+
+func (m *MsgDeleteLimitParams) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	l = len(m.Authority)
+	if l > 0 {
+		n += 1 + l + sovTx(uint64(l))
+	}
+	l = len(m.Denom)
+	if l > 0 {
+		n += 1 + l + sovTx(uint64(l))
+	}
+	return n
+}
+
+func (m *MsgDeleteLimitParamsResponse) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	return n
+}
+
+func sovTx(x uint64) (n int) {
+	return (math_bits.Len64(x|1) + 6) / 7
+}
+func sozTx(x uint64) (n int) {
+	return sovTx(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+}
+func (m *MsgSetLimitParams) 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 ErrIntOverflowTx
+			}
+			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: MsgSetLimitParams: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: MsgSetLimitParams: 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 ErrIntOverflowTx
+				}
+				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 ErrInvalidLengthTx
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex < 0 {
+				return ErrInvalidLengthTx
+			}
+			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 LimitParams", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTx
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthTx
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthTx
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if m.LimitParams == nil {
+				m.LimitParams = &LimitParams{}
+			}
+			if err := m.LimitParams.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipTx(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if (skippy < 0) || (iNdEx+skippy) < 0 {
+				return ErrInvalidLengthTx
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *MsgSetLimitParamsResponse) 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 ErrIntOverflowTx
+			}
+			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: MsgSetLimitParamsResponse: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: MsgSetLimitParamsResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		default:
+			iNdEx = preIndex
+			skippy, err := skipTx(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if (skippy < 0) || (iNdEx+skippy) < 0 {
+				return ErrInvalidLengthTx
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *MsgDeleteLimitParams) 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 ErrIntOverflowTx
+			}
+			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: MsgDeleteLimitParams: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: MsgDeleteLimitParams: 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 ErrIntOverflowTx
+				}
+				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 ErrInvalidLengthTx
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex < 0 {
+				return ErrInvalidLengthTx
+			}
+			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 Denom", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTx
+				}
+				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 ErrInvalidLengthTx
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex < 0 {
+				return ErrInvalidLengthTx
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Denom = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipTx(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if (skippy < 0) || (iNdEx+skippy) < 0 {
+				return ErrInvalidLengthTx
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *MsgDeleteLimitParamsResponse) 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 ErrIntOverflowTx
+			}
+			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: MsgDeleteLimitParamsResponse: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: MsgDeleteLimitParamsResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		default:
+			iNdEx = preIndex
+			skippy, err := skipTx(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if (skippy < 0) || (iNdEx+skippy) < 0 {
+				return ErrInvalidLengthTx
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func skipTx(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, ErrIntOverflowTx
+			}
+			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, ErrIntOverflowTx
+				}
+				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, ErrIntOverflowTx
+				}
+				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, ErrInvalidLengthTx
+			}
+			iNdEx += length
+		case 3:
+			depth++
+		case 4:
+			if depth == 0 {
+				return 0, ErrUnexpectedEndOfGroupTx
+			}
+			depth--
+		case 5:
+			iNdEx += 4
+		default:
+			return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
+		}
+		if iNdEx < 0 {
+			return 0, ErrInvalidLengthTx
+		}
+		if depth == 0 {
+			return iNdEx, nil
+		}
+	}
+	return 0, io.ErrUnexpectedEOF
+}
+
+var (
+	ErrInvalidLengthTx        = fmt.Errorf("proto: negative length found during unmarshaling")
+	ErrIntOverflowTx          = fmt.Errorf("proto: integer overflow")
+	ErrUnexpectedEndOfGroupTx = fmt.Errorf("proto: unexpected end of group")
+)