From e0ea646d1f42c065d9da5613eba3215a0cc7706c Mon Sep 17 00:00:00 2001
From: Lucas Bertrand <lucas.bertrand.22@gmail.com>
Date: Thu, 18 Apr 2024 20:14:08 +0200
Subject: [PATCH] feat(`crosschain`): add rate limiter flags singleton state
 variable (#2046)

* initialize type

* keeper and genesis

* new state variable

* add query

* make generate

* changelog

* fix lint

* fix unit test

* address comments
---
 changelog.md                                  |   1 +
 .../zetacored/zetacored_query_crosschain.md   |   1 +
 ...uery_crosschain_update_rate_limit_flags.md |  33 +
 docs/openapi/openapi.swagger.yaml             |  47 ++
 docs/spec/crosschain/messages.md              |  12 +
 proto/crosschain/genesis.proto                |   2 +
 proto/crosschain/query.proto                  |  12 +
 proto/crosschain/rate_limiter_flags.proto     |  30 +
 proto/crosschain/tx.proto                     |  10 +
 testutil/sample/crosschain.go                 |  34 +
 typescript/crosschain/genesis_pb.d.ts         |   6 +
 typescript/crosschain/index.d.ts              |   1 +
 typescript/crosschain/query_pb.d.ts           |  44 ++
 .../crosschain/rate_limiter_flags_pb.d.ts     |  82 +++
 typescript/crosschain/tx_pb.d.ts              |  49 ++
 x/crosschain/client/cli/query.go              |   8 +-
 .../client/cli/query_rate_limiter_flags.go    |  33 +
 x/crosschain/genesis.go                       |   7 +
 x/crosschain/genesis_test.go                  |   1 +
 .../keeper/grpc_query_rate_limiter_flags.go   |  26 +
 .../grpc_query_rate_limiter_flags_test.go     |  46 ++
 .../msg_server_update_rate_limiter_flags.go   |  25 +
 ...g_server_update_rate_limiter_flags_test.go |  57 ++
 x/crosschain/keeper/rate_limiter_flags.go     |  27 +
 .../keeper/rate_limiter_flags_test.go         |  24 +
 x/crosschain/types/codec.go                   |   2 +
 x/crosschain/types/errors.go                  |   3 +-
 x/crosschain/types/genesis.go                 |  16 +-
 x/crosschain/types/genesis.pb.go              | 119 ++-
 x/crosschain/types/genesis_test.go            |  16 +
 x/crosschain/types/keys.go                    |   2 +
 .../message_update_rate_limiter_flags.go      |  49 ++
 .../message_update_rate_limiter_flags_test.go |  97 +++
 x/crosschain/types/query.pb.go                | 552 +++++++++++---
 x/crosschain/types/query.pb.gw.go             |  65 ++
 x/crosschain/types/rate_limiter_flags.go      |  47 ++
 x/crosschain/types/rate_limiter_flags.pb.go   | 684 ++++++++++++++++++
 x/crosschain/types/rate_limiter_flags_test.go | 186 +++++
 x/crosschain/types/tx.pb.go                   | 567 ++++++++++++---
 39 files changed, 2769 insertions(+), 254 deletions(-)
 create mode 100644 docs/cli/zetacored/zetacored_query_crosschain_update_rate_limit_flags.md
 create mode 100644 proto/crosschain/rate_limiter_flags.proto
 create mode 100644 typescript/crosschain/rate_limiter_flags_pb.d.ts
 create mode 100644 x/crosschain/client/cli/query_rate_limiter_flags.go
 create mode 100644 x/crosschain/keeper/grpc_query_rate_limiter_flags.go
 create mode 100644 x/crosschain/keeper/grpc_query_rate_limiter_flags_test.go
 create mode 100644 x/crosschain/keeper/msg_server_update_rate_limiter_flags.go
 create mode 100644 x/crosschain/keeper/msg_server_update_rate_limiter_flags_test.go
 create mode 100644 x/crosschain/keeper/rate_limiter_flags.go
 create mode 100644 x/crosschain/keeper/rate_limiter_flags_test.go
 create mode 100644 x/crosschain/types/message_update_rate_limiter_flags.go
 create mode 100644 x/crosschain/types/message_update_rate_limiter_flags_test.go
 create mode 100644 x/crosschain/types/rate_limiter_flags.go
 create mode 100644 x/crosschain/types/rate_limiter_flags.pb.go
 create mode 100644 x/crosschain/types/rate_limiter_flags_test.go

diff --git a/changelog.md b/changelog.md
index 3c13ec7bee..fd1a9c8b99 100644
--- a/changelog.md
+++ b/changelog.md
@@ -53,6 +53,7 @@
 * [1935](https://github.com/zeta-chain/node/pull/1935) - add an operational authority group
 * [1954](https://github.com/zeta-chain/node/pull/1954) - add metric for concurrent keysigns
 * [2006](https://github.com/zeta-chain/node/pull/2006) - add Amoy testnet static chain information
+* [2046](https://github.com/zeta-chain/node/pull/2046) - add state variable in crosschain for rate limiter flags
 
 ### Tests
 
diff --git a/docs/cli/zetacored/zetacored_query_crosschain.md b/docs/cli/zetacored/zetacored_query_crosschain.md
index db80778e2a..48345c136d 100644
--- a/docs/cli/zetacored/zetacored_query_crosschain.md
+++ b/docs/cli/zetacored/zetacored_query_crosschain.md
@@ -39,4 +39,5 @@ zetacored query crosschain [flags]
 * [zetacored query crosschain show-gas-price](zetacored_query_crosschain_show-gas-price.md)	 - shows a gasPrice
 * [zetacored query crosschain show-in-tx-hash-to-cctx](zetacored_query_crosschain_show-in-tx-hash-to-cctx.md)	 - shows a inTxHashToCctx
 * [zetacored query crosschain show-out-tx-tracker](zetacored_query_crosschain_show-out-tx-tracker.md)	 - shows a OutTxTracker
+* [zetacored query crosschain update_rate_limit_flags](zetacored_query_crosschain_update_rate_limit_flags.md)	 - shows the rate limiter flags
 
diff --git a/docs/cli/zetacored/zetacored_query_crosschain_update_rate_limit_flags.md b/docs/cli/zetacored/zetacored_query_crosschain_update_rate_limit_flags.md
new file mode 100644
index 0000000000..a4455cc6b0
--- /dev/null
+++ b/docs/cli/zetacored/zetacored_query_crosschain_update_rate_limit_flags.md
@@ -0,0 +1,33 @@
+# query crosschain update_rate_limit_flags
+
+shows the rate limiter flags
+
+```
+zetacored query crosschain update_rate_limit_flags [flags]
+```
+
+### Options
+
+```
+      --grpc-addr string   the gRPC endpoint to use for this chain
+      --grpc-insecure      allow gRPC over insecure channels, if not TLS the server must use TLS
+      --height int         Use a specific height to query state at (this can error if the node is pruning state)
+  -h, --help               help for update_rate_limit_flags
+      --node string        [host]:[port] to Tendermint RPC interface for this chain 
+  -o, --output string      Output format (text|json) 
+```
+
+### Options inherited from parent commands
+
+```
+      --chain-id string     The network chain ID
+      --home string         directory for config and data 
+      --log_format string   The logging format (json|plain) 
+      --log_level string    The logging level (trace|debug|info|warn|error|fatal|panic) 
+      --trace               print out full stack trace on errors
+```
+
+### SEE ALSO
+
+* [zetacored query crosschain](zetacored_query_crosschain.md)	 - Querying commands for the crosschain module
+
diff --git a/docs/openapi/openapi.swagger.yaml b/docs/openapi/openapi.swagger.yaml
index a35e40ae93..f18907f74f 100644
--- a/docs/openapi/openapi.swagger.yaml
+++ b/docs/openapi/openapi.swagger.yaml
@@ -27187,6 +27187,21 @@ paths:
             $ref: '#/definitions/googlerpcStatus'
       tags:
         - Query
+  /zeta-chain/crosschain/rateLimiterFlags:
+    get:
+      summary: Queries the rate limiter flags
+      operationId: Query_RateLimiterFlags
+      responses:
+        "200":
+          description: A successful response.
+          schema:
+            $ref: '#/definitions/crosschainQueryRateLimiterFlagsResponse'
+        default:
+          description: An unexpected error response.
+          schema:
+            $ref: '#/definitions/googlerpcStatus'
+      tags:
+        - Query
   /zeta-chain/crosschain/zetaAccounting:
     get:
       operationId: Query_ZetaAccounting
@@ -53614,6 +53629,13 @@ definitions:
        - PendingRevert: outbound cannot succeed; should revert inbound
        - Reverted: inbound reverted.
        - Aborted: inbound tx error or invalid paramters and cannot revert; just abort. But the amount can be refunded to zetachain using and admin proposal
+  crosschainConversion:
+    type: object
+    properties:
+      zrc20:
+        type: string
+      rate:
+        type: string
   crosschainCrossChainTx:
     type: object
     properties:
@@ -53743,6 +53765,8 @@ definitions:
     type: object
   crosschainMsgRemoveFromOutTxTrackerResponse:
     type: object
+  crosschainMsgUpdateRateLimiterFlagsResponse:
+    type: object
   crosschainMsgUpdateTssAddressResponse:
     type: object
   crosschainMsgVoteGasPriceResponse:
@@ -53962,11 +53986,34 @@ definitions:
     properties:
       feeInZeta:
         type: string
+  crosschainQueryRateLimiterFlagsResponse:
+    type: object
+    properties:
+      rateLimiterFlags:
+        $ref: '#/definitions/crosschainRateLimiterFlags'
   crosschainQueryZetaAccountingResponse:
     type: object
     properties:
       aborted_zeta_amount:
         type: string
+  crosschainRateLimiterFlags:
+    type: object
+    properties:
+      enabled:
+        type: boolean
+      window:
+        type: string
+        format: int64
+        title: window in blocks
+      rate:
+        type: string
+        title: rate in azeta per block
+      conversions:
+        type: array
+        items:
+          type: object
+          $ref: '#/definitions/crosschainConversion'
+        title: conversion in azeta per token
   crosschainTxFinalizationStatus:
     type: string
     enum:
diff --git a/docs/spec/crosschain/messages.md b/docs/spec/crosschain/messages.md
index 068c8c8597..549b719407 100644
--- a/docs/spec/crosschain/messages.md
+++ b/docs/spec/crosschain/messages.md
@@ -260,3 +260,15 @@ message MsgRefundAbortedCCTX {
 }
 ```
 
+## MsgUpdateRateLimiterFlags
+
+UpdateRateLimiterFlags updates the rate limiter flags.
+Authorized: admin policy operational.
+
+```proto
+message MsgUpdateRateLimiterFlags {
+	string creator = 1;
+	RateLimiterFlags rate_limiter_flags = 2;
+}
+```
+
diff --git a/proto/crosschain/genesis.proto b/proto/crosschain/genesis.proto
index 2d5d96c3a9..9213a128a5 100644
--- a/proto/crosschain/genesis.proto
+++ b/proto/crosschain/genesis.proto
@@ -7,6 +7,7 @@ import "crosschain/in_tx_hash_to_cctx.proto";
 import "crosschain/in_tx_tracker.proto";
 import "crosschain/last_block_height.proto";
 import "crosschain/out_tx_tracker.proto";
+import "crosschain/rate_limiter_flags.proto";
 import "gogoproto/gogo.proto";
 
 option go_package = "github.com/zeta-chain/zetacore/x/crosschain/types";
@@ -21,4 +22,5 @@ message GenesisState {
   repeated InTxTracker in_tx_tracker_list = 11 [(gogoproto.nullable) = false];
   ZetaAccounting zeta_accounting = 12 [(gogoproto.nullable) = false];
   repeated string FinalizedInbounds = 16;
+  RateLimiterFlags rate_limiter_flags = 17 [(gogoproto.nullable) = false];
 }
diff --git a/proto/crosschain/query.proto b/proto/crosschain/query.proto
index 99ad6b4b72..326b615560 100644
--- a/proto/crosschain/query.proto
+++ b/proto/crosschain/query.proto
@@ -8,6 +8,7 @@ import "crosschain/in_tx_hash_to_cctx.proto";
 import "crosschain/in_tx_tracker.proto";
 import "crosschain/last_block_height.proto";
 import "crosschain/out_tx_tracker.proto";
+import "crosschain/rate_limiter_flags.proto";
 import "gogoproto/gogo.proto";
 import "google/api/annotations.proto";
 
@@ -106,6 +107,11 @@ service Query {
   rpc LastZetaHeight(QueryLastZetaHeightRequest) returns (QueryLastZetaHeightResponse) {
     option (google.api.http).get = "/zeta-chain/crosschain/lastZetaHeight";
   }
+
+  // Queries the rate limiter flags
+  rpc RateLimiterFlags(QueryRateLimiterFlagsRequest) returns (QueryRateLimiterFlagsResponse) {
+    option (google.api.http).get = "/zeta-chain/crosschain/rateLimiterFlags";
+  }
 }
 
 message QueryZetaAccountingRequest {}
@@ -274,3 +280,9 @@ message QueryMessagePassingProtocolFeeRequest {}
 message QueryMessagePassingProtocolFeeResponse {
   string feeInZeta = 1;
 }
+
+message QueryRateLimiterFlagsRequest {}
+
+message QueryRateLimiterFlagsResponse {
+  RateLimiterFlags rateLimiterFlags = 1 [(gogoproto.nullable) = false];
+}
diff --git a/proto/crosschain/rate_limiter_flags.proto b/proto/crosschain/rate_limiter_flags.proto
new file mode 100644
index 0000000000..0e8185713b
--- /dev/null
+++ b/proto/crosschain/rate_limiter_flags.proto
@@ -0,0 +1,30 @@
+syntax = "proto3";
+package zetachain.zetacore.crosschain;
+
+import "gogoproto/gogo.proto";
+
+option go_package = "github.com/zeta-chain/zetacore/x/crosschain/types";
+
+message RateLimiterFlags {
+  bool enabled = 1;
+
+  // window in blocks
+  int64 window = 2;
+
+  // rate in azeta per block
+  string rate = 3 [
+    (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Uint",
+    (gogoproto.nullable) = false
+  ];
+
+  // conversion in azeta per token
+  repeated Conversion conversions = 4 [(gogoproto.nullable) = false];
+}
+
+message Conversion {
+  string zrc20 = 1;
+  string rate = 2 [
+    (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec",
+    (gogoproto.nullable) = false
+  ];
+}
diff --git a/proto/crosschain/tx.proto b/proto/crosschain/tx.proto
index ab33e1e1bb..31a6ead988 100644
--- a/proto/crosschain/tx.proto
+++ b/proto/crosschain/tx.proto
@@ -1,6 +1,7 @@
 syntax = "proto3";
 package zetachain.zetacore.crosschain;
 
+import "crosschain/rate_limiter_flags.proto";
 import "gogoproto/gogo.proto";
 import "pkg/chains/chains.proto";
 import "pkg/coin/coin.proto";
@@ -23,6 +24,8 @@ service Msg {
 
   rpc AbortStuckCCTX(MsgAbortStuckCCTX) returns (MsgAbortStuckCCTXResponse);
   rpc RefundAbortedCCTX(MsgRefundAbortedCCTX) returns (MsgRefundAbortedCCTXResponse);
+
+  rpc UpdateRateLimiterFlags(MsgUpdateRateLimiterFlags) returns (MsgUpdateRateLimiterFlagsResponse);
 }
 
 message MsgMigrateTssFunds {
@@ -164,3 +167,10 @@ message MsgRefundAbortedCCTX {
 }
 
 message MsgRefundAbortedCCTXResponse {}
+
+message MsgUpdateRateLimiterFlags {
+  string creator = 1;
+  RateLimiterFlags rate_limiter_flags = 2 [(gogoproto.nullable) = false];
+}
+
+message MsgUpdateRateLimiterFlagsResponse {}
diff --git a/testutil/sample/crosschain.go b/testutil/sample/crosschain.go
index 0040a7fc3a..f7b563d2bf 100644
--- a/testutil/sample/crosschain.go
+++ b/testutil/sample/crosschain.go
@@ -5,6 +5,8 @@ import (
 	"math/rand"
 	"testing"
 
+	sdk "github.com/cosmos/cosmos-sdk/types"
+
 	"cosmossdk.io/math"
 	ethtypes "github.com/ethereum/go-ethereum/core/types"
 	"github.com/ethereum/go-ethereum/crypto"
@@ -14,6 +16,38 @@ import (
 	"github.com/zeta-chain/zetacore/x/crosschain/types"
 )
 
+func RateLimiterFlags() types.RateLimiterFlags {
+	r := Rand()
+
+	return types.RateLimiterFlags{
+		Enabled: true,
+		Window:  r.Int63(),
+		Rate:    sdk.NewUint(r.Uint64()),
+		Conversions: []types.Conversion{
+			{
+				Zrc20: EthAddress().Hex(),
+				Rate:  sdk.NewDec(r.Int63()),
+			},
+			{
+				Zrc20: EthAddress().Hex(),
+				Rate:  sdk.NewDec(r.Int63()),
+			},
+			{
+				Zrc20: EthAddress().Hex(),
+				Rate:  sdk.NewDec(r.Int63()),
+			},
+			{
+				Zrc20: EthAddress().Hex(),
+				Rate:  sdk.NewDec(r.Int63()),
+			},
+			{
+				Zrc20: EthAddress().Hex(),
+				Rate:  sdk.NewDec(r.Int63()),
+			},
+		},
+	}
+}
+
 func OutTxTracker(t *testing.T, index string) types.OutTxTracker {
 	r := newRandFromStringSeed(t, index)
 
diff --git a/typescript/crosschain/genesis_pb.d.ts b/typescript/crosschain/genesis_pb.d.ts
index 08d35e3746..9ff48d6f47 100644
--- a/typescript/crosschain/genesis_pb.d.ts
+++ b/typescript/crosschain/genesis_pb.d.ts
@@ -11,6 +11,7 @@ import type { CrossChainTx, ZetaAccounting } from "./cross_chain_tx_pb.js";
 import type { LastBlockHeight } from "./last_block_height_pb.js";
 import type { InTxHashToCctx } from "./in_tx_hash_to_cctx_pb.js";
 import type { InTxTracker } from "./in_tx_tracker_pb.js";
+import type { RateLimiterFlags } from "./rate_limiter_flags_pb.js";
 
 /**
  * GenesisState defines the metacore module's genesis state.
@@ -58,6 +59,11 @@ export declare class GenesisState extends Message<GenesisState> {
    */
   FinalizedInbounds: string[];
 
+  /**
+   * @generated from field: zetachain.zetacore.crosschain.RateLimiterFlags rate_limiter_flags = 17;
+   */
+  rateLimiterFlags?: RateLimiterFlags;
+
   constructor(data?: PartialMessage<GenesisState>);
 
   static readonly runtime: typeof proto3;
diff --git a/typescript/crosschain/index.d.ts b/typescript/crosschain/index.d.ts
index e357b4b8b3..0f542908cb 100644
--- a/typescript/crosschain/index.d.ts
+++ b/typescript/crosschain/index.d.ts
@@ -7,4 +7,5 @@ export * from "./in_tx_tracker_pb";
 export * from "./last_block_height_pb";
 export * from "./out_tx_tracker_pb";
 export * from "./query_pb";
+export * from "./rate_limiter_flags_pb";
 export * from "./tx_pb";
diff --git a/typescript/crosschain/query_pb.d.ts b/typescript/crosschain/query_pb.d.ts
index 370926427e..e73ef4394d 100644
--- a/typescript/crosschain/query_pb.d.ts
+++ b/typescript/crosschain/query_pb.d.ts
@@ -12,6 +12,7 @@ import type { InTxHashToCctx } from "./in_tx_hash_to_cctx_pb.js";
 import type { CrossChainTx } from "./cross_chain_tx_pb.js";
 import type { GasPrice } from "./gas_price_pb.js";
 import type { LastBlockHeight } from "./last_block_height_pb.js";
+import type { RateLimiterFlags } from "./rate_limiter_flags_pb.js";
 
 /**
  * @generated from message zetachain.zetacore.crosschain.QueryZetaAccountingRequest
@@ -1019,3 +1020,46 @@ export declare class QueryMessagePassingProtocolFeeResponse extends Message<Quer
   static equals(a: QueryMessagePassingProtocolFeeResponse | PlainMessage<QueryMessagePassingProtocolFeeResponse> | undefined, b: QueryMessagePassingProtocolFeeResponse | PlainMessage<QueryMessagePassingProtocolFeeResponse> | undefined): boolean;
 }
 
+/**
+ * @generated from message zetachain.zetacore.crosschain.QueryRateLimiterFlagsRequest
+ */
+export declare class QueryRateLimiterFlagsRequest extends Message<QueryRateLimiterFlagsRequest> {
+  constructor(data?: PartialMessage<QueryRateLimiterFlagsRequest>);
+
+  static readonly runtime: typeof proto3;
+  static readonly typeName = "zetachain.zetacore.crosschain.QueryRateLimiterFlagsRequest";
+  static readonly fields: FieldList;
+
+  static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): QueryRateLimiterFlagsRequest;
+
+  static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): QueryRateLimiterFlagsRequest;
+
+  static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): QueryRateLimiterFlagsRequest;
+
+  static equals(a: QueryRateLimiterFlagsRequest | PlainMessage<QueryRateLimiterFlagsRequest> | undefined, b: QueryRateLimiterFlagsRequest | PlainMessage<QueryRateLimiterFlagsRequest> | undefined): boolean;
+}
+
+/**
+ * @generated from message zetachain.zetacore.crosschain.QueryRateLimiterFlagsResponse
+ */
+export declare class QueryRateLimiterFlagsResponse extends Message<QueryRateLimiterFlagsResponse> {
+  /**
+   * @generated from field: zetachain.zetacore.crosschain.RateLimiterFlags rateLimiterFlags = 1;
+   */
+  rateLimiterFlags?: RateLimiterFlags;
+
+  constructor(data?: PartialMessage<QueryRateLimiterFlagsResponse>);
+
+  static readonly runtime: typeof proto3;
+  static readonly typeName = "zetachain.zetacore.crosschain.QueryRateLimiterFlagsResponse";
+  static readonly fields: FieldList;
+
+  static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): QueryRateLimiterFlagsResponse;
+
+  static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): QueryRateLimiterFlagsResponse;
+
+  static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): QueryRateLimiterFlagsResponse;
+
+  static equals(a: QueryRateLimiterFlagsResponse | PlainMessage<QueryRateLimiterFlagsResponse> | undefined, b: QueryRateLimiterFlagsResponse | PlainMessage<QueryRateLimiterFlagsResponse> | undefined): boolean;
+}
+
diff --git a/typescript/crosschain/rate_limiter_flags_pb.d.ts b/typescript/crosschain/rate_limiter_flags_pb.d.ts
new file mode 100644
index 0000000000..02997cd099
--- /dev/null
+++ b/typescript/crosschain/rate_limiter_flags_pb.d.ts
@@ -0,0 +1,82 @@
+// @generated by protoc-gen-es v1.3.0 with parameter "target=dts"
+// @generated from file crosschain/rate_limiter_flags.proto (package zetachain.zetacore.crosschain, syntax proto3)
+/* eslint-disable */
+// @ts-nocheck
+
+import type { BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage } from "@bufbuild/protobuf";
+import { Message, proto3 } from "@bufbuild/protobuf";
+
+/**
+ * @generated from message zetachain.zetacore.crosschain.RateLimiterFlags
+ */
+export declare class RateLimiterFlags extends Message<RateLimiterFlags> {
+  /**
+   * @generated from field: bool enabled = 1;
+   */
+  enabled: boolean;
+
+  /**
+   * window in blocks
+   *
+   * @generated from field: int64 window = 2;
+   */
+  window: bigint;
+
+  /**
+   * rate in azeta per block
+   *
+   * @generated from field: string rate = 3;
+   */
+  rate: string;
+
+  /**
+   * conversion in azeta per token
+   *
+   * @generated from field: repeated zetachain.zetacore.crosschain.Conversion conversions = 4;
+   */
+  conversions: Conversion[];
+
+  constructor(data?: PartialMessage<RateLimiterFlags>);
+
+  static readonly runtime: typeof proto3;
+  static readonly typeName = "zetachain.zetacore.crosschain.RateLimiterFlags";
+  static readonly fields: FieldList;
+
+  static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): RateLimiterFlags;
+
+  static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): RateLimiterFlags;
+
+  static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): RateLimiterFlags;
+
+  static equals(a: RateLimiterFlags | PlainMessage<RateLimiterFlags> | undefined, b: RateLimiterFlags | PlainMessage<RateLimiterFlags> | undefined): boolean;
+}
+
+/**
+ * @generated from message zetachain.zetacore.crosschain.Conversion
+ */
+export declare class Conversion extends Message<Conversion> {
+  /**
+   * @generated from field: string zrc20 = 1;
+   */
+  zrc20: string;
+
+  /**
+   * @generated from field: string rate = 2;
+   */
+  rate: string;
+
+  constructor(data?: PartialMessage<Conversion>);
+
+  static readonly runtime: typeof proto3;
+  static readonly typeName = "zetachain.zetacore.crosschain.Conversion";
+  static readonly fields: FieldList;
+
+  static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): Conversion;
+
+  static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): Conversion;
+
+  static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): Conversion;
+
+  static equals(a: Conversion | PlainMessage<Conversion> | undefined, b: Conversion | PlainMessage<Conversion> | undefined): boolean;
+}
+
diff --git a/typescript/crosschain/tx_pb.d.ts b/typescript/crosschain/tx_pb.d.ts
index b7a76801dd..c43d5da4bc 100644
--- a/typescript/crosschain/tx_pb.d.ts
+++ b/typescript/crosschain/tx_pb.d.ts
@@ -8,6 +8,7 @@ import { Message, proto3 } from "@bufbuild/protobuf";
 import type { CoinType } from "../pkg/coin/coin_pb.js";
 import type { Proof } from "../pkg/proofs/proofs_pb.js";
 import type { ReceiveStatus } from "../pkg/chains/chains_pb.js";
+import type { RateLimiterFlags } from "./rate_limiter_flags_pb.js";
 
 /**
  * @generated from message zetachain.zetacore.crosschain.MsgMigrateTssFunds
@@ -777,3 +778,51 @@ export declare class MsgRefundAbortedCCTXResponse extends Message<MsgRefundAbort
   static equals(a: MsgRefundAbortedCCTXResponse | PlainMessage<MsgRefundAbortedCCTXResponse> | undefined, b: MsgRefundAbortedCCTXResponse | PlainMessage<MsgRefundAbortedCCTXResponse> | undefined): boolean;
 }
 
+/**
+ * @generated from message zetachain.zetacore.crosschain.MsgUpdateRateLimiterFlags
+ */
+export declare class MsgUpdateRateLimiterFlags extends Message<MsgUpdateRateLimiterFlags> {
+  /**
+   * @generated from field: string creator = 1;
+   */
+  creator: string;
+
+  /**
+   * @generated from field: zetachain.zetacore.crosschain.RateLimiterFlags rate_limiter_flags = 2;
+   */
+  rateLimiterFlags?: RateLimiterFlags;
+
+  constructor(data?: PartialMessage<MsgUpdateRateLimiterFlags>);
+
+  static readonly runtime: typeof proto3;
+  static readonly typeName = "zetachain.zetacore.crosschain.MsgUpdateRateLimiterFlags";
+  static readonly fields: FieldList;
+
+  static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): MsgUpdateRateLimiterFlags;
+
+  static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): MsgUpdateRateLimiterFlags;
+
+  static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): MsgUpdateRateLimiterFlags;
+
+  static equals(a: MsgUpdateRateLimiterFlags | PlainMessage<MsgUpdateRateLimiterFlags> | undefined, b: MsgUpdateRateLimiterFlags | PlainMessage<MsgUpdateRateLimiterFlags> | undefined): boolean;
+}
+
+/**
+ * @generated from message zetachain.zetacore.crosschain.MsgUpdateRateLimiterFlagsResponse
+ */
+export declare class MsgUpdateRateLimiterFlagsResponse extends Message<MsgUpdateRateLimiterFlagsResponse> {
+  constructor(data?: PartialMessage<MsgUpdateRateLimiterFlagsResponse>);
+
+  static readonly runtime: typeof proto3;
+  static readonly typeName = "zetachain.zetacore.crosschain.MsgUpdateRateLimiterFlagsResponse";
+  static readonly fields: FieldList;
+
+  static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): MsgUpdateRateLimiterFlagsResponse;
+
+  static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): MsgUpdateRateLimiterFlagsResponse;
+
+  static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): MsgUpdateRateLimiterFlagsResponse;
+
+  static equals(a: MsgUpdateRateLimiterFlagsResponse | PlainMessage<MsgUpdateRateLimiterFlagsResponse> | undefined, b: MsgUpdateRateLimiterFlagsResponse | PlainMessage<MsgUpdateRateLimiterFlagsResponse> | undefined): boolean;
+}
+
diff --git a/x/crosschain/client/cli/query.go b/x/crosschain/client/cli/query.go
index cd966e55af..9f9ae29752 100644
--- a/x/crosschain/client/cli/query.go
+++ b/x/crosschain/client/cli/query.go
@@ -3,14 +3,8 @@ package cli
 import (
 	"fmt"
 
-	// "strings"
-
 	"github.com/cosmos/cosmos-sdk/client"
 	"github.com/spf13/cobra"
-
-	// "github.com/cosmos/cosmos-sdk/client/flags"
-	// sdk "github.com/cosmos/cosmos-sdk/types"
-
 	"github.com/zeta-chain/zetacore/x/crosschain/types"
 )
 
@@ -42,6 +36,8 @@ func GetQueryCmd(_ string) *cobra.Command {
 		CmdListInTxTrackerByChain(),
 		CmdListInTxTrackers(),
 		CmdGetZetaAccounting(),
+
+		CmdShowUpdateRateLimiterFlags(),
 	)
 
 	return cmd
diff --git a/x/crosschain/client/cli/query_rate_limiter_flags.go b/x/crosschain/client/cli/query_rate_limiter_flags.go
new file mode 100644
index 0000000000..43377e8b50
--- /dev/null
+++ b/x/crosschain/client/cli/query_rate_limiter_flags.go
@@ -0,0 +1,33 @@
+package cli
+
+import (
+	"context"
+
+	"github.com/cosmos/cosmos-sdk/client"
+	"github.com/cosmos/cosmos-sdk/client/flags"
+	"github.com/spf13/cobra"
+	"github.com/zeta-chain/zetacore/x/crosschain/types"
+)
+
+func CmdShowUpdateRateLimiterFlags() *cobra.Command {
+	cmd := &cobra.Command{
+		Use:   "update_rate_limit_flags",
+		Short: "shows the rate limiter flags",
+		RunE: func(cmd *cobra.Command, args []string) error {
+			clientCtx := client.GetClientContextFromCmd(cmd)
+
+			queryClient := types.NewQueryClient(clientCtx)
+
+			res, err := queryClient.RateLimiterFlags(context.Background(), &types.QueryRateLimiterFlagsRequest{})
+			if err != nil {
+				return err
+			}
+
+			return clientCtx.PrintProto(res)
+		},
+	}
+
+	flags.AddQueryFlagsToCmd(cmd)
+
+	return cmd
+}
diff --git a/x/crosschain/genesis.go b/x/crosschain/genesis.go
index c2603532a6..895ca05639 100644
--- a/x/crosschain/genesis.go
+++ b/x/crosschain/genesis.go
@@ -50,6 +50,8 @@ func InitGenesis(ctx sdk.Context, k keeper.Keeper, genState types.GenesisState)
 	for _, elem := range genState.FinalizedInbounds {
 		k.SetFinalizedInbound(ctx, elem)
 	}
+
+	k.SetRateLimiterFlags(ctx, genState.RateLimiterFlags)
 }
 
 // ExportGenesis returns the crosschain module's exported genesis.
@@ -87,5 +89,10 @@ func ExportGenesis(ctx sdk.Context, k keeper.Keeper) *types.GenesisState {
 	}
 	genesis.FinalizedInbounds = k.GetAllFinalizedInbound(ctx)
 
+	rateLimiterFlags, found := k.GetRateLimiterFlags(ctx)
+	if found {
+		genesis.RateLimiterFlags = rateLimiterFlags
+	}
+
 	return &genesis
 }
diff --git a/x/crosschain/genesis_test.go b/x/crosschain/genesis_test.go
index 470d07b09b..bc624baf29 100644
--- a/x/crosschain/genesis_test.go
+++ b/x/crosschain/genesis_test.go
@@ -49,6 +49,7 @@ func TestGenesis(t *testing.T) {
 			sample.InTxHashToCctx(t, "0x1"),
 			sample.InTxHashToCctx(t, "0x2"),
 		},
+		RateLimiterFlags: sample.RateLimiterFlags(),
 	}
 
 	// Init and export
diff --git a/x/crosschain/keeper/grpc_query_rate_limiter_flags.go b/x/crosschain/keeper/grpc_query_rate_limiter_flags.go
new file mode 100644
index 0000000000..998b9cf0a2
--- /dev/null
+++ b/x/crosschain/keeper/grpc_query_rate_limiter_flags.go
@@ -0,0 +1,26 @@
+package keeper
+
+import (
+	"context"
+
+	sdk "github.com/cosmos/cosmos-sdk/types"
+	"github.com/zeta-chain/zetacore/x/crosschain/types"
+	"google.golang.org/grpc/codes"
+	"google.golang.org/grpc/status"
+)
+
+// RateLimiterFlags queries the rate limiter flags
+func (k Keeper) RateLimiterFlags(c context.Context, req *types.QueryRateLimiterFlagsRequest) (*types.QueryRateLimiterFlagsResponse, error) {
+	if req == nil {
+		return nil, status.Error(codes.InvalidArgument, "invalid request")
+	}
+
+	ctx := sdk.UnwrapSDKContext(c)
+
+	rateLimiterFlags, found := k.GetRateLimiterFlags(ctx)
+	if !found {
+		return nil, status.Error(codes.Internal, "not found")
+	}
+
+	return &types.QueryRateLimiterFlagsResponse{RateLimiterFlags: rateLimiterFlags}, nil
+}
diff --git a/x/crosschain/keeper/grpc_query_rate_limiter_flags_test.go b/x/crosschain/keeper/grpc_query_rate_limiter_flags_test.go
new file mode 100644
index 0000000000..66aaf2d751
--- /dev/null
+++ b/x/crosschain/keeper/grpc_query_rate_limiter_flags_test.go
@@ -0,0 +1,46 @@
+package keeper_test
+
+import (
+	"testing"
+
+	sdk "github.com/cosmos/cosmos-sdk/types"
+	"github.com/stretchr/testify/require"
+	keepertest "github.com/zeta-chain/zetacore/testutil/keeper"
+	"github.com/zeta-chain/zetacore/testutil/sample"
+	"github.com/zeta-chain/zetacore/x/crosschain/types"
+)
+
+func TestKeeper_RateLimiterFlags(t *testing.T) {
+	t.Run("should error if req is nil", func(t *testing.T) {
+		k, ctx, _, _ := keepertest.CrosschainKeeper(t)
+		wctx := sdk.WrapSDKContext(ctx)
+
+		res, err := k.RateLimiterFlags(wctx, nil)
+		require.Nil(t, res)
+		require.Error(t, err)
+	})
+
+	t.Run("should error if rate limiter flags not found", func(t *testing.T) {
+		k, ctx, _, _ := keepertest.CrosschainKeeper(t)
+		wctx := sdk.WrapSDKContext(ctx)
+
+		res, err := k.RateLimiterFlags(wctx, &types.QueryRateLimiterFlagsRequest{})
+		require.Nil(t, res)
+		require.Error(t, err)
+	})
+
+	t.Run("should return if rate limiter flags found", func(t *testing.T) {
+		k, ctx, _, _ := keepertest.CrosschainKeeper(t)
+		wctx := sdk.WrapSDKContext(ctx)
+
+		flags := sample.RateLimiterFlags()
+		k.SetRateLimiterFlags(ctx, flags)
+
+		res, err := k.RateLimiterFlags(wctx, &types.QueryRateLimiterFlagsRequest{})
+
+		require.NoError(t, err)
+		require.Equal(t, &types.QueryRateLimiterFlagsResponse{
+			RateLimiterFlags: flags,
+		}, res)
+	})
+}
diff --git a/x/crosschain/keeper/msg_server_update_rate_limiter_flags.go b/x/crosschain/keeper/msg_server_update_rate_limiter_flags.go
new file mode 100644
index 0000000000..357bbfa7fc
--- /dev/null
+++ b/x/crosschain/keeper/msg_server_update_rate_limiter_flags.go
@@ -0,0 +1,25 @@
+package keeper
+
+import (
+	"context"
+	"fmt"
+
+	errorsmod "cosmossdk.io/errors"
+	sdk "github.com/cosmos/cosmos-sdk/types"
+	authoritytypes "github.com/zeta-chain/zetacore/x/authority/types"
+	"github.com/zeta-chain/zetacore/x/crosschain/types"
+)
+
+// UpdateRateLimiterFlags updates the rate limiter flags.
+// Authorized: admin policy operational.
+func (k msgServer) UpdateRateLimiterFlags(goCtx context.Context, msg *types.MsgUpdateRateLimiterFlags) (*types.MsgUpdateRateLimiterFlagsResponse, error) {
+	ctx := sdk.UnwrapSDKContext(goCtx)
+
+	if !k.GetAuthorityKeeper().IsAuthorized(ctx, msg.Creator, authoritytypes.PolicyType_groupOperational) {
+		return nil, errorsmod.Wrap(authoritytypes.ErrUnauthorized, fmt.Sprintf("Creator %s", msg.Creator))
+	}
+
+	k.SetRateLimiterFlags(ctx, msg.RateLimiterFlags)
+
+	return &types.MsgUpdateRateLimiterFlagsResponse{}, nil
+}
diff --git a/x/crosschain/keeper/msg_server_update_rate_limiter_flags_test.go b/x/crosschain/keeper/msg_server_update_rate_limiter_flags_test.go
new file mode 100644
index 0000000000..53b1d6772d
--- /dev/null
+++ b/x/crosschain/keeper/msg_server_update_rate_limiter_flags_test.go
@@ -0,0 +1,57 @@
+package keeper_test
+
+import (
+	"testing"
+
+	"github.com/stretchr/testify/require"
+	keepertest "github.com/zeta-chain/zetacore/testutil/keeper"
+	"github.com/zeta-chain/zetacore/testutil/sample"
+	authoritytypes "github.com/zeta-chain/zetacore/x/authority/types"
+	"github.com/zeta-chain/zetacore/x/crosschain/keeper"
+	"github.com/zeta-chain/zetacore/x/crosschain/types"
+)
+
+func TestMsgServer_UpdateRateLimiterFlags(t *testing.T) {
+	t.Run("can update rate limiter flags", func(t *testing.T) {
+		k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, keepertest.CrosschainMockOptions{
+			UseAuthorityMock: true,
+		})
+		msgServer := keeper.NewMsgServerImpl(*k)
+		admin := sample.AccAddress()
+
+		authorityMock := keepertest.GetCrosschainAuthorityMock(t, k)
+		keepertest.MockIsAuthorized(&authorityMock.Mock, admin, authoritytypes.PolicyType_groupOperational, true)
+
+		_, found := k.GetRateLimiterFlags(ctx)
+		require.False(t, found)
+
+		flags := sample.RateLimiterFlags()
+
+		_, err := msgServer.UpdateRateLimiterFlags(ctx, types.NewMsgUpdateRateLimiterFlags(
+			admin,
+			flags,
+		))
+		require.NoError(t, err)
+
+		storedFlags, found := k.GetRateLimiterFlags(ctx)
+		require.True(t, found)
+		require.Equal(t, flags, storedFlags)
+	})
+
+	t.Run("cannot update rate limiter flags if unauthorized", func(t *testing.T) {
+		k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, keepertest.CrosschainMockOptions{
+			UseAuthorityMock: true,
+		})
+		msgServer := keeper.NewMsgServerImpl(*k)
+		admin := sample.AccAddress()
+
+		authorityMock := keepertest.GetCrosschainAuthorityMock(t, k)
+		keepertest.MockIsAuthorized(&authorityMock.Mock, admin, authoritytypes.PolicyType_groupOperational, false)
+
+		_, err := msgServer.UpdateRateLimiterFlags(ctx, types.NewMsgUpdateRateLimiterFlags(
+			admin,
+			sample.RateLimiterFlags(),
+		))
+		require.ErrorIs(t, err, authoritytypes.ErrUnauthorized)
+	})
+}
diff --git a/x/crosschain/keeper/rate_limiter_flags.go b/x/crosschain/keeper/rate_limiter_flags.go
new file mode 100644
index 0000000000..d0d7e2febc
--- /dev/null
+++ b/x/crosschain/keeper/rate_limiter_flags.go
@@ -0,0 +1,27 @@
+package keeper
+
+import (
+	"github.com/cosmos/cosmos-sdk/store/prefix"
+	sdk "github.com/cosmos/cosmos-sdk/types"
+	"github.com/zeta-chain/zetacore/x/crosschain/types"
+)
+
+// SetRateLimiterFlags set the rate limiter flags in the store
+func (k Keeper) SetRateLimiterFlags(ctx sdk.Context, rateLimiterFlags types.RateLimiterFlags) {
+	store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.RateLimiterFlagsKey))
+	b := k.cdc.MustMarshal(&rateLimiterFlags)
+	store.Set([]byte{0}, b)
+}
+
+// GetRateLimiterFlags returns the rate limiter flags
+func (k Keeper) GetRateLimiterFlags(ctx sdk.Context) (val types.RateLimiterFlags, found bool) {
+	store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.RateLimiterFlagsKey))
+
+	b := store.Get([]byte{0})
+	if b == nil {
+		return val, false
+	}
+
+	k.cdc.MustUnmarshal(b, &val)
+	return val, true
+}
diff --git a/x/crosschain/keeper/rate_limiter_flags_test.go b/x/crosschain/keeper/rate_limiter_flags_test.go
new file mode 100644
index 0000000000..044d02bc67
--- /dev/null
+++ b/x/crosschain/keeper/rate_limiter_flags_test.go
@@ -0,0 +1,24 @@
+package keeper_test
+
+import (
+	"testing"
+
+	"github.com/stretchr/testify/require"
+	keepertest "github.com/zeta-chain/zetacore/testutil/keeper"
+	"github.com/zeta-chain/zetacore/testutil/sample"
+)
+
+func TestKeeper_GetRateLimiterFlags(t *testing.T) {
+	k, ctx, _, _ := keepertest.CrosschainKeeper(t)
+
+	// not found
+	_, found := k.GetRateLimiterFlags(ctx)
+	require.False(t, found)
+
+	flags := sample.RateLimiterFlags()
+
+	k.SetRateLimiterFlags(ctx, flags)
+	r, found := k.GetRateLimiterFlags(ctx)
+	require.True(t, found)
+	require.Equal(t, flags, r)
+}
diff --git a/x/crosschain/types/codec.go b/x/crosschain/types/codec.go
index 757cb73ad7..2f0bcc0eb0 100644
--- a/x/crosschain/types/codec.go
+++ b/x/crosschain/types/codec.go
@@ -18,6 +18,7 @@ func RegisterCodec(cdc *codec.LegacyAmino) {
 	cdc.RegisterConcrete(&MsgMigrateTssFunds{}, "crosschain/MigrateTssFunds", nil)
 	cdc.RegisterConcrete(&MsgUpdateTssAddress{}, "crosschain/UpdateTssAddress", nil)
 	cdc.RegisterConcrete(&MsgAbortStuckCCTX{}, "crosschain/AbortStuckCCTX", nil)
+	cdc.RegisterConcrete(&MsgUpdateRateLimiterFlags{}, "crosschain/UpdateRateLimiterFlags", nil)
 }
 
 func RegisterInterfaces(registry cdctypes.InterfaceRegistry) {
@@ -32,6 +33,7 @@ func RegisterInterfaces(registry cdctypes.InterfaceRegistry) {
 		&MsgMigrateTssFunds{},
 		&MsgUpdateTssAddress{},
 		&MsgAbortStuckCCTX{},
+		&MsgUpdateRateLimiterFlags{},
 	)
 
 	msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc)
diff --git a/x/crosschain/types/errors.go b/x/crosschain/types/errors.go
index 0578e68fa6..1b80e4fe19 100644
--- a/x/crosschain/types/errors.go
+++ b/x/crosschain/types/errors.go
@@ -41,5 +41,6 @@ var (
 	ErrUnableProcessRefund           = errorsmod.Register(ModuleName, 1148, "unable to process refund")
 	ErrUnableToFindZetaAccounting    = errorsmod.Register(ModuleName, 1149, "unable to find zeta accounting")
 	ErrInsufficientZetaAmount        = errorsmod.Register(ModuleName, 1150, "insufficient zeta amount")
-	ErrMaxTxOutTrackerHashesReached  = errorsmod.Register(ModuleName, 1151, "max tx out tracker hashes reached")
+	ErrInvalidRateLimiterFlags       = errorsmod.Register(ModuleName, 1151, "invalid rate limiter flags")
+	ErrMaxTxOutTrackerHashesReached  = errorsmod.Register(ModuleName, 1152, "max tx out tracker hashes reached")
 )
diff --git a/x/crosschain/types/genesis.go b/x/crosschain/types/genesis.go
index 23343133c8..834e4ddb9d 100644
--- a/x/crosschain/types/genesis.go
+++ b/x/crosschain/types/genesis.go
@@ -7,9 +7,6 @@ import (
 	"github.com/cosmos/cosmos-sdk/codec"
 )
 
-// DefaultIndex is the default crosschain global index
-const DefaultIndex uint64 = 1
-
 // DefaultGenesis returns the default crosschain genesis state
 func DefaultGenesis() *GenesisState {
 	return &GenesisState{
@@ -44,7 +41,6 @@ func (gs GenesisState) Validate() error {
 		}
 		inTxHashToCctxIndexMap[index] = struct{}{}
 	}
-	// TODO add migrate for TSS
 
 	// Check for duplicated index in gasPrice
 	gasPriceIndexMap := make(map[string]bool)
@@ -56,17 +52,7 @@ func (gs GenesisState) Validate() error {
 		gasPriceIndexMap[elem.Index] = true
 	}
 
-	// Check for duplicated index in send
-	//sendIndexMap := make(map[string]bool)
-
-	//for _, elem := range gs.SendList {
-	//	if _, ok := sendIndexMap[elem.Index]; ok {
-	//		return fmt.Errorf("duplicated index for send")
-	//	}
-	//	sendIndexMap[elem.Index] = true
-	//}
-
-	return nil
+	return gs.RateLimiterFlags.Validate()
 }
 
 func GetGenesisStateFromAppState(marshaler codec.JSONCodec, appState map[string]json.RawMessage) GenesisState {
diff --git a/x/crosschain/types/genesis.pb.go b/x/crosschain/types/genesis.pb.go
index d7511b155d..8045b2d098 100644
--- a/x/crosschain/types/genesis.pb.go
+++ b/x/crosschain/types/genesis.pb.go
@@ -34,6 +34,7 @@ type GenesisState struct {
 	InTxTrackerList     []InTxTracker      `protobuf:"bytes,11,rep,name=in_tx_tracker_list,json=inTxTrackerList,proto3" json:"in_tx_tracker_list"`
 	ZetaAccounting      ZetaAccounting     `protobuf:"bytes,12,opt,name=zeta_accounting,json=zetaAccounting,proto3" json:"zeta_accounting"`
 	FinalizedInbounds   []string           `protobuf:"bytes,16,rep,name=FinalizedInbounds,proto3" json:"FinalizedInbounds,omitempty"`
+	RateLimiterFlags    RateLimiterFlags   `protobuf:"bytes,17,opt,name=rate_limiter_flags,json=rateLimiterFlags,proto3" json:"rate_limiter_flags"`
 }
 
 func (m *GenesisState) Reset()         { *m = GenesisState{} }
@@ -125,6 +126,13 @@ func (m *GenesisState) GetFinalizedInbounds() []string {
 	return nil
 }
 
+func (m *GenesisState) GetRateLimiterFlags() RateLimiterFlags {
+	if m != nil {
+		return m.RateLimiterFlags
+	}
+	return RateLimiterFlags{}
+}
+
 func init() {
 	proto.RegisterType((*GenesisState)(nil), "zetachain.zetacore.crosschain.GenesisState")
 }
@@ -132,37 +140,39 @@ func init() {
 func init() { proto.RegisterFile("crosschain/genesis.proto", fileDescriptor_dd51403692d571f4) }
 
 var fileDescriptor_dd51403692d571f4 = []byte{
-	// 465 bytes of a gzipped FileDescriptorProto
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x93, 0x41, 0x6f, 0xd3, 0x30,
-	0x14, 0xc7, 0x5b, 0xc6, 0x80, 0x79, 0x85, 0x0d, 0xc3, 0x21, 0xaa, 0x44, 0x56, 0x8d, 0x03, 0x13,
-	0xb0, 0x44, 0xc0, 0x27, 0xa0, 0x95, 0xd8, 0xa6, 0x4d, 0x02, 0x42, 0x4e, 0x13, 0x93, 0x71, 0x3c,
-	0x2b, 0xb1, 0x16, 0xec, 0x2a, 0x7e, 0x91, 0x42, 0x3f, 0x05, 0xdf, 0x88, 0xeb, 0x8e, 0x3b, 0x72,
-	0x42, 0xa8, 0xfd, 0x22, 0xc8, 0x4e, 0x18, 0x8e, 0x32, 0xd1, 0xde, 0x9e, 0xfc, 0xde, 0xff, 0xf7,
-	0x7f, 0xf9, 0x3b, 0x46, 0x1e, 0x2b, 0x94, 0xd6, 0x2c, 0xa3, 0x42, 0x86, 0x29, 0x97, 0x5c, 0x0b,
-	0x1d, 0x4c, 0x0b, 0x05, 0x0a, 0x3f, 0x99, 0x71, 0xa0, 0xb6, 0x11, 0xd8, 0x4a, 0x15, 0x3c, 0xf8,
-	0x37, 0x3c, 0xdc, 0x71, 0x84, 0xb6, 0x24, 0xb6, 0x26, 0x50, 0xd5, 0xfa, 0xe1, 0xd0, 0x25, 0x53,
-	0x4d, 0xa6, 0x85, 0x60, 0xbc, 0xe9, 0x3d, 0x75, 0x7a, 0x56, 0x43, 0x32, 0xaa, 0x33, 0x02, 0x8a,
-	0x30, 0x76, 0x0d, 0xf0, 0x3b, 0x43, 0x50, 0x50, 0x76, 0xc1, 0x8b, 0xa6, 0xbf, 0xeb, 0xf4, 0x73,
-	0xaa, 0x81, 0x24, 0xb9, 0x62, 0x17, 0x24, 0xe3, 0x22, 0xcd, 0xa0, 0x99, 0x71, 0xb7, 0x54, 0x25,
-	0x74, 0x21, 0x8f, 0x53, 0x95, 0x2a, 0x5b, 0x86, 0xa6, 0xaa, 0x4f, 0x77, 0x7f, 0xac, 0xa3, 0xc1,
-	0x41, 0x9d, 0xc6, 0x27, 0xa0, 0xc0, 0xf1, 0x19, 0xda, 0x56, 0x25, 0xc4, 0x55, 0x5c, 0x8b, 0x4f,
-	0x84, 0x06, 0xef, 0xd6, 0x68, 0x6d, 0x6f, 0xf3, 0xf5, 0x8b, 0xe0, 0xbf, 0x39, 0x05, 0xef, 0x1d,
-	0xd9, 0xf8, 0xf6, 0xe5, 0xaf, 0x9d, 0x5e, 0xd4, 0x41, 0xe1, 0x63, 0x34, 0x48, 0xa9, 0xfe, 0x60,
-	0x12, 0xb2, 0xe8, 0x75, 0x8b, 0x7e, 0xb6, 0x04, 0x7d, 0xd0, 0x48, 0xa2, 0x96, 0x18, 0x7f, 0x44,
-	0xf7, 0x27, 0x66, 0x68, 0x62, 0x86, 0xe2, 0x4a, 0x7b, 0x77, 0x57, 0x5a, 0xd4, 0xd5, 0x44, 0x6d,
-	0x02, 0xfe, 0x82, 0x1e, 0x99, 0x84, 0xc7, 0x26, 0xe0, 0x43, 0x9b, 0xaf, 0x5d, 0xf3, 0x9e, 0x05,
-	0x07, 0x4b, 0xc0, 0x27, 0x6d, 0x65, 0x74, 0x13, 0x0a, 0x33, 0x84, 0x8d, 0xd5, 0x21, 0xd5, 0x59,
-	0xac, 0x26, 0x0c, 0x2a, 0x6b, 0xb0, 0x61, 0x0d, 0xf6, 0x97, 0x18, 0x1c, 0xb5, 0x84, 0x4d, 0xc8,
-	0x37, 0xe0, 0xf0, 0x99, 0x31, 0x71, 0xfe, 0x01, 0x92, 0x1b, 0x93, 0x4d, 0x6b, 0xf2, 0x7c, 0x05,
-	0x93, 0xf6, 0x35, 0x6e, 0x09, 0xd9, 0xbe, 0xc5, 0xcf, 0x68, 0xcb, 0x28, 0x09, 0x65, 0x4c, 0x95,
-	0x12, 0x84, 0x4c, 0xbd, 0xc1, 0xa8, 0xbf, 0xc2, 0x07, 0x9c, 0x72, 0xa0, 0x6f, 0xaf, 0x45, 0x0d,
-	0xfe, 0xc1, 0xac, 0x75, 0x8a, 0x5f, 0xa2, 0x87, 0xef, 0x84, 0xa4, 0xb9, 0x98, 0xf1, 0xf3, 0x23,
-	0x99, 0xa8, 0x52, 0x9e, 0x6b, 0x6f, 0x7b, 0xb4, 0xb6, 0xb7, 0x11, 0x75, 0x1b, 0xe3, 0xe3, 0xcb,
-	0xb9, 0xdf, 0xbf, 0x9a, 0xfb, 0xfd, 0xdf, 0x73, 0xbf, 0xff, 0x7d, 0xe1, 0xf7, 0xae, 0x16, 0x7e,
-	0xef, 0xe7, 0xc2, 0xef, 0x9d, 0xbe, 0x4a, 0x05, 0x64, 0x65, 0x12, 0x30, 0xf5, 0x35, 0x34, 0x16,
-	0xfb, 0xf5, 0xeb, 0xf8, 0xbb, 0x57, 0x58, 0x85, 0xce, 0x9b, 0x81, 0x6f, 0x53, 0xae, 0x93, 0x3b,
-	0xf6, 0x55, 0xbc, 0xf9, 0x13, 0x00, 0x00, 0xff, 0xff, 0x28, 0xc8, 0xb0, 0x72, 0x2d, 0x04, 0x00,
-	0x00,
+	// 507 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x93, 0xdf, 0x6e, 0xd3, 0x30,
+	0x14, 0xc6, 0x5b, 0x06, 0x83, 0x79, 0x85, 0x6d, 0x86, 0x8b, 0xa8, 0x12, 0x59, 0x35, 0x2e, 0x98,
+	0x80, 0x25, 0x02, 0x9e, 0x80, 0x55, 0xda, 0x1f, 0xad, 0x12, 0x10, 0x7a, 0x35, 0x31, 0x19, 0xd7,
+	0x33, 0x89, 0xb5, 0x2c, 0xae, 0xec, 0x13, 0x29, 0xf4, 0x29, 0x78, 0x08, 0x1e, 0x66, 0x97, 0xbb,
+	0xe4, 0x0a, 0xa1, 0xf6, 0x45, 0x90, 0x9d, 0x6c, 0x38, 0xa4, 0xa2, 0xbd, 0x3b, 0xf2, 0x39, 0xdf,
+	0xef, 0x3b, 0x3e, 0xc7, 0x46, 0x1e, 0x53, 0x52, 0x6b, 0x96, 0x50, 0x91, 0x85, 0x31, 0xcf, 0xb8,
+	0x16, 0x3a, 0x18, 0x2b, 0x09, 0x12, 0x3f, 0x9d, 0x70, 0xa0, 0x36, 0x11, 0xd8, 0x48, 0x2a, 0x1e,
+	0xfc, 0x2d, 0xee, 0x6e, 0x3b, 0x42, 0x1b, 0x12, 0x1b, 0x13, 0x28, 0x4a, 0x7d, 0xb7, 0xeb, 0x92,
+	0xa9, 0x26, 0x63, 0x25, 0x18, 0xaf, 0x72, 0xcf, 0x9c, 0x9c, 0xd5, 0x90, 0x84, 0xea, 0x84, 0x80,
+	0x24, 0x8c, 0xdd, 0x02, 0xfc, 0x46, 0x11, 0x28, 0xca, 0x2e, 0xb8, 0xaa, 0xf2, 0x3b, 0x4e, 0x3e,
+	0xa5, 0x1a, 0xc8, 0x28, 0x95, 0xec, 0x82, 0x24, 0x5c, 0xc4, 0x09, 0x54, 0x35, 0x6e, 0x97, 0x32,
+	0x87, 0x26, 0xc4, 0xed, 0x44, 0x51, 0xe0, 0x24, 0x15, 0x97, 0x02, 0xb8, 0x22, 0x5f, 0x53, 0x1a,
+	0x57, 0xa3, 0xe8, 0x3e, 0x89, 0x65, 0x2c, 0x6d, 0x18, 0x9a, 0xa8, 0x3c, 0xdd, 0xf9, 0xb1, 0x8a,
+	0x3a, 0x87, 0xe5, 0xc8, 0x3e, 0x01, 0x05, 0x8e, 0xcf, 0xd0, 0xa6, 0xcc, 0x61, 0x58, 0x0c, 0x4b,
+	0x87, 0x81, 0xd0, 0xe0, 0xdd, 0xe9, 0xad, 0xec, 0xae, 0xbf, 0x79, 0x19, 0xfc, 0x77, 0x98, 0xc1,
+	0x7b, 0x47, 0xb6, 0x7f, 0xf7, 0xea, 0xd7, 0x76, 0x2b, 0x6a, 0xa0, 0xf0, 0x09, 0xea, 0xc4, 0x54,
+	0x7f, 0x30, 0x63, 0xb4, 0xe8, 0x7b, 0x16, 0xfd, 0x7c, 0x01, 0xfa, 0xb0, 0x92, 0x44, 0x35, 0x31,
+	0xfe, 0x88, 0x1e, 0xf6, 0x4d, 0x51, 0xdf, 0x14, 0x0d, 0x0b, 0xed, 0xdd, 0x5f, 0xaa, 0x51, 0x57,
+	0x13, 0xd5, 0x09, 0xf8, 0x0b, 0x7a, 0x6c, 0xd6, 0xb0, 0x6f, 0xb6, 0x70, 0x64, 0x97, 0x60, 0xdb,
+	0x7c, 0x60, 0xc1, 0xc1, 0x02, 0xf0, 0xa0, 0xae, 0x8c, 0xe6, 0xa1, 0x30, 0x43, 0xd8, 0x58, 0x1d,
+	0x51, 0x9d, 0x0c, 0x65, 0x9f, 0x41, 0x61, 0x0d, 0xd6, 0xac, 0xc1, 0xde, 0x02, 0x83, 0xe3, 0x9a,
+	0xb0, 0x1a, 0xf2, 0x1c, 0x1c, 0x3e, 0x33, 0x26, 0xce, 0x43, 0x21, 0xa9, 0x31, 0x59, 0xb7, 0x26,
+	0x2f, 0x96, 0x30, 0xa9, 0xaf, 0x71, 0x43, 0x64, 0xf5, 0x2d, 0x7e, 0x46, 0x1b, 0x46, 0x49, 0x28,
+	0x63, 0x32, 0xcf, 0x40, 0x64, 0xb1, 0xd7, 0xe9, 0xb5, 0x97, 0xb8, 0xc0, 0x29, 0x07, 0xfa, 0xee,
+	0x56, 0x54, 0xe1, 0x1f, 0x4d, 0x6a, 0xa7, 0xf8, 0x15, 0xda, 0x3a, 0x10, 0x19, 0x4d, 0xc5, 0x84,
+	0x9f, 0x1f, 0x67, 0x23, 0x99, 0x67, 0xe7, 0xda, 0xdb, 0xec, 0xad, 0xec, 0xae, 0x45, 0xcd, 0x84,
+	0x99, 0x67, 0xf3, 0xcd, 0x7b, 0x5b, 0xb6, 0x9d, 0x70, 0x41, 0x3b, 0x11, 0x05, 0x3e, 0x28, 0x75,
+	0x07, 0x46, 0x76, 0xf3, 0x6c, 0xd5, 0xbf, 0xe7, 0x27, 0x57, 0x53, 0xbf, 0x7d, 0x3d, 0xf5, 0xdb,
+	0xbf, 0xa7, 0x7e, 0xfb, 0xfb, 0xcc, 0x6f, 0x5d, 0xcf, 0xfc, 0xd6, 0xcf, 0x99, 0xdf, 0x3a, 0x7d,
+	0x1d, 0x0b, 0x48, 0xf2, 0x51, 0xc0, 0xe4, 0x65, 0x68, 0x2c, 0xf6, 0xca, 0x6f, 0x78, 0xe3, 0x16,
+	0x16, 0xa1, 0xf3, 0x39, 0xe1, 0xdb, 0x98, 0xeb, 0xd1, 0xaa, 0xfd, 0x7a, 0x6f, 0xff, 0x04, 0x00,
+	0x00, 0xff, 0xff, 0x4d, 0xc1, 0xbb, 0x72, 0xb7, 0x04, 0x00, 0x00,
 }
 
 func (m *GenesisState) Marshal() (dAtA []byte, err error) {
@@ -185,6 +195,18 @@ func (m *GenesisState) MarshalToSizedBuffer(dAtA []byte) (int, error) {
 	_ = i
 	var l int
 	_ = l
+	{
+		size, err := m.RateLimiterFlags.MarshalToSizedBuffer(dAtA[:i])
+		if err != nil {
+			return 0, err
+		}
+		i -= size
+		i = encodeVarintGenesis(dAtA, i, uint64(size))
+	}
+	i--
+	dAtA[i] = 0x1
+	i--
+	dAtA[i] = 0x8a
 	if len(m.FinalizedInbounds) > 0 {
 		for iNdEx := len(m.FinalizedInbounds) - 1; iNdEx >= 0; iNdEx-- {
 			i -= len(m.FinalizedInbounds[iNdEx])
@@ -354,6 +376,8 @@ func (m *GenesisState) Size() (n int) {
 			n += 2 + l + sovGenesis(uint64(l))
 		}
 	}
+	l = m.RateLimiterFlags.Size()
+	n += 2 + l + sovGenesis(uint64(l))
 	return n
 }
 
@@ -661,6 +685,39 @@ func (m *GenesisState) Unmarshal(dAtA []byte) error {
 			}
 			m.FinalizedInbounds = append(m.FinalizedInbounds, string(dAtA[iNdEx:postIndex]))
 			iNdEx = postIndex
+		case 17:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field RateLimiterFlags", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGenesis
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthGenesis
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthGenesis
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if err := m.RateLimiterFlags.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
 		default:
 			iNdEx = preIndex
 			skippy, err := skipGenesis(dAtA[iNdEx:])
diff --git a/x/crosschain/types/genesis_test.go b/x/crosschain/types/genesis_test.go
index c3e555fa61..1d09c26488 100644
--- a/x/crosschain/types/genesis_test.go
+++ b/x/crosschain/types/genesis_test.go
@@ -43,6 +43,7 @@ func TestGenesisState_Validate(t *testing.T) {
 					sample.GasPrice(t, "1"),
 					sample.GasPrice(t, "2"),
 				},
+				RateLimiterFlags: sample.RateLimiterFlags(),
 			},
 			valid: true,
 		},
@@ -60,6 +61,21 @@ func TestGenesisState_Validate(t *testing.T) {
 			},
 			valid: false,
 		},
+		{
+			desc: "duplicated outTxTracker",
+			genState: &types.GenesisState{
+				OutTxTrackerList: []types.OutTxTracker{
+					{
+						Index: "0",
+					},
+				},
+				RateLimiterFlags: types.RateLimiterFlags{
+					Enabled: true,
+					Window:  -1,
+				},
+			},
+			valid: false,
+		},
 		{
 			desc: "duplicated inTxHashToCctx",
 			genState: &types.GenesisState{
diff --git a/x/crosschain/types/keys.go b/x/crosschain/types/keys.go
index 719f54687f..af888d0324 100644
--- a/x/crosschain/types/keys.go
+++ b/x/crosschain/types/keys.go
@@ -53,6 +53,8 @@ const (
 	// #nosec G101: Potential hardcoded credentials (gosec)
 	// ZetaAccountingKey value is used as prefix for storing ZetaAccountingKey
 	ZetaAccountingKey = "ZetaAccounting-value-"
+
+	RateLimiterFlagsKey = "RateLimiterFlags-value-"
 )
 
 // OutTxTrackerKey returns the store key to retrieve a OutTxTracker from the index fields
diff --git a/x/crosschain/types/message_update_rate_limiter_flags.go b/x/crosschain/types/message_update_rate_limiter_flags.go
new file mode 100644
index 0000000000..85d3ccf7c4
--- /dev/null
+++ b/x/crosschain/types/message_update_rate_limiter_flags.go
@@ -0,0 +1,49 @@
+package types
+
+import (
+	errorsmod "cosmossdk.io/errors"
+	sdk "github.com/cosmos/cosmos-sdk/types"
+	sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
+)
+
+const TypeMsgUpdateRateLimiterFlags = "UpdateRateLimiterFlags"
+
+var _ sdk.Msg = &MsgUpdateRateLimiterFlags{}
+
+func NewMsgUpdateRateLimiterFlags(creator string, flags RateLimiterFlags) *MsgUpdateRateLimiterFlags {
+	return &MsgUpdateRateLimiterFlags{
+		Creator:          creator,
+		RateLimiterFlags: flags,
+	}
+}
+
+func (msg *MsgUpdateRateLimiterFlags) Route() string {
+	return RouterKey
+}
+
+func (msg *MsgUpdateRateLimiterFlags) Type() string {
+	return TypeMsgUpdateRateLimiterFlags
+}
+
+func (msg *MsgUpdateRateLimiterFlags) GetSigners() []sdk.AccAddress {
+	creator, err := sdk.AccAddressFromBech32(msg.Creator)
+	if err != nil {
+		panic(err)
+	}
+	return []sdk.AccAddress{creator}
+}
+
+func (msg *MsgUpdateRateLimiterFlags) GetSignBytes() []byte {
+	bz := ModuleCdc.MustMarshalJSON(msg)
+	return sdk.MustSortJSON(bz)
+}
+
+func (msg *MsgUpdateRateLimiterFlags) ValidateBasic() error {
+	if _, err := sdk.AccAddressFromBech32(msg.Creator); err != nil {
+		return errorsmod.Wrapf(sdkerrors.ErrInvalidAddress, "invalid creator address (%s)", err)
+	}
+	if err := msg.RateLimiterFlags.Validate(); err != nil {
+		return errorsmod.Wrapf(ErrInvalidRateLimiterFlags, err.Error())
+	}
+	return nil
+}
diff --git a/x/crosschain/types/message_update_rate_limiter_flags_test.go b/x/crosschain/types/message_update_rate_limiter_flags_test.go
new file mode 100644
index 0000000000..9a6f933a8b
--- /dev/null
+++ b/x/crosschain/types/message_update_rate_limiter_flags_test.go
@@ -0,0 +1,97 @@
+package types_test
+
+import (
+	"testing"
+
+	sdk "github.com/cosmos/cosmos-sdk/types"
+	sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
+	"github.com/stretchr/testify/require"
+	"github.com/zeta-chain/zetacore/testutil/sample"
+	"github.com/zeta-chain/zetacore/x/crosschain/types"
+)
+
+func TestMsgUpdateRateLimiterFlags_ValidateBasic(t *testing.T) {
+	tests := []struct {
+		name string
+		msg  *types.MsgUpdateRateLimiterFlags
+		err  error
+	}{
+		{
+			name: "valid message",
+			msg:  types.NewMsgUpdateRateLimiterFlags(sample.AccAddress(), sample.RateLimiterFlags()),
+		},
+		{
+			name: "invalid creator address",
+			msg:  types.NewMsgUpdateRateLimiterFlags("invalid", sample.RateLimiterFlags()),
+			err:  sdkerrors.ErrInvalidAddress,
+		},
+		{
+			name: "invalid rate limiter flags",
+			msg: types.NewMsgUpdateRateLimiterFlags(sample.AccAddress(), types.RateLimiterFlags{
+				Window: -1,
+			}),
+			err: types.ErrInvalidRateLimiterFlags,
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			err := tt.msg.ValidateBasic()
+			if tt.err != nil {
+				require.ErrorIs(t, err, tt.err)
+			} else {
+				require.NoError(t, err)
+			}
+		})
+	}
+}
+
+func TestMsgUpdateRateLimiterFlags_GetSigners(t *testing.T) {
+	signer := sample.AccAddress()
+	tests := []struct {
+		name   string
+		msg    *types.MsgUpdateRateLimiterFlags
+		panics bool
+	}{
+		{
+			name:   "valid signer",
+			msg:    types.NewMsgUpdateRateLimiterFlags(signer, sample.RateLimiterFlags()),
+			panics: false,
+		},
+		{
+			name:   "invalid signer",
+			msg:    types.NewMsgUpdateRateLimiterFlags("invalid", sample.RateLimiterFlags()),
+			panics: true,
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			if !tt.panics {
+				signers := tt.msg.GetSigners()
+				require.Equal(t, []sdk.AccAddress{sdk.MustAccAddressFromBech32(signer)}, signers)
+			} else {
+				require.Panics(t, func() {
+					tt.msg.GetSigners()
+				})
+			}
+		})
+	}
+}
+
+func TestMsgUpdateRateLimiterFlags_Type(t *testing.T) {
+	msg := types.NewMsgUpdateRateLimiterFlags(sample.AccAddress(), sample.RateLimiterFlags())
+	require.Equal(t, types.TypeMsgUpdateRateLimiterFlags, msg.Type())
+}
+
+func TestMsgUpdateRateLimiterFlags_Route(t *testing.T) {
+	msg := types.NewMsgUpdateRateLimiterFlags(sample.AccAddress(), sample.RateLimiterFlags())
+	require.Equal(t, types.RouterKey, msg.Route())
+}
+
+func TestMsgUpdateRateLimiterFlags_GetSignBytes(t *testing.T) {
+	msg := types.NewMsgUpdateRateLimiterFlags(sample.AccAddress(), sample.RateLimiterFlags())
+	require.NotPanics(t, func() {
+		msg.GetSignBytes()
+	})
+}
diff --git a/x/crosschain/types/query.pb.go b/x/crosschain/types/query.pb.go
index af554543a3..2add2ae2ae 100644
--- a/x/crosschain/types/query.pb.go
+++ b/x/crosschain/types/query.pb.go
@@ -1861,6 +1861,86 @@ func (m *QueryMessagePassingProtocolFeeResponse) GetFeeInZeta() string {
 	return ""
 }
 
+type QueryRateLimiterFlagsRequest struct {
+}
+
+func (m *QueryRateLimiterFlagsRequest) Reset()         { *m = QueryRateLimiterFlagsRequest{} }
+func (m *QueryRateLimiterFlagsRequest) String() string { return proto.CompactTextString(m) }
+func (*QueryRateLimiterFlagsRequest) ProtoMessage()    {}
+func (*QueryRateLimiterFlagsRequest) Descriptor() ([]byte, []int) {
+	return fileDescriptor_65a992045e92a606, []int{39}
+}
+func (m *QueryRateLimiterFlagsRequest) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *QueryRateLimiterFlagsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_QueryRateLimiterFlagsRequest.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 *QueryRateLimiterFlagsRequest) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_QueryRateLimiterFlagsRequest.Merge(m, src)
+}
+func (m *QueryRateLimiterFlagsRequest) XXX_Size() int {
+	return m.Size()
+}
+func (m *QueryRateLimiterFlagsRequest) XXX_DiscardUnknown() {
+	xxx_messageInfo_QueryRateLimiterFlagsRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_QueryRateLimiterFlagsRequest proto.InternalMessageInfo
+
+type QueryRateLimiterFlagsResponse struct {
+	RateLimiterFlags RateLimiterFlags `protobuf:"bytes,1,opt,name=rateLimiterFlags,proto3" json:"rateLimiterFlags"`
+}
+
+func (m *QueryRateLimiterFlagsResponse) Reset()         { *m = QueryRateLimiterFlagsResponse{} }
+func (m *QueryRateLimiterFlagsResponse) String() string { return proto.CompactTextString(m) }
+func (*QueryRateLimiterFlagsResponse) ProtoMessage()    {}
+func (*QueryRateLimiterFlagsResponse) Descriptor() ([]byte, []int) {
+	return fileDescriptor_65a992045e92a606, []int{40}
+}
+func (m *QueryRateLimiterFlagsResponse) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *QueryRateLimiterFlagsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_QueryRateLimiterFlagsResponse.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 *QueryRateLimiterFlagsResponse) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_QueryRateLimiterFlagsResponse.Merge(m, src)
+}
+func (m *QueryRateLimiterFlagsResponse) XXX_Size() int {
+	return m.Size()
+}
+func (m *QueryRateLimiterFlagsResponse) XXX_DiscardUnknown() {
+	xxx_messageInfo_QueryRateLimiterFlagsResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_QueryRateLimiterFlagsResponse proto.InternalMessageInfo
+
+func (m *QueryRateLimiterFlagsResponse) GetRateLimiterFlags() RateLimiterFlags {
+	if m != nil {
+		return m.RateLimiterFlags
+	}
+	return RateLimiterFlags{}
+}
+
 func init() {
 	proto.RegisterType((*QueryZetaAccountingRequest)(nil), "zetachain.zetacore.crosschain.QueryZetaAccountingRequest")
 	proto.RegisterType((*QueryZetaAccountingResponse)(nil), "zetachain.zetacore.crosschain.QueryZetaAccountingResponse")
@@ -1901,120 +1981,127 @@ func init() {
 	proto.RegisterType((*QueryConvertGasToZetaResponse)(nil), "zetachain.zetacore.crosschain.QueryConvertGasToZetaResponse")
 	proto.RegisterType((*QueryMessagePassingProtocolFeeRequest)(nil), "zetachain.zetacore.crosschain.QueryMessagePassingProtocolFeeRequest")
 	proto.RegisterType((*QueryMessagePassingProtocolFeeResponse)(nil), "zetachain.zetacore.crosschain.QueryMessagePassingProtocolFeeResponse")
+	proto.RegisterType((*QueryRateLimiterFlagsRequest)(nil), "zetachain.zetacore.crosschain.QueryRateLimiterFlagsRequest")
+	proto.RegisterType((*QueryRateLimiterFlagsResponse)(nil), "zetachain.zetacore.crosschain.QueryRateLimiterFlagsResponse")
 }
 
 func init() { proto.RegisterFile("crosschain/query.proto", fileDescriptor_65a992045e92a606) }
 
 var fileDescriptor_65a992045e92a606 = []byte{
-	// 1715 bytes of a gzipped FileDescriptorProto
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x59, 0xd1, 0x6f, 0x14, 0x45,
-	0x18, 0xef, 0xf4, 0x28, 0x94, 0x69, 0xa1, 0x32, 0x54, 0xac, 0x4b, 0x7b, 0x85, 0xad, 0xd0, 0x0a,
-	0xf6, 0x16, 0x0a, 0x14, 0x81, 0x62, 0xbc, 0x16, 0x29, 0xc4, 0x02, 0xf5, 0x52, 0xa3, 0xc1, 0x98,
-	0xcb, 0x74, 0x6f, 0xdd, 0xdb, 0xb0, 0xdd, 0x29, 0xb7, 0x7b, 0xa4, 0xa5, 0xe9, 0x0b, 0x0f, 0x3e,
-	0x9b, 0xf0, 0xe0, 0x8b, 0xaf, 0x46, 0x1f, 0x7c, 0xf0, 0xc1, 0xe8, 0x83, 0x09, 0xc6, 0xa8, 0xc8,
-	0x23, 0x89, 0x89, 0x31, 0x9a, 0x18, 0x03, 0xfe, 0x05, 0xfe, 0x05, 0x66, 0x67, 0xbf, 0xbd, 0x9b,
-	0xdd, 0xdb, 0xbd, 0x9b, 0x5e, 0x8f, 0x07, 0x9e, 0x7a, 0xbb, 0x33, 0xdf, 0x37, 0xbf, 0xdf, 0x6f,
-	0xbe, 0xf9, 0xf6, 0xfb, 0xa6, 0xf8, 0x80, 0x5e, 0x61, 0xae, 0xab, 0x97, 0xa9, 0xe5, 0x68, 0xb7,
-	0xab, 0x46, 0x65, 0x3d, 0xb7, 0x5a, 0x61, 0x1e, 0x23, 0x23, 0x77, 0x0d, 0x8f, 0xf2, 0xd7, 0x39,
-	0xfe, 0x8b, 0x55, 0x8c, 0x5c, 0x7d, 0xaa, 0x72, 0x4c, 0x67, 0xee, 0x0a, 0x73, 0xb5, 0x65, 0xea,
-	0x1a, 0x81, 0x9d, 0x76, 0xe7, 0xe4, 0xb2, 0xe1, 0xd1, 0x93, 0xda, 0x2a, 0x35, 0x2d, 0x87, 0x7a,
-	0x16, 0x73, 0x02, 0x57, 0xca, 0xa8, 0xb0, 0x04, 0xff, 0x59, 0xe4, 0xbf, 0x8b, 0xde, 0x1a, 0x4c,
-	0x50, 0x84, 0x09, 0x26, 0x75, 0x8b, 0xab, 0x15, 0x4b, 0x37, 0x60, 0x6c, 0x4c, 0x18, 0xe3, 0x36,
-	0xc5, 0x32, 0x75, 0xcb, 0x45, 0x8f, 0x15, 0x75, 0xbd, 0xe6, 0x20, 0xdb, 0x30, 0xc9, 0xab, 0x50,
-	0xfd, 0x96, 0x51, 0x81, 0x71, 0x55, 0x18, 0xb7, 0xa9, 0xeb, 0x15, 0x97, 0x6d, 0xa6, 0xdf, 0x2a,
-	0x96, 0x0d, 0xcb, 0x2c, 0x7b, 0x09, 0x28, 0x59, 0xd5, 0x6b, 0x74, 0x32, 0x68, 0x32, 0x93, 0xf1,
-	0x9f, 0x9a, 0xff, 0x0b, 0xde, 0x0e, 0x9b, 0x8c, 0x99, 0xb6, 0xa1, 0xd1, 0x55, 0x4b, 0xa3, 0x8e,
-	0xc3, 0x3c, 0xce, 0xdc, 0x0d, 0x46, 0xd5, 0x61, 0xac, 0xbc, 0xe3, 0x8b, 0x73, 0xd3, 0xf0, 0x68,
-	0x5e, 0xd7, 0x59, 0xd5, 0xf1, 0x2c, 0xc7, 0x2c, 0x18, 0xb7, 0xab, 0x86, 0xeb, 0xa9, 0xd7, 0xf0,
-	0xc1, 0xc4, 0x51, 0x77, 0x95, 0x39, 0xae, 0x41, 0x72, 0x78, 0x3f, 0x5d, 0x66, 0x15, 0xcf, 0x28,
-	0x15, 0xfd, 0x2d, 0x28, 0xd2, 0x15, 0x7f, 0xc6, 0x10, 0x3a, 0x84, 0x26, 0x76, 0x17, 0xf6, 0xc1,
-	0x10, 0xb7, 0xe5, 0x03, 0x35, 0x77, 0xf3, 0x86, 0x77, 0xa3, 0xea, 0x2d, 0xad, 0x2d, 0x05, 0xf0,
-	0x61, 0x35, 0x32, 0x84, 0x77, 0x71, 0x76, 0x57, 0x2f, 0x71, 0x17, 0x99, 0x42, 0xf8, 0x48, 0x06,
-	0x71, 0x8f, 0xc3, 0x1c, 0xdd, 0x18, 0xea, 0x3e, 0x84, 0x26, 0x76, 0x14, 0x82, 0x07, 0xb5, 0x8a,
-	0x87, 0x93, 0xdd, 0x01, 0xbc, 0x77, 0x71, 0x3f, 0x13, 0xde, 0x73, 0xa7, 0x7d, 0x53, 0xc7, 0x73,
-	0x4d, 0x03, 0x27, 0x27, 0xba, 0x9a, 0xdd, 0xf1, 0xe8, 0xef, 0xd1, 0xae, 0x42, 0xc4, 0x8d, 0x6a,
-	0x00, 0x8b, 0xbc, 0x6d, 0x27, 0xb1, 0xb8, 0x8c, 0x71, 0x3d, 0xc0, 0x60, 0xcd, 0xa3, 0xb9, 0x20,
-	0x1a, 0x73, 0x7e, 0x34, 0xe6, 0x82, 0x28, 0x86, 0x68, 0xcc, 0x2d, 0x52, 0xd3, 0x00, 0xdb, 0x82,
-	0x60, 0xa9, 0x3e, 0x40, 0x40, 0xaf, 0x61, 0x9d, 0x54, 0x7a, 0x99, 0x0e, 0xd0, 0x23, 0xf3, 0x11,
-	0xfc, 0xdd, 0x1c, 0xff, 0x78, 0x4b, 0xfc, 0x01, 0xa6, 0x08, 0x81, 0x7b, 0x08, 0xab, 0x49, 0x04,
-	0x66, 0xd7, 0xe7, 0x7c, 0x24, 0xa1, 0x5e, 0x83, 0xb8, 0x87, 0x23, 0x83, 0x3d, 0x0f, 0x1e, 0x62,
-	0x2a, 0x76, 0xb7, 0xad, 0xe2, 0x2f, 0x08, 0x8f, 0x35, 0x05, 0xf1, 0x9c, 0x88, 0xf9, 0x31, 0xc2,
-	0x87, 0x43, 0x1e, 0x57, 0x9d, 0x34, 0x2d, 0x5f, 0xc6, 0xbd, 0x41, 0xe6, 0xb2, 0x4a, 0xd1, 0x23,
-	0x54, 0xea, 0x98, 0xa0, 0x3f, 0x0a, 0xbb, 0x9a, 0x04, 0x04, 0xf4, 0x2c, 0xe0, 0x3e, 0xcb, 0x89,
-	0xcb, 0x79, 0xac, 0x85, 0x9c, 0xa2, 0xbf, 0x40, 0x4d, 0xd1, 0x49, 0xe7, 0xc4, 0x14, 0x4e, 0xb0,
-	0xb0, 0xa4, 0xdb, 0xe9, 0x13, 0xfc, 0xbd, 0x70, 0x82, 0xa3, 0xeb, 0x3c, 0x0f, 0x22, 0x5d, 0xc0,
-	0x23, 0x61, 0x76, 0xf5, 0x97, 0xbc, 0x42, 0xdd, 0xf2, 0x12, 0x9b, 0xd3, 0xbd, 0xb5, 0x50, 0x26,
-	0x05, 0xf7, 0x5a, 0x30, 0x00, 0x29, 0xbf, 0xf6, 0xac, 0x6e, 0xe2, 0x6c, 0x9a, 0x31, 0x70, 0xff,
-	0x00, 0xef, 0xb5, 0x22, 0x23, 0x20, 0xf4, 0xa4, 0x04, 0xfd, 0xba, 0x11, 0x28, 0x10, 0x73, 0xa5,
-	0xce, 0xc0, 0xf2, 0xd1, 0xc9, 0x97, 0xa8, 0x47, 0x65, 0xc0, 0xdf, 0xc5, 0xa3, 0xa9, 0xd6, 0x80,
-	0xfe, 0x3d, 0xbc, 0x67, 0xce, 0xc7, 0xc4, 0x83, 0x7e, 0x69, 0xcd, 0x95, 0xcc, 0x17, 0xa2, 0x0d,
-	0x40, 0x8f, 0xfa, 0x51, 0x4d, 0x50, 0x1d, 0x42, 0xa6, 0x51, 0xf5, 0x4e, 0x05, 0xe7, 0x43, 0x04,
-	0x1a, 0x25, 0xac, 0xd4, 0x64, 0x8b, 0x32, 0x1d, 0xda, 0xa2, 0xce, 0xc5, 0xa9, 0x86, 0x5f, 0x0a,
-	0x43, 0x6d, 0x9e, 0xba, 0x8b, 0x7e, 0x65, 0x26, 0x7c, 0x5a, 0x2c, 0xa7, 0x64, 0xac, 0xc1, 0x0e,
-	0x07, 0x0f, 0x6a, 0x11, 0x0f, 0x35, 0x1a, 0x00, 0xe5, 0x39, 0xdc, 0x1b, 0xbe, 0x03, 0x6d, 0xc7,
-	0x5b, 0x90, 0xad, 0xb9, 0xa8, 0x19, 0xaa, 0x14, 0x10, 0xe5, 0x6d, 0x3b, 0x8e, 0xa8, 0x53, 0xbb,
-	0xf7, 0x25, 0x02, 0x12, 0x91, 0x35, 0x12, 0x49, 0x64, 0xda, 0x22, 0xd1, 0xb9, 0xfd, 0x99, 0xae,
-	0xa7, 0x82, 0x05, 0xea, 0x7a, 0xb3, 0x7e, 0x61, 0x7b, 0x85, 0xd7, 0xb5, 0xcd, 0xb7, 0x69, 0x03,
-	0x4e, 0x61, 0x92, 0x1d, 0x10, 0x7d, 0x1f, 0x0f, 0xc4, 0x86, 0x40, 0xd2, 0x5c, 0x0b, 0xbe, 0x71,
-	0x87, 0x71, 0x37, 0x6a, 0xb9, 0x7e, 0x38, 0x52, 0x40, 0x77, 0x6a, 0x27, 0x7f, 0x46, 0xc0, 0x33,
-	0x69, 0xa9, 0x66, 0x3c, 0x33, 0x1d, 0xe0, 0xd9, 0xb9, 0x5d, 0x3e, 0x8e, 0xf7, 0x87, 0xbb, 0x25,
-	0x66, 0xab, 0xe4, 0xad, 0x5d, 0x80, 0xa6, 0x03, 0x26, 0xcf, 0xae, 0x5f, 0xf7, 0xeb, 0xf9, 0x76,
-	0xdb, 0x00, 0x13, 0x0f, 0x46, 0x97, 0x06, 0xd5, 0x6e, 0xe0, 0x7e, 0x31, 0xb7, 0x4a, 0x96, 0xff,
-	0xa2, 0x49, 0x21, 0xe2, 0x40, 0xfd, 0x10, 0x38, 0xe6, 0x6d, 0xfb, 0x59, 0x64, 0xe4, 0xaf, 0x11,
-	0x10, 0xa9, 0xf9, 0x4f, 0x25, 0x92, 0xd9, 0x16, 0x91, 0xce, 0xed, 0xfa, 0x75, 0x28, 0xa4, 0x16,
-	0x2c, 0x97, 0x6b, 0xbf, 0x68, 0x38, 0xa5, 0x7a, 0xfb, 0xd8, 0xac, 0x1c, 0x1d, 0xc4, 0x3d, 0xb6,
-	0xb5, 0x62, 0x79, 0x7c, 0xf5, 0x3d, 0x85, 0xe0, 0x41, 0xbd, 0x1f, 0x56, 0x4c, 0x0d, 0x0e, 0x9f,
-	0x95, 0x14, 0x2a, 0xee, 0xf7, 0x98, 0x47, 0x6d, 0x58, 0x08, 0x22, 0x2b, 0xf2, 0xae, 0xd6, 0x23,
-	0xfb, 0x87, 0xc7, 0xef, 0x66, 0x23, 0x89, 0x40, 0x3d, 0x13, 0x6a, 0x10, 0x1b, 0x05, 0xc4, 0x07,
-	0xf0, 0x4e, 0x21, 0x35, 0x65, 0x0a, 0xf0, 0xa4, 0x2e, 0x01, 0xd3, 0x39, 0xe6, 0xdc, 0x31, 0x2a,
-	0xfe, 0x97, 0x68, 0x89, 0xf9, 0xe6, 0x0d, 0xa7, 0xa0, 0x41, 0x3a, 0x05, 0xf7, 0x9a, 0xd4, 0x5d,
-	0xa8, 0xa9, 0xb7, 0xbb, 0x50, 0x7b, 0x56, 0x3f, 0x47, 0x50, 0x3f, 0x34, 0xba, 0x05, 0x3c, 0xaf,
-	0xe1, 0x7d, 0xac, 0xea, 0x2d, 0xb3, 0xaa, 0x53, 0x9a, 0xa7, 0xee, 0x55, 0xc7, 0x1f, 0x0c, 0x3b,
-	0xf6, 0x86, 0x01, 0x7f, 0x36, 0xbf, 0x27, 0xd0, 0x99, 0x7d, 0xd9, 0x30, 0x60, 0x76, 0xb0, 0x68,
-	0xe3, 0x00, 0x99, 0xc0, 0x03, 0xfe, 0x5f, 0x31, 0x4f, 0x65, 0xb8, 0x9e, 0xf1, 0xd7, 0xea, 0x38,
-	0x3e, 0xc2, 0x61, 0x5e, 0x33, 0x5c, 0x97, 0x9a, 0xc6, 0x22, 0x75, 0x5d, 0xcb, 0x31, 0x17, 0xeb,
-	0x1e, 0x43, 0x75, 0x2f, 0xe3, 0xa3, 0xad, 0x26, 0x02, 0xb1, 0x61, 0xbc, 0xfb, 0xa3, 0x1a, 0xc4,
-	0x80, 0x50, 0xfd, 0xc5, 0xd4, 0x7f, 0x23, 0xb8, 0x87, 0x3b, 0x22, 0x0f, 0x11, 0xee, 0x17, 0xfb,
-	0x36, 0x72, 0xbe, 0x45, 0xf4, 0x34, 0xb9, 0xb2, 0x50, 0x2e, 0xb4, 0x65, 0x1b, 0x20, 0x56, 0x2f,
-	0xde, 0xfb, 0xed, 0xdf, 0xfb, 0xdd, 0x67, 0xc9, 0x19, 0xcd, 0x37, 0x9d, 0x14, 0xee, 0x9f, 0x6a,
-	0x97, 0x3c, 0x35, 0x23, 0x6d, 0x03, 0x92, 0xe0, 0xa6, 0xb6, 0xc1, 0xd3, 0xde, 0x26, 0xf9, 0x0e,
-	0xe1, 0x01, 0xd1, 0x6f, 0xde, 0xb6, 0xe5, 0xb8, 0x24, 0x5f, 0x5c, 0xc8, 0x71, 0x49, 0xb9, 0x8c,
-	0x50, 0x8f, 0x73, 0x2e, 0x47, 0xc8, 0x98, 0x04, 0x17, 0xf2, 0x17, 0xc2, 0x07, 0x62, 0xc8, 0xa1,
-	0x7f, 0x24, 0xf9, 0x36, 0x40, 0x44, 0x9b, 0x60, 0x65, 0x76, 0x3b, 0x2e, 0x80, 0xce, 0x79, 0x4e,
-	0xe7, 0x34, 0x99, 0x92, 0xa0, 0x03, 0xb6, 0xb0, 0x43, 0x9b, 0xe4, 0x4f, 0x84, 0x5f, 0x14, 0x9a,
-	0x34, 0x81, 0xdc, 0x9b, 0x92, 0xc8, 0x52, 0x1b, 0x7c, 0x25, 0xbf, 0x0d, 0x0f, 0x40, 0x6d, 0x86,
-	0x53, 0x9b, 0x26, 0xa7, 0x53, 0xa8, 0x59, 0x4e, 0x0a, 0xb3, 0xa2, 0x55, 0xda, 0x24, 0xdf, 0x22,
-	0xbc, 0x37, 0x4a, 0x4e, 0x3a, 0xe6, 0x12, 0x5a, 0x6d, 0xe9, 0x98, 0x4b, 0x6a, 0x9f, 0x5b, 0xc6,
-	0x9c, 0xc0, 0xc4, 0x25, 0xbf, 0x02, 0x70, 0xa1, 0x05, 0x99, 0x91, 0x3c, 0xbc, 0x89, 0x8d, 0x98,
-	0x72, 0xb1, 0x4d, 0x6b, 0x00, 0xff, 0x3a, 0x07, 0x3f, 0x45, 0x4e, 0x34, 0x01, 0x5f, 0x37, 0xd3,
-	0x36, 0xc2, 0xe7, 0x4d, 0xf2, 0x3b, 0xc2, 0xa4, 0xb1, 0x35, 0x25, 0x52, 0x78, 0x52, 0x1b, 0x62,
-	0xe5, 0x8d, 0x76, 0xcd, 0x81, 0x4f, 0x9e, 0xf3, 0xb9, 0x40, 0xce, 0xa5, 0xf2, 0x89, 0x5f, 0x8d,
-	0x17, 0x4b, 0xd4, 0xa3, 0x22, 0xb1, 0x1f, 0x10, 0xde, 0x17, 0x5d, 0xc1, 0x0f, 0xaf, 0x99, 0x2d,
-	0x84, 0x48, 0x9b, 0xbb, 0x94, 0xda, 0x02, 0xab, 0x93, 0x9c, 0xd5, 0x38, 0x39, 0x22, 0xb5, 0x4b,
-	0xe4, 0x2b, 0x54, 0x6f, 0xbd, 0xc8, 0xb4, 0x64, 0x80, 0xc4, 0x7a, 0x44, 0xe5, 0xec, 0x96, 0xed,
-	0x00, 0xac, 0xc6, 0xc1, 0xbe, 0x4a, 0xc6, 0x53, 0xc0, 0x9a, 0x60, 0xe0, 0x6b, 0x5e, 0x32, 0xd6,
-	0x36, 0xc9, 0x17, 0x08, 0xf7, 0x85, 0x5e, 0x7c, 0xa9, 0xa7, 0x25, 0xc5, 0x6a, 0x0b, 0x71, 0x42,
-	0xa7, 0xaa, 0x8e, 0x73, 0xc4, 0x87, 0xc9, 0x68, 0x0b, 0xc4, 0xe4, 0x01, 0xc2, 0x2f, 0xc4, 0x4b,
-	0x1a, 0x22, 0x95, 0x3c, 0x52, 0xea, 0x2b, 0x65, 0xa6, 0x3d, 0x63, 0x49, 0xa9, 0xf5, 0x38, 0xd6,
-	0x87, 0x08, 0xf7, 0x09, 0x55, 0x0b, 0xb9, 0x24, 0xb3, 0x7c, 0xab, 0xea, 0x48, 0x79, 0x6b, 0x9b,
-	0x5e, 0x80, 0xcd, 0x31, 0xce, 0xe6, 0x15, 0xa2, 0xa6, 0xb0, 0x11, 0x2a, 0x3d, 0xf2, 0x08, 0x35,
-	0x34, 0xa3, 0x44, 0x36, 0x15, 0x26, 0xb7, 0xd2, 0x72, 0xa9, 0x27, 0xfd, 0x1a, 0x40, 0x9d, 0xe6,
-	0xf0, 0x4f, 0x90, 0x5c, 0x0a, 0x7c, 0x3b, 0x6a, 0x57, 0x0b, 0xff, 0x9f, 0x10, 0x26, 0x31, 0x9f,
-	0xfe, 0x29, 0x90, 0x4d, 0x19, 0xdb, 0x61, 0x93, 0xde, 0xec, 0xab, 0x39, 0xce, 0x66, 0x82, 0x1c,
-	0x95, 0x63, 0x43, 0x3e, 0x43, 0x78, 0x07, 0x4f, 0x3e, 0x53, 0x92, 0x32, 0x8a, 0xe9, 0xf1, 0xd4,
-	0x96, 0x6c, 0x24, 0xbf, 0xbb, 0x3a, 0x7c, 0xb0, 0xb8, 0xc8, 0xdf, 0x20, 0xdc, 0x27, 0x34, 0xf9,
-	0xe4, 0xdc, 0x16, 0x56, 0x8c, 0x5e, 0x0c, 0xb4, 0x07, 0xf6, 0x0c, 0x07, 0xab, 0x91, 0xc9, 0xa6,
-	0x60, 0x1b, 0x8a, 0xeb, 0x4f, 0x11, 0xde, 0x15, 0x7e, 0x81, 0xa6, 0x24, 0x77, 0x74, 0xcb, 0xc2,
-	0xc6, 0x1a, 0x7d, 0x75, 0x8c, 0x63, 0x1d, 0x21, 0x07, 0x9b, 0x60, 0xf5, 0x2b, 0xb0, 0x01, 0xdf,
-	0xca, 0x6f, 0x91, 0xa1, 0x43, 0x95, 0x2b, 0xc1, 0x92, 0x9b, 0x74, 0xb9, 0x12, 0x2c, 0xa5, 0x1f,
-	0x6f, 0x99, 0x39, 0xf4, 0xba, 0x0d, 0x2f, 0x1d, 0xa3, 0xff, 0x48, 0x96, 0x0b, 0x86, 0xc4, 0x7f,
-	0x4d, 0x2b, 0xe7, 0xdb, 0x31, 0x95, 0xfc, 0xaa, 0xdf, 0x8d, 0xa2, 0xf4, 0x81, 0x47, 0xbb, 0x7b,
-	0x39, 0xe0, 0x89, 0xf7, 0x05, 0x72, 0xc0, 0x93, 0x2f, 0x13, 0x5a, 0x02, 0xb7, 0x23, 0x66, 0xb3,
-	0x6f, 0x3f, 0x7a, 0x92, 0x45, 0x8f, 0x9f, 0x64, 0xd1, 0x3f, 0x4f, 0xb2, 0xe8, 0x93, 0xa7, 0xd9,
-	0xae, 0xc7, 0x4f, 0xb3, 0x5d, 0x7f, 0x3c, 0xcd, 0x76, 0xdd, 0x3c, 0x69, 0x5a, 0x5e, 0xb9, 0xba,
-	0x9c, 0xd3, 0xd9, 0x8a, 0xe8, 0x2a, 0xc4, 0xa3, 0xad, 0x89, 0x5e, 0xbd, 0xf5, 0x55, 0xc3, 0x5d,
-	0xde, 0xc9, 0xbf, 0x02, 0xa7, 0xfe, 0x0f, 0x00, 0x00, 0xff, 0xff, 0xda, 0xf6, 0xfb, 0xb3, 0x90,
-	0x21, 0x00, 0x00,
+	// 1796 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x59, 0xcf, 0x6f, 0x14, 0xc7,
+	0x12, 0x76, 0x7b, 0x31, 0x98, 0xb6, 0xc1, 0xd0, 0xf8, 0xf1, 0xfc, 0x16, 0x7b, 0x0d, 0xe3, 0x07,
+	0xf6, 0x83, 0xe7, 0x1d, 0x30, 0x60, 0x1e, 0x60, 0x9e, 0xb2, 0x36, 0xb1, 0x41, 0x31, 0xe0, 0xac,
+	0x1c, 0x25, 0x22, 0x8a, 0x56, 0xed, 0xd9, 0x66, 0x76, 0xc4, 0x78, 0xc6, 0xec, 0xcc, 0x22, 0x1b,
+	0xcb, 0x17, 0x0e, 0x39, 0x47, 0xe2, 0x90, 0x4b, 0xae, 0x51, 0x72, 0xc8, 0x21, 0x52, 0xa2, 0xe4,
+	0x10, 0x89, 0x28, 0x4a, 0x42, 0x38, 0x22, 0x45, 0x8a, 0xa2, 0x44, 0x8a, 0x22, 0xc8, 0x1f, 0x12,
+	0x4d, 0x4f, 0xcd, 0x6e, 0xcf, 0xaf, 0xdd, 0xf6, 0x7a, 0x39, 0x70, 0xf2, 0xf6, 0x74, 0x57, 0xf5,
+	0xf7, 0x55, 0x57, 0x57, 0x57, 0x95, 0xf1, 0x61, 0xad, 0x6a, 0x3b, 0x8e, 0x56, 0xa1, 0x86, 0xa5,
+	0xde, 0xab, 0xb1, 0xea, 0x46, 0x7e, 0xad, 0x6a, 0xbb, 0x36, 0x19, 0x79, 0xc0, 0x5c, 0xca, 0x3f,
+	0xe7, 0xf9, 0x2f, 0xbb, 0xca, 0xf2, 0x8d, 0xa5, 0xd9, 0x93, 0x9a, 0xed, 0xac, 0xda, 0x8e, 0xba,
+	0x42, 0x1d, 0xe6, 0xcb, 0xa9, 0xf7, 0xcf, 0xac, 0x30, 0x97, 0x9e, 0x51, 0xd7, 0xa8, 0x6e, 0x58,
+	0xd4, 0x35, 0x6c, 0xcb, 0x57, 0x95, 0x1d, 0x15, 0xb6, 0xe0, 0x3f, 0x4b, 0xfc, 0x77, 0xc9, 0x5d,
+	0x87, 0x05, 0x59, 0x61, 0x81, 0x4e, 0x9d, 0xd2, 0x5a, 0xd5, 0xd0, 0x18, 0xcc, 0x8d, 0x09, 0x73,
+	0x5c, 0xa6, 0x54, 0xa1, 0x4e, 0xa5, 0xe4, 0xda, 0x25, 0x4d, 0xab, 0x2b, 0xc8, 0xc5, 0x16, 0xb9,
+	0x55, 0xaa, 0xdd, 0x65, 0x55, 0x98, 0x57, 0x84, 0x79, 0x93, 0x3a, 0x6e, 0x69, 0xc5, 0xb4, 0xb5,
+	0xbb, 0xa5, 0x0a, 0x33, 0xf4, 0x8a, 0x9b, 0x80, 0xd2, 0xae, 0xb9, 0x71, 0x25, 0x22, 0x92, 0x2a,
+	0x75, 0x59, 0xc9, 0x34, 0x56, 0x0d, 0x97, 0x55, 0x4b, 0x77, 0x4c, 0xaa, 0x3b, 0xb0, 0x68, 0x50,
+	0xb7, 0x75, 0x9b, 0xff, 0x54, 0xbd, 0x5f, 0xf0, 0x75, 0x58, 0xb7, 0x6d, 0xdd, 0x64, 0x2a, 0x5d,
+	0x33, 0x54, 0x6a, 0x59, 0xb6, 0xcb, 0xcd, 0x03, 0x32, 0xca, 0x30, 0xce, 0xbe, 0xe9, 0x59, 0xf0,
+	0x36, 0x73, 0x69, 0x41, 0xd3, 0xec, 0x9a, 0xe5, 0x1a, 0x96, 0x5e, 0x64, 0xf7, 0x6a, 0xcc, 0x71,
+	0x95, 0x1b, 0xf8, 0x48, 0xe2, 0xac, 0xb3, 0x66, 0x5b, 0x0e, 0x23, 0x79, 0x7c, 0x88, 0xae, 0xd8,
+	0x55, 0x97, 0x95, 0x4b, 0xde, 0x39, 0x95, 0xe8, 0xaa, 0xb7, 0x62, 0x08, 0x1d, 0x45, 0x13, 0x7b,
+	0x8b, 0x07, 0x61, 0x8a, 0xcb, 0xf2, 0x89, 0xba, 0xba, 0x05, 0xe6, 0xde, 0xaa, 0xb9, 0xcb, 0xeb,
+	0xcb, 0x3e, 0x47, 0xd8, 0x8d, 0x0c, 0xe1, 0x3d, 0x9c, 0xe1, 0xf5, 0xab, 0x5c, 0x45, 0xa6, 0x18,
+	0x0c, 0xc9, 0x20, 0xee, 0xb1, 0x6c, 0x4b, 0x63, 0x43, 0xdd, 0x47, 0xd1, 0xc4, 0xae, 0xa2, 0x3f,
+	0x50, 0x6a, 0x78, 0x38, 0x59, 0x1d, 0xc0, 0x7b, 0x0b, 0xf7, 0xdb, 0xc2, 0x77, 0xae, 0xb4, 0x6f,
+	0xea, 0x54, 0xbe, 0xa9, 0x77, 0xe5, 0x45, 0x55, 0xb3, 0xbb, 0x9e, 0xfe, 0x31, 0xda, 0x55, 0x0c,
+	0xa9, 0x51, 0x18, 0xb0, 0x28, 0x98, 0x66, 0x12, 0x8b, 0x79, 0x8c, 0x1b, 0x5e, 0x08, 0x7b, 0x9e,
+	0xc8, 0xfb, 0x2e, 0x9b, 0xf7, 0x5c, 0x36, 0xef, 0xbb, 0x3a, 0xb8, 0x6c, 0x7e, 0x89, 0xea, 0x0c,
+	0x64, 0x8b, 0x82, 0xa4, 0xf2, 0x18, 0x01, 0xbd, 0xd8, 0x3e, 0xa9, 0xf4, 0x32, 0x1d, 0xa0, 0x47,
+	0x16, 0x42, 0xf8, 0xbb, 0x39, 0xfe, 0xf1, 0x96, 0xf8, 0x7d, 0x4c, 0x21, 0x02, 0x0f, 0x11, 0x56,
+	0x92, 0x08, 0xcc, 0x6e, 0xcc, 0x79, 0x48, 0x02, 0x7b, 0x0d, 0xe2, 0x1e, 0x8e, 0x0c, 0xce, 0xdc,
+	0x1f, 0x44, 0xac, 0xd8, 0xdd, 0xb6, 0x15, 0x7f, 0x44, 0x78, 0xac, 0x29, 0x88, 0x57, 0xc4, 0x98,
+	0xef, 0x23, 0x7c, 0x2c, 0xe0, 0x71, 0xdd, 0x4a, 0xb3, 0xe5, 0xbf, 0x70, 0xaf, 0x1f, 0xde, 0x8c,
+	0x72, 0xf8, 0x0a, 0x95, 0x3b, 0x66, 0xd0, 0xef, 0x84, 0x53, 0x4d, 0x02, 0x02, 0xf6, 0x2c, 0xe2,
+	0x3e, 0xc3, 0x8a, 0x9a, 0xf3, 0x64, 0x0b, 0x73, 0x8a, 0xfa, 0x7c, 0x6b, 0x8a, 0x4a, 0x3a, 0x67,
+	0x4c, 0xe1, 0x06, 0x0b, 0x5b, 0x3a, 0x9d, 0xbe, 0xc1, 0xdf, 0x08, 0x37, 0x38, 0xbc, 0xcf, 0xab,
+	0x60, 0xa4, 0xcb, 0x78, 0x24, 0x88, 0xae, 0xde, 0x96, 0xd7, 0xa8, 0x53, 0x59, 0xb6, 0xe7, 0x34,
+	0x77, 0x3d, 0x30, 0x53, 0x16, 0xf7, 0x1a, 0x30, 0x01, 0x21, 0xbf, 0x3e, 0x56, 0xb6, 0x70, 0x2e,
+	0x4d, 0x18, 0xb8, 0xbf, 0x8b, 0xf7, 0x1b, 0xa1, 0x19, 0x30, 0xf4, 0xa4, 0x04, 0xfd, 0x86, 0x10,
+	0x58, 0x20, 0xa2, 0x4a, 0x99, 0x81, 0xed, 0xc3, 0x8b, 0xaf, 0x52, 0x97, 0xca, 0x80, 0x7f, 0x80,
+	0x47, 0x53, 0xa5, 0x01, 0xfd, 0xdb, 0x78, 0xdf, 0x9c, 0x87, 0x89, 0x3b, 0xfd, 0xf2, 0xba, 0x23,
+	0x19, 0x2f, 0x44, 0x19, 0x80, 0x1e, 0xd6, 0xa3, 0xe8, 0x60, 0x75, 0x70, 0x99, 0xb8, 0xd5, 0x3b,
+	0xe5, 0x9c, 0x4f, 0x10, 0xd8, 0x28, 0x61, 0xa7, 0x26, 0x47, 0x94, 0xe9, 0xd0, 0x11, 0x75, 0xce,
+	0x4f, 0x55, 0xfc, 0xcf, 0xc0, 0xd5, 0x16, 0xa8, 0xb3, 0xe4, 0xa5, 0x6f, 0xc2, 0xd3, 0x62, 0x58,
+	0x65, 0xb6, 0x0e, 0x27, 0xec, 0x0f, 0x94, 0x12, 0x1e, 0x8a, 0x0b, 0x00, 0xe5, 0x39, 0xdc, 0x1b,
+	0x7c, 0x03, 0xdb, 0x8e, 0xb7, 0x20, 0x5b, 0x57, 0x51, 0x17, 0x54, 0x28, 0x20, 0x2a, 0x98, 0x66,
+	0x14, 0x51, 0xa7, 0x4e, 0xef, 0x53, 0x04, 0x24, 0x42, 0x7b, 0x24, 0x92, 0xc8, 0xb4, 0x45, 0xa2,
+	0x73, 0xe7, 0x33, 0xdd, 0x08, 0x05, 0x8b, 0xd4, 0x71, 0x67, 0xbd, 0xec, 0xf7, 0x1a, 0x4f, 0x7e,
+	0x9b, 0x1f, 0xd3, 0x26, 0xdc, 0xc2, 0x24, 0x39, 0x20, 0xfa, 0x0e, 0x1e, 0x88, 0x4c, 0x81, 0x49,
+	0xf3, 0x2d, 0xf8, 0x46, 0x15, 0x46, 0xd5, 0x28, 0x95, 0xc6, 0xe5, 0x48, 0x01, 0xdd, 0xa9, 0x93,
+	0xfc, 0x01, 0x01, 0xcf, 0xa4, 0xad, 0x9a, 0xf1, 0xcc, 0x74, 0x80, 0x67, 0xe7, 0x4e, 0xf9, 0x14,
+	0x3e, 0x14, 0x9c, 0x96, 0x18, 0xad, 0x92, 0x8f, 0x76, 0x11, 0x8a, 0x0e, 0x58, 0x3c, 0xbb, 0x71,
+	0xd3, 0xcb, 0xe7, 0xdb, 0x2d, 0x03, 0x74, 0x3c, 0x18, 0xde, 0x1a, 0xac, 0x76, 0x0b, 0xf7, 0x8b,
+	0xb1, 0x55, 0x32, 0xfd, 0x17, 0x45, 0x8a, 0x21, 0x05, 0xca, 0x7b, 0xc0, 0xb1, 0x60, 0x9a, 0x2f,
+	0x23, 0x22, 0x7f, 0x8e, 0x80, 0x48, 0x5d, 0x7f, 0x2a, 0x91, 0xcc, 0x8e, 0x88, 0x74, 0xee, 0xd4,
+	0x6f, 0x42, 0x22, 0xb5, 0x68, 0x38, 0xdc, 0xf6, 0x4b, 0xcc, 0x2a, 0x37, 0xca, 0xc7, 0x66, 0xe9,
+	0xe8, 0x20, 0xee, 0xe1, 0x25, 0x2c, 0xdf, 0x7d, 0x5f, 0xd1, 0x1f, 0x28, 0x8f, 0x82, 0x8c, 0x29,
+	0xa6, 0xf0, 0x65, 0x99, 0x42, 0xc1, 0xfd, 0xae, 0xed, 0x52, 0x13, 0x36, 0x02, 0xcf, 0x0a, 0x7d,
+	0xab, 0xd7, 0xc8, 0xde, 0xe5, 0xf1, 0xaa, 0xd9, 0x50, 0x20, 0x50, 0xce, 0x07, 0x36, 0x88, 0xcc,
+	0x02, 0xe2, 0xc3, 0x78, 0xb7, 0x10, 0x9a, 0x32, 0x45, 0x18, 0x29, 0xcb, 0xc0, 0x74, 0xce, 0xb6,
+	0xee, 0xb3, 0xaa, 0xf7, 0x12, 0x2d, 0xdb, 0x9e, 0x78, 0xec, 0x16, 0xc4, 0x4c, 0x97, 0xc5, 0xbd,
+	0x3a, 0x75, 0x16, 0xeb, 0xd6, 0xdb, 0x5b, 0xac, 0x8f, 0x95, 0x8f, 0x11, 0xe4, 0x0f, 0x71, 0xb5,
+	0x80, 0xe7, 0xbf, 0xf8, 0xa0, 0x5d, 0x73, 0x57, 0xec, 0x9a, 0x55, 0x5e, 0xa0, 0xce, 0x75, 0xcb,
+	0x9b, 0x0c, 0x2a, 0xf6, 0xd8, 0x84, 0xb7, 0x9a, 0xf7, 0x09, 0x34, 0xdb, 0x9c, 0x67, 0x0c, 0x56,
+	0xfb, 0x9b, 0xc6, 0x27, 0xc8, 0x04, 0x1e, 0xf0, 0xfe, 0x8a, 0x71, 0x2a, 0xc3, 0xed, 0x19, 0xfd,
+	0xac, 0x8c, 0xe3, 0xe3, 0x1c, 0xe6, 0x0d, 0xe6, 0x38, 0x54, 0x67, 0x4b, 0xd4, 0x71, 0x0c, 0x4b,
+	0x5f, 0x6a, 0x68, 0x0c, 0xac, 0x3b, 0x8f, 0x4f, 0xb4, 0x5a, 0x08, 0xc4, 0x86, 0xf1, 0xde, 0x3b,
+	0x75, 0x88, 0x3e, 0xa1, 0xc6, 0x07, 0x25, 0x07, 0xe6, 0x2e, 0x52, 0x97, 0x2d, 0xfa, 0xbd, 0x93,
+	0x79, 0x93, 0xea, 0x41, 0xce, 0xef, 0x15, 0xab, 0x23, 0x29, 0x0b, 0x40, 0x3f, 0xc5, 0x07, 0xaa,
+	0x91, 0x39, 0xb8, 0xec, 0x6a, 0x0b, 0xf7, 0x8b, 0xaa, 0x84, 0x8c, 0x28, 0xa6, 0x6e, 0xea, 0x8b,
+	0x51, 0xdc, 0xc3, 0x41, 0x90, 0x27, 0x08, 0xf7, 0x8b, 0xc5, 0x25, 0xb9, 0xd4, 0x62, 0x8f, 0x26,
+	0x7d, 0x95, 0xec, 0xe5, 0xb6, 0x64, 0x7d, 0xda, 0xca, 0x95, 0x87, 0x3f, 0xff, 0xf5, 0xa8, 0xfb,
+	0x02, 0x39, 0xaf, 0x7a, 0xa2, 0x93, 0x42, 0x27, 0xad, 0xde, 0xae, 0xaa, 0x0b, 0xa9, 0x9b, 0x10,
+	0xa9, 0xb7, 0xd4, 0x4d, 0x1e, 0x9b, 0xb7, 0xc8, 0xd7, 0x08, 0x0f, 0x88, 0x7a, 0x0b, 0xa6, 0x29,
+	0xc7, 0x25, 0xb9, 0xbb, 0x22, 0xc7, 0x25, 0xa5, 0x63, 0xa2, 0x9c, 0xe2, 0x5c, 0x8e, 0x93, 0x31,
+	0x09, 0x2e, 0xe4, 0x77, 0x84, 0x0f, 0x47, 0x90, 0x43, 0x91, 0x4b, 0x0a, 0x6d, 0x80, 0x08, 0x57,
+	0xea, 0xd9, 0xd9, 0x9d, 0xa8, 0x00, 0x3a, 0x97, 0x38, 0x9d, 0x73, 0x64, 0x4a, 0x82, 0x0e, 0xc8,
+	0xc2, 0x09, 0x6d, 0x91, 0xdf, 0x10, 0xfe, 0x87, 0x50, 0x49, 0x0a, 0xe4, 0x5e, 0x93, 0x44, 0x96,
+	0xda, 0x85, 0xc8, 0x16, 0x76, 0xa0, 0x01, 0xa8, 0xcd, 0x70, 0x6a, 0xd3, 0xe4, 0x5c, 0x0a, 0x35,
+	0xc3, 0x4a, 0x61, 0x56, 0x32, 0xca, 0x5b, 0xe4, 0x2b, 0x84, 0xf7, 0x87, 0xc9, 0x49, 0xfb, 0x5c,
+	0x42, 0x3f, 0x40, 0xda, 0xe7, 0x92, 0x6a, 0xfc, 0x96, 0x3e, 0x27, 0x30, 0x71, 0xc8, 0x4f, 0x00,
+	0x5c, 0xa8, 0x93, 0x66, 0x24, 0x2f, 0x6f, 0x62, 0xb5, 0x98, 0xbd, 0xd2, 0xa6, 0x34, 0x80, 0xff,
+	0x1f, 0x07, 0x3f, 0x45, 0x4e, 0x37, 0x01, 0xdf, 0x10, 0x53, 0x37, 0x83, 0xf1, 0x16, 0xf9, 0x05,
+	0x61, 0x12, 0xaf, 0x9f, 0x89, 0x14, 0x9e, 0xd4, 0xaa, 0x3d, 0xfb, 0xff, 0x76, 0xc5, 0x81, 0x4f,
+	0x81, 0xf3, 0xb9, 0x4c, 0x2e, 0xa6, 0xf2, 0x89, 0x36, 0xf9, 0x4b, 0x65, 0xea, 0x52, 0x91, 0xd8,
+	0xb7, 0x08, 0x1f, 0x0c, 0xef, 0xe0, 0xb9, 0xd7, 0xcc, 0x36, 0x5c, 0xa4, 0xcd, 0x53, 0x4a, 0xad,
+	0xd3, 0x95, 0x49, 0xce, 0x6a, 0x9c, 0x1c, 0x97, 0x3a, 0x25, 0xf2, 0x19, 0x6a, 0xd4, 0x87, 0x64,
+	0x5a, 0xd2, 0x41, 0x22, 0x85, 0x6c, 0xf6, 0xc2, 0xb6, 0xe5, 0x00, 0xac, 0xca, 0xc1, 0xfe, 0x87,
+	0x8c, 0xa7, 0x80, 0xd5, 0x41, 0xc0, 0xb3, 0x79, 0x99, 0xad, 0x6f, 0x91, 0x4f, 0x10, 0xee, 0x0b,
+	0xb4, 0x78, 0xa6, 0x9e, 0x96, 0x34, 0x56, 0x5b, 0x88, 0x13, 0xca, 0x69, 0x65, 0x9c, 0x23, 0x3e,
+	0x46, 0x46, 0x5b, 0x20, 0x26, 0x8f, 0x11, 0x3e, 0x10, 0xcd, 0xbb, 0x88, 0x54, 0xf0, 0x48, 0x49,
+	0x02, 0xb3, 0x33, 0xed, 0x09, 0x4b, 0x9a, 0x5a, 0x8b, 0x62, 0x7d, 0x82, 0x70, 0x9f, 0x90, 0x5a,
+	0x91, 0xab, 0x32, 0xdb, 0xb7, 0x4a, 0xe1, 0xb2, 0xaf, 0xef, 0x50, 0x0b, 0xb0, 0x39, 0xc9, 0xd9,
+	0xfc, 0x9b, 0x28, 0x29, 0x6c, 0x84, 0x74, 0x94, 0x3c, 0x45, 0xb1, 0x8a, 0x99, 0xc8, 0x86, 0xc2,
+	0xe4, 0x7a, 0x5f, 0x2e, 0xf4, 0xa4, 0xf7, 0x2a, 0x94, 0x69, 0x0e, 0xff, 0x34, 0xc9, 0xa7, 0xc0,
+	0x37, 0xc3, 0x72, 0x75, 0xf7, 0xff, 0x1e, 0x61, 0x12, 0xd1, 0xe9, 0xdd, 0x02, 0xd9, 0x90, 0xb1,
+	0x13, 0x36, 0xe9, 0x1d, 0x09, 0x25, 0xcf, 0xd9, 0x4c, 0x90, 0x13, 0x72, 0x6c, 0xc8, 0x47, 0x08,
+	0xef, 0xe2, 0xc1, 0x67, 0x4a, 0xd2, 0x8c, 0x62, 0x78, 0x3c, 0xbb, 0x2d, 0x19, 0xc9, 0x77, 0x57,
+	0x83, 0x07, 0x8b, 0x1b, 0xf9, 0x4b, 0x84, 0xfb, 0x84, 0x4e, 0x04, 0xb9, 0xb8, 0x8d, 0x1d, 0xc3,
+	0xdd, 0x8b, 0xf6, 0xc0, 0x9e, 0xe7, 0x60, 0x55, 0x32, 0xd9, 0x14, 0x6c, 0x2c, 0xb9, 0xfe, 0x10,
+	0xe1, 0x3d, 0xc1, 0x0b, 0x34, 0x25, 0x79, 0xa2, 0xdb, 0x36, 0x6c, 0xa4, 0x1b, 0xa1, 0x8c, 0x71,
+	0xac, 0x23, 0xe4, 0x48, 0x13, 0xac, 0x5e, 0x06, 0x36, 0xe0, 0x49, 0x79, 0x75, 0x3c, 0x94, 0xd1,
+	0x72, 0x29, 0x58, 0x72, 0x27, 0x41, 0x2e, 0x05, 0x4b, 0x69, 0x1a, 0xb4, 0x8c, 0x1c, 0x5a, 0x43,
+	0x86, 0xa7, 0x8e, 0xe1, 0xff, 0x76, 0xcb, 0x39, 0x43, 0xe2, 0xff, 0xcf, 0xb3, 0x97, 0xda, 0x11,
+	0x95, 0x7c, 0xd5, 0x1f, 0x84, 0x51, 0x7a, 0xc0, 0xc3, 0x2d, 0x08, 0x39, 0xe0, 0x89, 0x4d, 0x0d,
+	0x39, 0xe0, 0xc9, 0x1d, 0x8f, 0x96, 0xc0, 0xcd, 0x30, 0x4a, 0xef, 0xd5, 0x8c, 0x56, 0xc8, 0x72,
+	0xaf, 0x66, 0x4a, 0x2d, 0x2f, 0xf7, 0x6a, 0xa6, 0xd5, 0xf9, 0x2d, 0x5f, 0xcd, 0x68, 0xd5, 0x3e,
+	0xfb, 0xc6, 0xd3, 0xe7, 0x39, 0xf4, 0xec, 0x79, 0x0e, 0xfd, 0xf9, 0x3c, 0x87, 0x3e, 0x78, 0x91,
+	0xeb, 0x7a, 0xf6, 0x22, 0xd7, 0xf5, 0xeb, 0x8b, 0x5c, 0xd7, 0xed, 0x33, 0xba, 0xe1, 0x56, 0x6a,
+	0x2b, 0x79, 0xcd, 0x5e, 0x15, 0x95, 0x05, 0x98, 0xd4, 0x75, 0x51, 0xaf, 0xbb, 0xb1, 0xc6, 0x9c,
+	0x95, 0xdd, 0xfc, 0x19, 0x3b, 0xfb, 0x77, 0x00, 0x00, 0x00, 0xff, 0xff, 0xe2, 0x51, 0x5a, 0xb9,
+	0x1b, 0x23, 0x00, 0x00,
 }
 
 // Reference imports to suppress errors if they are not otherwise used.
@@ -2063,6 +2150,8 @@ type QueryClient interface {
 	ZetaAccounting(ctx context.Context, in *QueryZetaAccountingRequest, opts ...grpc.CallOption) (*QueryZetaAccountingResponse, error)
 	// Queries a list of lastMetaHeight items.
 	LastZetaHeight(ctx context.Context, in *QueryLastZetaHeightRequest, opts ...grpc.CallOption) (*QueryLastZetaHeightResponse, error)
+	// Queries the rate limiter flags
+	RateLimiterFlags(ctx context.Context, in *QueryRateLimiterFlagsRequest, opts ...grpc.CallOption) (*QueryRateLimiterFlagsResponse, error)
 }
 
 type queryClient struct {
@@ -2253,6 +2342,15 @@ func (c *queryClient) LastZetaHeight(ctx context.Context, in *QueryLastZetaHeigh
 	return out, nil
 }
 
+func (c *queryClient) RateLimiterFlags(ctx context.Context, in *QueryRateLimiterFlagsRequest, opts ...grpc.CallOption) (*QueryRateLimiterFlagsResponse, error) {
+	out := new(QueryRateLimiterFlagsResponse)
+	err := c.cc.Invoke(ctx, "/zetachain.zetacore.crosschain.Query/RateLimiterFlags", in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
 // QueryServer is the server API for Query service.
 type QueryServer interface {
 	// Queries a OutTxTracker by index.
@@ -2289,6 +2387,8 @@ type QueryServer interface {
 	ZetaAccounting(context.Context, *QueryZetaAccountingRequest) (*QueryZetaAccountingResponse, error)
 	// Queries a list of lastMetaHeight items.
 	LastZetaHeight(context.Context, *QueryLastZetaHeightRequest) (*QueryLastZetaHeightResponse, error)
+	// Queries the rate limiter flags
+	RateLimiterFlags(context.Context, *QueryRateLimiterFlagsRequest) (*QueryRateLimiterFlagsResponse, error)
 }
 
 // UnimplementedQueryServer can be embedded to have forward compatible implementations.
@@ -2355,6 +2455,9 @@ func (*UnimplementedQueryServer) ZetaAccounting(ctx context.Context, req *QueryZ
 func (*UnimplementedQueryServer) LastZetaHeight(ctx context.Context, req *QueryLastZetaHeightRequest) (*QueryLastZetaHeightResponse, error) {
 	return nil, status.Errorf(codes.Unimplemented, "method LastZetaHeight not implemented")
 }
+func (*UnimplementedQueryServer) RateLimiterFlags(ctx context.Context, req *QueryRateLimiterFlagsRequest) (*QueryRateLimiterFlagsResponse, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method RateLimiterFlags not implemented")
+}
 
 func RegisterQueryServer(s grpc1.Server, srv QueryServer) {
 	s.RegisterService(&_Query_serviceDesc, srv)
@@ -2720,6 +2823,24 @@ func _Query_LastZetaHeight_Handler(srv interface{}, ctx context.Context, dec fun
 	return interceptor(ctx, in, info, handler)
 }
 
+func _Query_RateLimiterFlags_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(QueryRateLimiterFlagsRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(QueryServer).RateLimiterFlags(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/zetachain.zetacore.crosschain.Query/RateLimiterFlags",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(QueryServer).RateLimiterFlags(ctx, req.(*QueryRateLimiterFlagsRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
 var _Query_serviceDesc = grpc.ServiceDesc{
 	ServiceName: "zetachain.zetacore.crosschain.Query",
 	HandlerType: (*QueryServer)(nil),
@@ -2804,6 +2925,10 @@ var _Query_serviceDesc = grpc.ServiceDesc{
 			MethodName: "LastZetaHeight",
 			Handler:    _Query_LastZetaHeight_Handler,
 		},
+		{
+			MethodName: "RateLimiterFlags",
+			Handler:    _Query_RateLimiterFlags_Handler,
+		},
 	},
 	Streams:  []grpc.StreamDesc{},
 	Metadata: "crosschain/query.proto",
@@ -4224,6 +4349,62 @@ func (m *QueryMessagePassingProtocolFeeResponse) MarshalToSizedBuffer(dAtA []byt
 	return len(dAtA) - i, nil
 }
 
+func (m *QueryRateLimiterFlagsRequest) 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 *QueryRateLimiterFlagsRequest) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *QueryRateLimiterFlagsRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	return len(dAtA) - i, nil
+}
+
+func (m *QueryRateLimiterFlagsResponse) 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 *QueryRateLimiterFlagsResponse) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *QueryRateLimiterFlagsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	{
+		size, err := m.RateLimiterFlags.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
@@ -4802,6 +4983,26 @@ func (m *QueryMessagePassingProtocolFeeResponse) Size() (n int) {
 	return n
 }
 
+func (m *QueryRateLimiterFlagsRequest) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	return n
+}
+
+func (m *QueryRateLimiterFlagsResponse) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	l = m.RateLimiterFlags.Size()
+	n += 1 + l + sovQuery(uint64(l))
+	return n
+}
+
 func sovQuery(x uint64) (n int) {
 	return (math_bits.Len64(x|1) + 6) / 7
 }
@@ -8396,6 +8597,139 @@ func (m *QueryMessagePassingProtocolFeeResponse) Unmarshal(dAtA []byte) error {
 	}
 	return nil
 }
+func (m *QueryRateLimiterFlagsRequest) 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: QueryRateLimiterFlagsRequest: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: QueryRateLimiterFlagsRequest: 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 *QueryRateLimiterFlagsResponse) 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: QueryRateLimiterFlagsResponse: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: QueryRateLimiterFlagsResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field RateLimiterFlags", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowQuery
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthQuery
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthQuery
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if err := m.RateLimiterFlags.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
diff --git a/x/crosschain/types/query.pb.gw.go b/x/crosschain/types/query.pb.gw.go
index 6234a732ea..e25a590184 100644
--- a/x/crosschain/types/query.pb.gw.go
+++ b/x/crosschain/types/query.pb.gw.go
@@ -941,6 +941,24 @@ func local_request_Query_LastZetaHeight_0(ctx context.Context, marshaler runtime
 
 }
 
+func request_Query_RateLimiterFlags_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+	var protoReq QueryRateLimiterFlagsRequest
+	var metadata runtime.ServerMetadata
+
+	msg, err := client.RateLimiterFlags(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+	return msg, metadata, err
+
+}
+
+func local_request_Query_RateLimiterFlags_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+	var protoReq QueryRateLimiterFlagsRequest
+	var metadata runtime.ServerMetadata
+
+	msg, err := server.RateLimiterFlags(ctx, &protoReq)
+	return msg, metadata, err
+
+}
+
 // RegisterQueryHandlerServer registers the http handlers for service Query to "mux".
 // UnaryRPC     :call QueryServer directly.
 // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
@@ -1407,6 +1425,29 @@ func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv
 
 	})
 
+	mux.Handle("GET", pattern_Query_RateLimiterFlags_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+		ctx, cancel := context.WithCancel(req.Context())
+		defer cancel()
+		var stream runtime.ServerTransportStream
+		ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
+		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+		rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+		if err != nil {
+			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+			return
+		}
+		resp, md, err := local_request_Query_RateLimiterFlags_0(rctx, inboundMarshaler, server, req, pathParams)
+		md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
+		ctx = runtime.NewServerMetadataContext(ctx, md)
+		if err != nil {
+			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+			return
+		}
+
+		forward_Query_RateLimiterFlags_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+	})
+
 	return nil
 }
 
@@ -1848,6 +1889,26 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie
 
 	})
 
+	mux.Handle("GET", pattern_Query_RateLimiterFlags_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+		ctx, cancel := context.WithCancel(req.Context())
+		defer cancel()
+		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+		rctx, err := runtime.AnnotateContext(ctx, mux, req)
+		if err != nil {
+			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+			return
+		}
+		resp, md, err := request_Query_RateLimiterFlags_0(rctx, inboundMarshaler, client, req, pathParams)
+		ctx = runtime.NewServerMetadataContext(ctx, md)
+		if err != nil {
+			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+			return
+		}
+
+		forward_Query_RateLimiterFlags_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+	})
+
 	return nil
 }
 
@@ -1891,6 +1952,8 @@ var (
 	pattern_Query_ZetaAccounting_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"zeta-chain", "crosschain", "zetaAccounting"}, "", runtime.AssumeColonVerbOpt(false)))
 
 	pattern_Query_LastZetaHeight_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"zeta-chain", "crosschain", "lastZetaHeight"}, "", runtime.AssumeColonVerbOpt(false)))
+
+	pattern_Query_RateLimiterFlags_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"zeta-chain", "crosschain", "rateLimiterFlags"}, "", runtime.AssumeColonVerbOpt(false)))
 )
 
 var (
@@ -1933,4 +1996,6 @@ var (
 	forward_Query_ZetaAccounting_0 = runtime.ForwardResponseMessage
 
 	forward_Query_LastZetaHeight_0 = runtime.ForwardResponseMessage
+
+	forward_Query_RateLimiterFlags_0 = runtime.ForwardResponseMessage
 )
diff --git a/x/crosschain/types/rate_limiter_flags.go b/x/crosschain/types/rate_limiter_flags.go
new file mode 100644
index 0000000000..93a9617961
--- /dev/null
+++ b/x/crosschain/types/rate_limiter_flags.go
@@ -0,0 +1,47 @@
+package types
+
+import (
+	"fmt"
+
+	sdk "github.com/cosmos/cosmos-sdk/types"
+	ethcommon "github.com/ethereum/go-ethereum/common"
+)
+
+// Validate checks that the RateLimiterFlags is valid
+func (r RateLimiterFlags) Validate() error {
+	// window must not be negative
+	if r.Window < 0 {
+		return fmt.Errorf("window must be positive: %d", r.Window)
+	}
+
+	seen := make(map[string]bool)
+	for _, conversion := range r.Conversions {
+		// check no duplicated conversion
+		if _, ok := seen[conversion.Zrc20]; ok {
+			return fmt.Errorf("duplicated conversion: %s", conversion.Zrc20)
+		}
+		seen[conversion.Zrc20] = true
+
+		// check conversion is valid
+		if conversion.Rate.IsNil() {
+			return fmt.Errorf("rate is nil for conversion: %s", conversion.Zrc20)
+		}
+
+		// check address is valid
+		if !ethcommon.IsHexAddress(conversion.Zrc20) {
+			return fmt.Errorf("invalid zrc20 address (%s)", conversion.Zrc20)
+		}
+	}
+
+	return nil
+}
+
+// GetConversionRate returns the conversion rate for the given zrc20
+func (r RateLimiterFlags) GetConversionRate(zrc20 string) (sdk.Dec, bool) {
+	for _, conversion := range r.Conversions {
+		if conversion.Zrc20 == zrc20 {
+			return conversion.Rate, true
+		}
+	}
+	return sdk.NewDec(0), false
+}
diff --git a/x/crosschain/types/rate_limiter_flags.pb.go b/x/crosschain/types/rate_limiter_flags.pb.go
new file mode 100644
index 0000000000..899a1d7099
--- /dev/null
+++ b/x/crosschain/types/rate_limiter_flags.pb.go
@@ -0,0 +1,684 @@
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: crosschain/rate_limiter_flags.proto
+
+package types
+
+import (
+	fmt "fmt"
+	io "io"
+	math "math"
+	math_bits "math/bits"
+
+	github_com_cosmos_cosmos_sdk_types "github.com/cosmos/cosmos-sdk/types"
+	_ "github.com/cosmos/gogoproto/gogoproto"
+	proto "github.com/gogo/protobuf/proto"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
+
+type RateLimiterFlags struct {
+	Enabled bool `protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled,omitempty"`
+	// window in blocks
+	Window int64 `protobuf:"varint,2,opt,name=window,proto3" json:"window,omitempty"`
+	// rate in azeta per block
+	Rate github_com_cosmos_cosmos_sdk_types.Uint `protobuf:"bytes,3,opt,name=rate,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Uint" json:"rate"`
+	// conversion in azeta per token
+	Conversions []Conversion `protobuf:"bytes,4,rep,name=conversions,proto3" json:"conversions"`
+}
+
+func (m *RateLimiterFlags) Reset()         { *m = RateLimiterFlags{} }
+func (m *RateLimiterFlags) String() string { return proto.CompactTextString(m) }
+func (*RateLimiterFlags) ProtoMessage()    {}
+func (*RateLimiterFlags) Descriptor() ([]byte, []int) {
+	return fileDescriptor_b17ae80d5af4e97e, []int{0}
+}
+func (m *RateLimiterFlags) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *RateLimiterFlags) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_RateLimiterFlags.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 *RateLimiterFlags) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_RateLimiterFlags.Merge(m, src)
+}
+func (m *RateLimiterFlags) XXX_Size() int {
+	return m.Size()
+}
+func (m *RateLimiterFlags) XXX_DiscardUnknown() {
+	xxx_messageInfo_RateLimiterFlags.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_RateLimiterFlags proto.InternalMessageInfo
+
+func (m *RateLimiterFlags) GetEnabled() bool {
+	if m != nil {
+		return m.Enabled
+	}
+	return false
+}
+
+func (m *RateLimiterFlags) GetWindow() int64 {
+	if m != nil {
+		return m.Window
+	}
+	return 0
+}
+
+func (m *RateLimiterFlags) GetConversions() []Conversion {
+	if m != nil {
+		return m.Conversions
+	}
+	return nil
+}
+
+type Conversion struct {
+	Zrc20 string                                 `protobuf:"bytes,1,opt,name=zrc20,proto3" json:"zrc20,omitempty"`
+	Rate  github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,2,opt,name=rate,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"rate"`
+}
+
+func (m *Conversion) Reset()         { *m = Conversion{} }
+func (m *Conversion) String() string { return proto.CompactTextString(m) }
+func (*Conversion) ProtoMessage()    {}
+func (*Conversion) Descriptor() ([]byte, []int) {
+	return fileDescriptor_b17ae80d5af4e97e, []int{1}
+}
+func (m *Conversion) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *Conversion) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_Conversion.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 *Conversion) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_Conversion.Merge(m, src)
+}
+func (m *Conversion) XXX_Size() int {
+	return m.Size()
+}
+func (m *Conversion) XXX_DiscardUnknown() {
+	xxx_messageInfo_Conversion.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Conversion proto.InternalMessageInfo
+
+func (m *Conversion) GetZrc20() string {
+	if m != nil {
+		return m.Zrc20
+	}
+	return ""
+}
+
+func init() {
+	proto.RegisterType((*RateLimiterFlags)(nil), "zetachain.zetacore.crosschain.RateLimiterFlags")
+	proto.RegisterType((*Conversion)(nil), "zetachain.zetacore.crosschain.Conversion")
+}
+
+func init() {
+	proto.RegisterFile("crosschain/rate_limiter_flags.proto", fileDescriptor_b17ae80d5af4e97e)
+}
+
+var fileDescriptor_b17ae80d5af4e97e = []byte{
+	// 331 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x91, 0xc1, 0x4e, 0x32, 0x31,
+	0x14, 0x85, 0xa7, 0xc0, 0xcf, 0x2f, 0x65, 0x63, 0x1a, 0x62, 0x26, 0x26, 0x0e, 0x13, 0x4c, 0x74,
+	0x5c, 0xd0, 0x2a, 0xbe, 0xc1, 0x60, 0xdc, 0xe8, 0xc6, 0x49, 0xdc, 0xb8, 0x21, 0x43, 0x29, 0x43,
+	0x23, 0xb4, 0xa4, 0xad, 0xa2, 0x3c, 0x85, 0x8f, 0xc5, 0x92, 0xa5, 0x31, 0x86, 0x18, 0x78, 0x11,
+	0x33, 0x9d, 0x41, 0x66, 0x65, 0x5c, 0xf5, 0xde, 0xe4, 0x9e, 0xd3, 0xef, 0xe4, 0xc0, 0x63, 0xaa,
+	0xa4, 0xd6, 0x74, 0x14, 0x73, 0x41, 0x54, 0x6c, 0x58, 0x6f, 0xcc, 0x27, 0xdc, 0x30, 0xd5, 0x1b,
+	0x8e, 0xe3, 0x44, 0xe3, 0xa9, 0x92, 0x46, 0xa2, 0xa3, 0x39, 0x33, 0xb1, 0xbd, 0xc1, 0x76, 0x92,
+	0x8a, 0xe1, 0x9d, 0xee, 0xb0, 0x91, 0xc8, 0x44, 0xda, 0x4b, 0x92, 0x4e, 0x99, 0xa8, 0xf5, 0x09,
+	0xe0, 0x7e, 0x14, 0x1b, 0x76, 0x9b, 0x19, 0x5e, 0xa7, 0x7e, 0xc8, 0x85, 0xff, 0x99, 0x88, 0xfb,
+	0x63, 0x36, 0x70, 0x81, 0x0f, 0x82, 0xbd, 0x68, 0xbb, 0xa2, 0x03, 0x58, 0x9d, 0x71, 0x31, 0x90,
+	0x33, 0xb7, 0xe4, 0x83, 0xa0, 0x1c, 0xe5, 0x1b, 0xea, 0xc2, 0x4a, 0xca, 0xe5, 0x96, 0x7d, 0x10,
+	0xd4, 0x42, 0xb2, 0x58, 0x35, 0x9d, 0x8f, 0x55, 0xf3, 0x34, 0xe1, 0x66, 0xf4, 0xd4, 0xc7, 0x54,
+	0x4e, 0x08, 0x95, 0x7a, 0x22, 0x75, 0xfe, 0xb4, 0xf5, 0xe0, 0x91, 0x98, 0xd7, 0x29, 0xd3, 0xf8,
+	0x9e, 0x0b, 0x13, 0x59, 0x31, 0xba, 0x83, 0x75, 0x2a, 0xc5, 0x33, 0x53, 0x9a, 0x4b, 0xa1, 0xdd,
+	0x8a, 0x5f, 0x0e, 0xea, 0x9d, 0x33, 0xfc, 0x6b, 0x2c, 0xdc, 0xfd, 0x51, 0x84, 0x95, 0xf4, 0xdb,
+	0xa8, 0xe8, 0xd1, 0x1a, 0x42, 0xb8, 0x3b, 0x40, 0x0d, 0xf8, 0x6f, 0xae, 0x68, 0xe7, 0xdc, 0xa6,
+	0xaa, 0x45, 0xd9, 0x82, 0xc2, 0x9c, 0xbd, 0x64, 0xd9, 0x71, 0xce, 0x7e, 0xf2, 0x07, 0xf6, 0x2b,
+	0x46, 0x33, 0xf4, 0xf0, 0x66, 0xb1, 0xf6, 0xc0, 0x72, 0xed, 0x81, 0xaf, 0xb5, 0x07, 0xde, 0x36,
+	0x9e, 0xb3, 0xdc, 0x78, 0xce, 0xfb, 0xc6, 0x73, 0x1e, 0x2e, 0x0a, 0x3e, 0x29, 0x7f, 0x3b, 0x6b,
+	0x71, 0x1b, 0x85, 0xbc, 0x90, 0x42, 0xb7, 0xd6, 0xb6, 0x5f, 0xb5, 0xd5, 0x5c, 0x7e, 0x07, 0x00,
+	0x00, 0xff, 0xff, 0xd2, 0x2c, 0x21, 0x90, 0xf6, 0x01, 0x00, 0x00,
+}
+
+func (m *RateLimiterFlags) 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 *RateLimiterFlags) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *RateLimiterFlags) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if len(m.Conversions) > 0 {
+		for iNdEx := len(m.Conversions) - 1; iNdEx >= 0; iNdEx-- {
+			{
+				size, err := m.Conversions[iNdEx].MarshalToSizedBuffer(dAtA[:i])
+				if err != nil {
+					return 0, err
+				}
+				i -= size
+				i = encodeVarintRateLimiterFlags(dAtA, i, uint64(size))
+			}
+			i--
+			dAtA[i] = 0x22
+		}
+	}
+	{
+		size := m.Rate.Size()
+		i -= size
+		if _, err := m.Rate.MarshalTo(dAtA[i:]); err != nil {
+			return 0, err
+		}
+		i = encodeVarintRateLimiterFlags(dAtA, i, uint64(size))
+	}
+	i--
+	dAtA[i] = 0x1a
+	if m.Window != 0 {
+		i = encodeVarintRateLimiterFlags(dAtA, i, uint64(m.Window))
+		i--
+		dAtA[i] = 0x10
+	}
+	if m.Enabled {
+		i--
+		if m.Enabled {
+			dAtA[i] = 1
+		} else {
+			dAtA[i] = 0
+		}
+		i--
+		dAtA[i] = 0x8
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *Conversion) 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 *Conversion) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *Conversion) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	{
+		size := m.Rate.Size()
+		i -= size
+		if _, err := m.Rate.MarshalTo(dAtA[i:]); err != nil {
+			return 0, err
+		}
+		i = encodeVarintRateLimiterFlags(dAtA, i, uint64(size))
+	}
+	i--
+	dAtA[i] = 0x12
+	if len(m.Zrc20) > 0 {
+		i -= len(m.Zrc20)
+		copy(dAtA[i:], m.Zrc20)
+		i = encodeVarintRateLimiterFlags(dAtA, i, uint64(len(m.Zrc20)))
+		i--
+		dAtA[i] = 0xa
+	}
+	return len(dAtA) - i, nil
+}
+
+func encodeVarintRateLimiterFlags(dAtA []byte, offset int, v uint64) int {
+	offset -= sovRateLimiterFlags(v)
+	base := offset
+	for v >= 1<<7 {
+		dAtA[offset] = uint8(v&0x7f | 0x80)
+		v >>= 7
+		offset++
+	}
+	dAtA[offset] = uint8(v)
+	return base
+}
+func (m *RateLimiterFlags) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.Enabled {
+		n += 2
+	}
+	if m.Window != 0 {
+		n += 1 + sovRateLimiterFlags(uint64(m.Window))
+	}
+	l = m.Rate.Size()
+	n += 1 + l + sovRateLimiterFlags(uint64(l))
+	if len(m.Conversions) > 0 {
+		for _, e := range m.Conversions {
+			l = e.Size()
+			n += 1 + l + sovRateLimiterFlags(uint64(l))
+		}
+	}
+	return n
+}
+
+func (m *Conversion) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	l = len(m.Zrc20)
+	if l > 0 {
+		n += 1 + l + sovRateLimiterFlags(uint64(l))
+	}
+	l = m.Rate.Size()
+	n += 1 + l + sovRateLimiterFlags(uint64(l))
+	return n
+}
+
+func sovRateLimiterFlags(x uint64) (n int) {
+	return (math_bits.Len64(x|1) + 6) / 7
+}
+func sozRateLimiterFlags(x uint64) (n int) {
+	return sovRateLimiterFlags(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+}
+func (m *RateLimiterFlags) 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 ErrIntOverflowRateLimiterFlags
+			}
+			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: RateLimiterFlags: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: RateLimiterFlags: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Enabled", wireType)
+			}
+			var v int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowRateLimiterFlags
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				v |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			m.Enabled = bool(v != 0)
+		case 2:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Window", wireType)
+			}
+			m.Window = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowRateLimiterFlags
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.Window |= int64(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		case 3:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Rate", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowRateLimiterFlags
+				}
+				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 ErrInvalidLengthRateLimiterFlags
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex < 0 {
+				return ErrInvalidLengthRateLimiterFlags
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if err := m.Rate.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 4:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Conversions", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowRateLimiterFlags
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthRateLimiterFlags
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthRateLimiterFlags
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Conversions = append(m.Conversions, Conversion{})
+			if err := m.Conversions[len(m.Conversions)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipRateLimiterFlags(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if (skippy < 0) || (iNdEx+skippy) < 0 {
+				return ErrInvalidLengthRateLimiterFlags
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *Conversion) 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 ErrIntOverflowRateLimiterFlags
+			}
+			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: Conversion: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: Conversion: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Zrc20", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowRateLimiterFlags
+				}
+				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 ErrInvalidLengthRateLimiterFlags
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex < 0 {
+				return ErrInvalidLengthRateLimiterFlags
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Zrc20 = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Rate", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowRateLimiterFlags
+				}
+				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 ErrInvalidLengthRateLimiterFlags
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex < 0 {
+				return ErrInvalidLengthRateLimiterFlags
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if err := m.Rate.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipRateLimiterFlags(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if (skippy < 0) || (iNdEx+skippy) < 0 {
+				return ErrInvalidLengthRateLimiterFlags
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func skipRateLimiterFlags(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, ErrIntOverflowRateLimiterFlags
+			}
+			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, ErrIntOverflowRateLimiterFlags
+				}
+				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, ErrIntOverflowRateLimiterFlags
+				}
+				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, ErrInvalidLengthRateLimiterFlags
+			}
+			iNdEx += length
+		case 3:
+			depth++
+		case 4:
+			if depth == 0 {
+				return 0, ErrUnexpectedEndOfGroupRateLimiterFlags
+			}
+			depth--
+		case 5:
+			iNdEx += 4
+		default:
+			return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
+		}
+		if iNdEx < 0 {
+			return 0, ErrInvalidLengthRateLimiterFlags
+		}
+		if depth == 0 {
+			return iNdEx, nil
+		}
+	}
+	return 0, io.ErrUnexpectedEOF
+}
+
+var (
+	ErrInvalidLengthRateLimiterFlags        = fmt.Errorf("proto: negative length found during unmarshaling")
+	ErrIntOverflowRateLimiterFlags          = fmt.Errorf("proto: integer overflow")
+	ErrUnexpectedEndOfGroupRateLimiterFlags = fmt.Errorf("proto: unexpected end of group")
+)
diff --git a/x/crosschain/types/rate_limiter_flags_test.go b/x/crosschain/types/rate_limiter_flags_test.go
new file mode 100644
index 0000000000..d837fabc51
--- /dev/null
+++ b/x/crosschain/types/rate_limiter_flags_test.go
@@ -0,0 +1,186 @@
+package types_test
+
+import (
+	"testing"
+
+	sdk "github.com/cosmos/cosmos-sdk/types"
+	"github.com/stretchr/testify/require"
+	"github.com/zeta-chain/zetacore/testutil/sample"
+	"github.com/zeta-chain/zetacore/x/crosschain/types"
+)
+
+func TestRateLimiterFlags_Validate(t *testing.T) {
+	dec, err := sdk.NewDecFromStr("0.00042")
+	require.NoError(t, err)
+	duplicatedAddress := sample.EthAddress().String()
+
+	tt := []struct {
+		name  string
+		flags types.RateLimiterFlags
+		isErr bool
+	}{
+		{
+			name: "valid flags",
+			flags: types.RateLimiterFlags{
+				Enabled: true,
+				Window:  42,
+				Rate:    sdk.NewUint(42),
+				Conversions: []types.Conversion{
+					{
+						Zrc20: sample.EthAddress().String(),
+						Rate:  sdk.NewDec(42),
+					},
+					{
+						Zrc20: sample.EthAddress().String(),
+						Rate:  dec,
+					},
+				},
+			},
+		},
+		{
+			name:  "empty is valid",
+			flags: types.RateLimiterFlags{},
+		},
+		{
+			name: "invalid zrc20 address",
+			flags: types.RateLimiterFlags{
+				Enabled: true,
+				Window:  42,
+				Rate:    sdk.NewUint(42),
+				Conversions: []types.Conversion{
+					{
+						Zrc20: "invalid",
+						Rate:  sdk.NewDec(42),
+					},
+					{
+						Zrc20: sample.EthAddress().String(),
+						Rate:  dec,
+					},
+				},
+			},
+			isErr: true,
+		},
+		{
+			name: "duplicated conversion",
+			flags: types.RateLimiterFlags{
+				Enabled: true,
+				Window:  42,
+				Rate:    sdk.NewUint(42),
+				Conversions: []types.Conversion{
+					{
+						Zrc20: duplicatedAddress,
+						Rate:  sdk.NewDec(42),
+					},
+					{
+						Zrc20: duplicatedAddress,
+						Rate:  dec,
+					},
+				},
+			},
+			isErr: true,
+		},
+		{
+			name: "invalid conversion rate",
+			flags: types.RateLimiterFlags{
+				Enabled: true,
+				Window:  42,
+				Rate:    sdk.NewUint(42),
+				Conversions: []types.Conversion{
+					{
+						Zrc20: sample.EthAddress().String(),
+						Rate:  sdk.NewDec(42),
+					},
+					{
+						Zrc20: sample.EthAddress().String(),
+					},
+				},
+			},
+			isErr: true,
+		},
+		{
+			name: "negative window",
+			flags: types.RateLimiterFlags{
+				Enabled: true,
+				Window:  -1,
+			},
+			isErr: true,
+		},
+	}
+
+	for _, tc := range tt {
+		t.Run(tc.name, func(t *testing.T) {
+			err := tc.flags.Validate()
+			if tc.isErr {
+				require.Error(t, err)
+			} else {
+				require.NoError(t, err)
+			}
+		})
+	}
+
+}
+
+func TestRateLimiterFlags_GetConversionRate(t *testing.T) {
+	dec, err := sdk.NewDecFromStr("0.00042")
+	require.NoError(t, err)
+	address := sample.EthAddress().String()
+
+	tt := []struct {
+		name       string
+		flags      types.RateLimiterFlags
+		zrc20      string
+		expected   sdk.Dec
+		shouldFind bool
+	}{
+		{
+			name: "valid conversion",
+			flags: types.RateLimiterFlags{
+				Enabled: true,
+				Window:  42,
+				Rate:    sdk.NewUint(42),
+				Conversions: []types.Conversion{
+					{
+						Zrc20: address,
+						Rate:  sdk.NewDec(42),
+					},
+					{
+						Zrc20: sample.EthAddress().String(),
+						Rate:  dec,
+					},
+				},
+			},
+			zrc20:      address,
+			expected:   sdk.NewDec(42),
+			shouldFind: true,
+		},
+		{
+			name: "not found",
+			flags: types.RateLimiterFlags{
+				Enabled: true,
+				Window:  42,
+				Rate:    sdk.NewUint(42),
+				Conversions: []types.Conversion{
+					{
+						Zrc20: sample.EthAddress().String(),
+						Rate:  sdk.NewDec(42),
+					},
+					{
+						Zrc20: sample.EthAddress().String(),
+						Rate:  dec,
+					},
+				},
+			},
+			zrc20:      address,
+			expected:   sdk.NewDec(0),
+			shouldFind: false,
+		},
+	}
+
+	for _, tc := range tt {
+		t.Run(tc.name, func(t *testing.T) {
+			actual, found := tc.flags.GetConversionRate(tc.zrc20)
+			require.Equal(t, tc.expected, actual)
+			require.Equal(t, tc.shouldFind, found)
+		})
+	}
+}
diff --git a/x/crosschain/types/tx.pb.go b/x/crosschain/types/tx.pb.go
index 54c8aee125..f7fa9790e4 100644
--- a/x/crosschain/types/tx.pb.go
+++ b/x/crosschain/types/tx.pb.go
@@ -1344,6 +1344,94 @@ func (m *MsgRefundAbortedCCTXResponse) XXX_DiscardUnknown() {
 
 var xxx_messageInfo_MsgRefundAbortedCCTXResponse proto.InternalMessageInfo
 
+type MsgUpdateRateLimiterFlags struct {
+	Creator          string           `protobuf:"bytes,1,opt,name=creator,proto3" json:"creator,omitempty"`
+	RateLimiterFlags RateLimiterFlags `protobuf:"bytes,2,opt,name=rate_limiter_flags,json=rateLimiterFlags,proto3" json:"rate_limiter_flags"`
+}
+
+func (m *MsgUpdateRateLimiterFlags) Reset()         { *m = MsgUpdateRateLimiterFlags{} }
+func (m *MsgUpdateRateLimiterFlags) String() string { return proto.CompactTextString(m) }
+func (*MsgUpdateRateLimiterFlags) ProtoMessage()    {}
+func (*MsgUpdateRateLimiterFlags) Descriptor() ([]byte, []int) {
+	return fileDescriptor_81d6d611190b7635, []int{22}
+}
+func (m *MsgUpdateRateLimiterFlags) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *MsgUpdateRateLimiterFlags) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_MsgUpdateRateLimiterFlags.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 *MsgUpdateRateLimiterFlags) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_MsgUpdateRateLimiterFlags.Merge(m, src)
+}
+func (m *MsgUpdateRateLimiterFlags) XXX_Size() int {
+	return m.Size()
+}
+func (m *MsgUpdateRateLimiterFlags) XXX_DiscardUnknown() {
+	xxx_messageInfo_MsgUpdateRateLimiterFlags.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_MsgUpdateRateLimiterFlags proto.InternalMessageInfo
+
+func (m *MsgUpdateRateLimiterFlags) GetCreator() string {
+	if m != nil {
+		return m.Creator
+	}
+	return ""
+}
+
+func (m *MsgUpdateRateLimiterFlags) GetRateLimiterFlags() RateLimiterFlags {
+	if m != nil {
+		return m.RateLimiterFlags
+	}
+	return RateLimiterFlags{}
+}
+
+type MsgUpdateRateLimiterFlagsResponse struct {
+}
+
+func (m *MsgUpdateRateLimiterFlagsResponse) Reset()         { *m = MsgUpdateRateLimiterFlagsResponse{} }
+func (m *MsgUpdateRateLimiterFlagsResponse) String() string { return proto.CompactTextString(m) }
+func (*MsgUpdateRateLimiterFlagsResponse) ProtoMessage()    {}
+func (*MsgUpdateRateLimiterFlagsResponse) Descriptor() ([]byte, []int) {
+	return fileDescriptor_81d6d611190b7635, []int{23}
+}
+func (m *MsgUpdateRateLimiterFlagsResponse) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *MsgUpdateRateLimiterFlagsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_MsgUpdateRateLimiterFlagsResponse.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 *MsgUpdateRateLimiterFlagsResponse) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_MsgUpdateRateLimiterFlagsResponse.Merge(m, src)
+}
+func (m *MsgUpdateRateLimiterFlagsResponse) XXX_Size() int {
+	return m.Size()
+}
+func (m *MsgUpdateRateLimiterFlagsResponse) XXX_DiscardUnknown() {
+	xxx_messageInfo_MsgUpdateRateLimiterFlagsResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_MsgUpdateRateLimiterFlagsResponse proto.InternalMessageInfo
+
 func init() {
 	proto.RegisterType((*MsgMigrateTssFunds)(nil), "zetachain.zetacore.crosschain.MsgMigrateTssFunds")
 	proto.RegisterType((*MsgMigrateTssFundsResponse)(nil), "zetachain.zetacore.crosschain.MsgMigrateTssFundsResponse")
@@ -1367,103 +1455,110 @@ func init() {
 	proto.RegisterType((*MsgAbortStuckCCTXResponse)(nil), "zetachain.zetacore.crosschain.MsgAbortStuckCCTXResponse")
 	proto.RegisterType((*MsgRefundAbortedCCTX)(nil), "zetachain.zetacore.crosschain.MsgRefundAbortedCCTX")
 	proto.RegisterType((*MsgRefundAbortedCCTXResponse)(nil), "zetachain.zetacore.crosschain.MsgRefundAbortedCCTXResponse")
+	proto.RegisterType((*MsgUpdateRateLimiterFlags)(nil), "zetachain.zetacore.crosschain.MsgUpdateRateLimiterFlags")
+	proto.RegisterType((*MsgUpdateRateLimiterFlagsResponse)(nil), "zetachain.zetacore.crosschain.MsgUpdateRateLimiterFlagsResponse")
 }
 
 func init() { proto.RegisterFile("crosschain/tx.proto", fileDescriptor_81d6d611190b7635) }
 
 var fileDescriptor_81d6d611190b7635 = []byte{
-	// 1452 bytes of a gzipped FileDescriptorProto
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x18, 0x5d, 0x4f, 0xdb, 0x56,
-	0x1b, 0xbf, 0x40, 0x48, 0x1e, 0x48, 0x78, 0x6b, 0x68, 0x09, 0xa6, 0x04, 0x6a, 0xde, 0xf6, 0x45,
-	0x7a, 0xd5, 0xa4, 0x4d, 0xf5, 0x4e, 0x6d, 0xb7, 0x49, 0x03, 0xd4, 0x0f, 0xb6, 0x52, 0x2a, 0x37,
-	0xdd, 0xa6, 0xdd, 0x58, 0x8e, 0x7d, 0x70, 0x2c, 0x12, 0x9f, 0xc8, 0xe7, 0x38, 0x0a, 0x68, 0xd2,
-	0xa6, 0x49, 0xbb, 0x9f, 0xa6, 0x49, 0x95, 0xf6, 0x8b, 0x7a, 0x59, 0xed, 0x66, 0x1f, 0x17, 0xd5,
-	0x44, 0x7f, 0xc0, 0xa4, 0xfd, 0x82, 0xc9, 0xcf, 0x39, 0x31, 0x71, 0x42, 0x3e, 0xa0, 0xea, 0x4d,
-	0xe2, 0xe7, 0x39, 0xe7, 0xf9, 0xfe, 0xb4, 0x61, 0xc1, 0x0e, 0x28, 0x63, 0x76, 0xcd, 0xf2, 0xfc,
-	0x12, 0x6f, 0x17, 0x9b, 0x01, 0xe5, 0x54, 0x5d, 0x3d, 0x26, 0xdc, 0x42, 0x5c, 0x11, 0x9f, 0x68,
-	0x40, 0x8a, 0xa7, 0xf7, 0xb4, 0x45, 0x97, 0xba, 0x14, 0x6f, 0x96, 0xa2, 0x27, 0x41, 0xa4, 0x2d,
-	0x35, 0x0f, 0xdd, 0x12, 0x5e, 0x60, 0xf2, 0x4f, 0x1e, 0x2c, 0xe0, 0x01, 0xf5, 0x7c, 0xfc, 0xe9,
-	0xbe, 0xdd, 0x0c, 0x28, 0x3d, 0x60, 0xf2, 0x4f, 0x1c, 0xe8, 0x3f, 0x2a, 0xa0, 0xee, 0x31, 0x77,
-	0xcf, 0x73, 0x03, 0x8b, 0x93, 0x0a, 0x63, 0x0f, 0x43, 0xdf, 0x61, 0x6a, 0x1e, 0x66, 0xec, 0x80,
-	0x58, 0x9c, 0x06, 0x79, 0x65, 0x5d, 0xd9, 0xcc, 0x18, 0x1d, 0x50, 0x5d, 0x86, 0x34, 0x8a, 0x33,
-	0x3d, 0x27, 0xff, 0xaf, 0x75, 0x65, 0x73, 0xd2, 0x98, 0x41, 0x78, 0xd7, 0x51, 0x1f, 0x41, 0xca,
-	0x6a, 0xd0, 0xd0, 0xe7, 0xf9, 0xc9, 0x88, 0x66, 0xbb, 0xf4, 0xea, 0xcd, 0xda, 0xc4, 0x1f, 0x6f,
-	0xd6, 0xfe, 0xeb, 0x7a, 0xbc, 0x16, 0x56, 0x8b, 0x36, 0x6d, 0x94, 0x6c, 0xca, 0x1a, 0x94, 0xc9,
-	0xbf, 0x9b, 0xcc, 0x39, 0x2c, 0xf1, 0xa3, 0x26, 0x61, 0xc5, 0x17, 0x9e, 0xcf, 0x0d, 0x49, 0xae,
-	0x5f, 0x05, 0xad, 0x5f, 0x27, 0x83, 0xb0, 0x26, 0xf5, 0x19, 0xd1, 0x9f, 0xc2, 0xc2, 0x1e, 0x73,
-	0x5f, 0x34, 0x1d, 0x71, 0xb8, 0xe5, 0x38, 0x01, 0x61, 0xc3, 0x54, 0x5e, 0x05, 0xe0, 0x8c, 0x99,
-	0xcd, 0xb0, 0x7a, 0x48, 0x8e, 0x50, 0xe9, 0x8c, 0x91, 0xe1, 0x8c, 0x3d, 0x43, 0x84, 0xbe, 0x0a,
-	0x2b, 0x67, 0xf0, 0x8b, 0xc5, 0xfd, 0xa5, 0xa0, 0xbc, 0x2d, 0xc7, 0xa9, 0xd0, 0x5d, 0xbf, 0xd2,
-	0xae, 0x04, 0x96, 0x7d, 0x48, 0x82, 0x8b, 0xb9, 0x68, 0x09, 0x66, 0x78, 0xdb, 0xac, 0x59, 0xac,
-	0x26, 0x7c, 0x64, 0xa4, 0x78, 0xfb, 0xb1, 0xc5, 0x6a, 0xea, 0xff, 0x20, 0x13, 0x85, 0xcb, 0x8c,
-	0xbc, 0x91, 0x9f, 0x5a, 0x57, 0x36, 0x73, 0xe5, 0x5c, 0x11, 0x03, 0xb8, 0x43, 0x3d, 0xbf, 0x72,
-	0xd4, 0x24, 0x46, 0xda, 0x96, 0x4f, 0xea, 0x06, 0x4c, 0x63, 0x10, 0xf3, 0xd3, 0xeb, 0xca, 0xe6,
-	0x6c, 0x39, 0x5b, 0x94, 0x21, 0x7d, 0x16, 0xfd, 0x19, 0xe2, 0x2c, 0xb2, 0xba, 0x5a, 0xa7, 0xf6,
-	0xa1, 0x90, 0x96, 0x12, 0x56, 0x23, 0x06, 0x05, 0x2e, 0x43, 0x9a, 0xb7, 0x4d, 0xcf, 0x77, 0x48,
-	0x3b, 0x3f, 0x23, 0x94, 0xe4, 0xed, 0xdd, 0x08, 0x94, 0x0e, 0xe9, 0x35, 0x38, 0x76, 0xc8, 0x2f,
-	0x0a, 0x5c, 0xda, 0x63, 0xee, 0x17, 0x35, 0x8f, 0x93, 0xba, 0xc7, 0xf8, 0x03, 0x63, 0xa7, 0x7c,
-	0x6b, 0x88, 0x3b, 0x36, 0x20, 0x4b, 0x02, 0xbb, 0x7c, 0xcb, 0xb4, 0x84, 0x67, 0x65, 0x04, 0xe6,
-	0x10, 0xd9, 0x89, 0x5e, 0xb7, 0xcf, 0x26, 0x93, 0x3e, 0x53, 0x61, 0xca, 0xb7, 0x1a, 0xc2, 0x2b,
-	0x19, 0x03, 0x9f, 0xd5, 0x2b, 0x90, 0x62, 0x47, 0x8d, 0x2a, 0xad, 0xa3, 0x0b, 0x32, 0x86, 0x84,
-	0x54, 0x0d, 0xd2, 0x0e, 0xb1, 0xbd, 0x86, 0x55, 0x67, 0x68, 0x72, 0xd6, 0x88, 0x61, 0x75, 0x05,
-	0x32, 0xae, 0xc5, 0xcc, 0xba, 0xd7, 0xf0, 0xb8, 0x34, 0x39, 0xed, 0x5a, 0xec, 0x49, 0x04, 0xeb,
-	0x26, 0x2c, 0xf7, 0xd9, 0xd4, 0xb1, 0x38, 0xb2, 0xe0, 0x38, 0x61, 0x81, 0xb0, 0x70, 0xee, 0xb8,
-	0xdb, 0x82, 0x55, 0x00, 0xdb, 0x8e, 0x5d, 0x2a, 0xb3, 0x2c, 0xc2, 0x08, 0xa7, 0xfe, 0xae, 0xc0,
-	0x62, 0xc7, 0xab, 0xfb, 0x21, 0x7f, 0xc7, 0x3c, 0x5a, 0x84, 0x69, 0x9f, 0xfa, 0x36, 0x41, 0x5f,
-	0x4d, 0x19, 0x02, 0xe8, 0xce, 0xae, 0xa9, 0x44, 0x76, 0xbd, 0xe7, 0x84, 0xf9, 0x18, 0xae, 0x9e,
-	0x65, 0x5a, 0xec, 0xbf, 0x55, 0x00, 0x8f, 0x99, 0x01, 0x69, 0xd0, 0x16, 0x71, 0xd0, 0xca, 0xb4,
-	0x91, 0xf1, 0x98, 0x21, 0x10, 0xfa, 0x01, 0xfa, 0x5e, 0x40, 0x0f, 0x03, 0xda, 0x78, 0x4f, 0xee,
-	0xd1, 0x37, 0xe0, 0xda, 0x40, 0x39, 0x71, 0x76, 0xbf, 0x54, 0x60, 0x7e, 0x8f, 0xb9, 0x9f, 0x53,
-	0x4e, 0x1e, 0x59, 0xec, 0x59, 0xe0, 0xd9, 0xe4, 0xc2, 0x3a, 0x34, 0x23, 0xea, 0x8e, 0x0e, 0x08,
-	0xa8, 0xd7, 0x60, 0x4e, 0x38, 0xd9, 0x0f, 0x1b, 0x55, 0x12, 0x60, 0x9c, 0xa6, 0x8c, 0x59, 0xc4,
-	0x3d, 0x45, 0x14, 0xe6, 0x76, 0xd8, 0x6c, 0xd6, 0x8f, 0xe2, 0xdc, 0x46, 0x48, 0x5f, 0x86, 0xa5,
-	0x1e, 0xc5, 0x62, 0xa5, 0x7f, 0x9d, 0xc6, 0x92, 0x8d, 0xce, 0xf6, 0xfd, 0xfd, 0x2a, 0x23, 0x41,
-	0x8b, 0x38, 0xfb, 0x21, 0xaf, 0xd2, 0xd0, 0x77, 0x2a, 0xed, 0x21, 0x06, 0xac, 0x00, 0xe6, 0xa8,
-	0x88, 0xb9, 0x48, 0xda, 0x74, 0x84, 0xc0, 0x90, 0x17, 0x61, 0x81, 0x4a, 0x66, 0x26, 0x8d, 0x9c,
-	0xd5, 0xdd, 0xb9, 0x2e, 0xd1, 0x53, 0x39, 0x15, 0x71, 0xff, 0x23, 0xd0, 0x7a, 0xee, 0x8b, 0xf4,
-	0x21, 0x9e, 0x5b, 0xe3, 0xd2, 0xd4, 0x7c, 0x82, 0x6c, 0xfb, 0xf4, 0x5c, 0xfd, 0x3f, 0x2c, 0xf5,
-	0x50, 0x47, 0xe5, 0x1a, 0x32, 0xe2, 0xe4, 0x01, 0x49, 0x17, 0x13, 0xa4, 0x8f, 0x2c, 0xf6, 0x82,
-	0x11, 0x47, 0x3d, 0x06, 0xbd, 0x87, 0x8c, 0x1c, 0x1c, 0x10, 0x9b, 0x7b, 0x2d, 0x82, 0x0c, 0x44,
-	0x10, 0x66, 0x71, 0x22, 0x15, 0xe5, 0x44, 0xba, 0x31, 0xc6, 0x44, 0xda, 0xf5, 0xb9, 0x51, 0x48,
-	0x48, 0x7c, 0xd0, 0xe1, 0x1b, 0x27, 0xc6, 0xa7, 0x23, 0x64, 0x8b, 0x5e, 0x33, 0x87, 0xda, 0x0f,
-	0xe6, 0x85, 0x1d, 0x48, 0xa5, 0x90, 0x6b, 0x59, 0xf5, 0x90, 0x98, 0x01, 0xb1, 0x89, 0x17, 0x15,
-	0x0a, 0x86, 0x7f, 0xfb, 0xf1, 0x39, 0xa7, 0xe8, 0xdf, 0x6f, 0xd6, 0x2e, 0x1f, 0x59, 0x8d, 0xfa,
-	0x7d, 0x3d, 0xc9, 0x4e, 0x37, 0xb2, 0x88, 0x30, 0x24, 0xac, 0xde, 0x84, 0x14, 0xe3, 0x16, 0x0f,
-	0x45, 0xa7, 0xcc, 0x95, 0x2f, 0x17, 0xe5, 0x1e, 0x21, 0x6f, 0x3c, 0xc7, 0x43, 0x43, 0x5e, 0x52,
-	0xd7, 0x60, 0x56, 0x98, 0x88, 0xb7, 0x64, 0x0b, 0x00, 0x44, 0xed, 0x44, 0x18, 0xf5, 0x06, 0xcc,
-	0x8b, 0x0b, 0xd1, 0xb0, 0x15, 0xe5, 0x97, 0x46, 0xcb, 0xb3, 0x88, 0xae, 0x30, 0xf6, 0x14, 0xbb,
-	0x54, 0x62, 0xd4, 0x65, 0x86, 0x8f, 0x3a, 0xfd, 0x3a, 0x6c, 0x0c, 0x49, 0xec, 0xb8, 0x00, 0xbe,
-	0x9d, 0xc2, 0x95, 0x21, 0x79, 0x6f, 0xd7, 0x1f, 0x9d, 0xff, 0x51, 0xb1, 0x11, 0xdf, 0x21, 0x81,
-	0x4c, 0x7e, 0x09, 0x45, 0xc6, 0x88, 0x27, 0xb3, 0x67, 0x2c, 0x65, 0x05, 0x7a, 0x47, 0x56, 0xb9,
-	0x06, 0x69, 0xe9, 0xe0, 0x40, 0xf6, 0xdc, 0x18, 0x56, 0xaf, 0x43, 0xae, 0xf3, 0x2c, 0x9d, 0x36,
-	0x2d, 0x58, 0x74, 0xb0, 0xc2, 0x6f, 0xa7, 0x6b, 0x53, 0xea, 0x9d, 0xd6, 0xa6, 0xc8, 0xca, 0x06,
-	0x61, 0xcc, 0x72, 0x85, 0xe3, 0x33, 0x46, 0x07, 0x54, 0xaf, 0x02, 0x44, 0x0e, 0x97, 0xf5, 0x9b,
-	0x11, 0x7a, 0x7a, 0xbe, 0x2c, 0xdb, 0x1b, 0x30, 0xef, 0xf9, 0xa6, 0xec, 0xfd, 0xa2, 0x56, 0x45,
-	0xc1, 0x65, 0x3d, 0xbf, 0xbb, 0x40, 0x13, 0x03, 0x74, 0x16, 0x6f, 0xc4, 0x03, 0x34, 0x19, 0xd5,
-	0xb9, 0x11, 0x0b, 0xcc, 0x0a, 0x64, 0x78, 0xdb, 0xa4, 0x81, 0xe7, 0x7a, 0x7e, 0x3e, 0x2b, 0xd4,
-	0xe1, 0xed, 0x7d, 0x84, 0xa3, 0xc6, 0x69, 0x31, 0x46, 0x78, 0x3e, 0x87, 0x07, 0x02, 0x88, 0xd2,
-	0x8f, 0xb4, 0x88, 0xcf, 0xe5, 0x04, 0x9a, 0x47, 0xf1, 0x80, 0x28, 0x31, 0x84, 0xfe, 0x03, 0xfa,
-	0xe0, 0x0c, 0x88, 0x13, 0xe5, 0x09, 0xee, 0x2e, 0x5b, 0x55, 0x1a, 0xf0, 0xe7, 0x3c, 0xb4, 0x0f,
-	0x77, 0x76, 0x2a, 0x5f, 0x0e, 0x5f, 0x1d, 0x87, 0x0d, 0xf5, 0x15, 0x9c, 0x5c, 0x49, 0x6e, 0xb1,
-	0xa8, 0x16, 0x0e, 0x7c, 0x83, 0x1c, 0x84, 0xbe, 0x83, 0x57, 0x88, 0xf3, 0x4e, 0xd2, 0x44, 0x3e,
-	0x45, 0xdc, 0xe2, 0x3d, 0x44, 0x74, 0xe2, 0xac, 0xc0, 0xca, 0x45, 0x44, 0x2f, 0xe0, 0x34, 0xee,
-	0x93, 0xdb, 0xd1, 0xab, 0x7c, 0x32, 0x0b, 0x93, 0x7b, 0xcc, 0x55, 0xbf, 0x57, 0xe0, 0x52, 0xff,
-	0x3a, 0x72, 0xa7, 0x38, 0xf4, 0x6d, 0xa4, 0x78, 0xd6, 0xa0, 0xd7, 0x3e, 0xbc, 0x00, 0x51, 0xbc,
-	0x1d, 0x7c, 0xa7, 0xc0, 0xbf, 0xfb, 0xb6, 0xeb, 0xf2, 0x98, 0x1c, 0xbb, 0x68, 0xb4, 0xfb, 0xe7,
-	0xa7, 0x89, 0x95, 0xf8, 0x49, 0x81, 0x2b, 0x03, 0x36, 0x90, 0xbb, 0xa3, 0xd9, 0x9e, 0x4d, 0xa9,
-	0x7d, 0x72, 0x51, 0xca, 0x58, 0xad, 0x16, 0xcc, 0x25, 0x36, 0x91, 0xe2, 0x68, 0x8e, 0xdd, 0xf7,
-	0xb5, 0x0f, 0xce, 0x77, 0x3f, 0x96, 0xfb, 0xb3, 0x02, 0xf9, 0x81, 0xdb, 0xc4, 0xfd, 0xf1, 0x98,
-	0x9e, 0x45, 0xab, 0x6d, 0x5f, 0x9c, 0x36, 0x56, 0xee, 0xa5, 0x02, 0x4b, 0x83, 0x3a, 0xfd, 0xbd,
-	0xf3, 0xf2, 0x8f, 0x49, 0xb5, 0xad, 0x0b, 0x93, 0xc6, 0x9a, 0x7d, 0x0d, 0xb9, 0x9e, 0xd7, 0xa2,
-	0x5b, 0xa3, 0x99, 0x26, 0x29, 0xb4, 0xbb, 0xe7, 0xa5, 0x48, 0x14, 0x52, 0xdf, 0x6b, 0xf1, 0x18,
-	0x85, 0xd4, 0x4b, 0x33, 0x4e, 0x21, 0x0d, 0x7a, 0x5d, 0x56, 0xbf, 0x81, 0xf9, 0xde, 0x8f, 0x09,
-	0xb7, 0x47, 0xb3, 0xeb, 0x21, 0xd1, 0xee, 0x9d, 0x9b, 0xa4, 0x3b, 0x06, 0x3d, 0xed, 0x7d, 0x8c,
-	0x18, 0x24, 0x29, 0xc6, 0x89, 0xc1, 0xd9, 0x4d, 0x1f, 0x9b, 0x6a, 0x7f, 0xcb, 0xbf, 0x33, 0x4e,
-	0x23, 0xe8, 0x21, 0x1a, 0xa7, 0xa9, 0x0e, 0x6c, 0xf2, 0xdb, 0x9f, 0xbd, 0x3a, 0x29, 0x28, 0xaf,
-	0x4f, 0x0a, 0xca, 0x9f, 0x27, 0x05, 0xe5, 0x87, 0xb7, 0x85, 0x89, 0xd7, 0x6f, 0x0b, 0x13, 0xbf,
-	0xbd, 0x2d, 0x4c, 0x7c, 0x75, 0xbb, 0x6b, 0xad, 0x88, 0xd8, 0xde, 0x14, 0x5f, 0xa3, 0x3a, 0x12,
-	0x4a, 0xed, 0x52, 0xf7, 0x37, 0xaa, 0x68, 0xcb, 0xa8, 0xa6, 0xf0, 0x5b, 0xd1, 0x9d, 0x7f, 0x02,
-	0x00, 0x00, 0xff, 0xff, 0x14, 0x36, 0x6f, 0x72, 0xbe, 0x12, 0x00, 0x00,
+	// 1528 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x18, 0x5b, 0x6b, 0xdb, 0x56,
+	0x38, 0x5a, 0x6e, 0xf6, 0x97, 0x38, 0x69, 0x95, 0xb4, 0x71, 0x9c, 0xc6, 0x49, 0x9d, 0xb5, 0x0b,
+	0x8c, 0xda, 0xad, 0xcb, 0x46, 0xdb, 0x6d, 0xb0, 0x24, 0xf4, 0x92, 0xad, 0x69, 0x8a, 0xea, 0x6e,
+	0x63, 0x2f, 0x42, 0x96, 0x4e, 0x14, 0x11, 0x5b, 0xc7, 0xe8, 0x1c, 0x05, 0x27, 0x0c, 0x36, 0x06,
+	0x7b, 0x1f, 0x63, 0x50, 0xe8, 0x2f, 0xea, 0x63, 0xd9, 0xcb, 0x2e, 0x0f, 0x65, 0xb4, 0x3f, 0x60,
+	0xb0, 0xb7, 0xbd, 0x8d, 0xf3, 0x9d, 0x63, 0xc5, 0x92, 0xaf, 0x49, 0xe9, 0x8b, 0xad, 0xef, 0x3b,
+	0xe7, 0xbb, 0x5f, 0x25, 0x98, 0xb3, 0x03, 0xca, 0x98, 0xbd, 0x6f, 0x79, 0x7e, 0x89, 0x37, 0x8b,
+	0x8d, 0x80, 0x72, 0xaa, 0x2f, 0x1f, 0x13, 0x6e, 0x21, 0xae, 0x88, 0x4f, 0x34, 0x20, 0xc5, 0x93,
+	0x7b, 0xb9, 0xb5, 0x36, 0x9a, 0xc0, 0xe2, 0xc4, 0xac, 0x79, 0x75, 0x8f, 0x93, 0xc0, 0xdc, 0xab,
+	0x59, 0x2e, 0x93, 0x3c, 0x72, 0xf3, 0x2e, 0x75, 0x29, 0x3e, 0x96, 0xc4, 0x93, 0xc2, 0x2e, 0x34,
+	0x0e, 0xdc, 0x12, 0x52, 0x32, 0xf5, 0xa7, 0x0e, 0xe6, 0xf0, 0x80, 0x7a, 0x3e, 0xfe, 0xb4, 0xdf,
+	0x6e, 0x04, 0x94, 0xee, 0x31, 0xf5, 0x27, 0x0f, 0x0a, 0xbf, 0x68, 0xa0, 0xef, 0x30, 0x77, 0xc7,
+	0x73, 0x85, 0xfc, 0x0a, 0x63, 0xf7, 0x42, 0xdf, 0x61, 0x7a, 0x16, 0x26, 0xed, 0x80, 0x58, 0x9c,
+	0x06, 0x59, 0x6d, 0x55, 0x5b, 0x4f, 0x1b, 0x2d, 0x50, 0x5f, 0x84, 0x14, 0x8a, 0x33, 0x3d, 0x27,
+	0xfb, 0xde, 0xaa, 0xb6, 0x3e, 0x6a, 0x4c, 0x22, 0xbc, 0xed, 0xe8, 0xf7, 0x61, 0xc2, 0xaa, 0xd3,
+	0xd0, 0xe7, 0xd9, 0x51, 0x41, 0xb3, 0x59, 0x7a, 0xf1, 0x6a, 0x65, 0xe4, 0xaf, 0x57, 0x2b, 0x1f,
+	0xb8, 0x1e, 0xdf, 0x0f, 0xab, 0x45, 0x9b, 0xd6, 0x4b, 0x36, 0x65, 0x75, 0xca, 0xd4, 0xdf, 0x35,
+	0xe6, 0x1c, 0x94, 0xf8, 0x51, 0x83, 0xb0, 0xe2, 0x53, 0xcf, 0xe7, 0x86, 0x22, 0x2f, 0x5c, 0x82,
+	0x5c, 0xa7, 0x4e, 0x06, 0x61, 0x0d, 0xea, 0x33, 0x52, 0x78, 0x04, 0x73, 0x3b, 0xcc, 0x7d, 0xda,
+	0x70, 0xe4, 0xe1, 0x86, 0xe3, 0x04, 0x84, 0xf5, 0x53, 0x79, 0x19, 0x80, 0x33, 0x66, 0x36, 0xc2,
+	0xea, 0x01, 0x39, 0x42, 0xa5, 0xd3, 0x46, 0x9a, 0x33, 0xf6, 0x18, 0x11, 0x85, 0x65, 0x58, 0xea,
+	0xc2, 0x2f, 0x12, 0xf7, 0x8f, 0x86, 0xf2, 0x36, 0x1c, 0xa7, 0x42, 0xb7, 0xfd, 0x4a, 0xb3, 0x12,
+	0x58, 0xf6, 0x01, 0x09, 0xce, 0xe6, 0xa2, 0x05, 0x98, 0xe4, 0x4d, 0x73, 0xdf, 0x62, 0xfb, 0xd2,
+	0x47, 0xc6, 0x04, 0x6f, 0x3e, 0xb0, 0xd8, 0xbe, 0xfe, 0x21, 0xa4, 0x45, 0xb8, 0x4c, 0xe1, 0x8d,
+	0xec, 0xd8, 0xaa, 0xb6, 0x3e, 0x53, 0x9e, 0x29, 0x62, 0x00, 0xb7, 0xa8, 0xe7, 0x57, 0x8e, 0x1a,
+	0xc4, 0x48, 0xd9, 0xea, 0x49, 0x5f, 0x83, 0x71, 0x0c, 0x62, 0x76, 0x7c, 0x55, 0x5b, 0x9f, 0x2a,
+	0x67, 0x8a, 0x2a, 0xa4, 0x8f, 0xc5, 0x9f, 0x21, 0xcf, 0x84, 0xd5, 0xd5, 0x1a, 0xb5, 0x0f, 0xa4,
+	0xb4, 0x09, 0x69, 0x35, 0x62, 0x50, 0xe0, 0x22, 0xa4, 0x78, 0xd3, 0xf4, 0x7c, 0x87, 0x34, 0xb3,
+	0x93, 0x52, 0x49, 0xde, 0xdc, 0x16, 0xa0, 0x72, 0x48, 0xd2, 0xe0, 0xc8, 0x21, 0xbf, 0x69, 0x70,
+	0x7e, 0x87, 0xb9, 0x5f, 0xef, 0x7b, 0x9c, 0xd4, 0x3c, 0xc6, 0xef, 0x1a, 0x5b, 0xe5, 0xeb, 0x7d,
+	0xdc, 0xb1, 0x06, 0x19, 0x12, 0xd8, 0xe5, 0xeb, 0xa6, 0x25, 0x3d, 0xab, 0x22, 0x30, 0x8d, 0xc8,
+	0x56, 0xf4, 0xda, 0x7d, 0x36, 0x1a, 0xf7, 0x99, 0x0e, 0x63, 0xbe, 0x55, 0x97, 0x5e, 0x49, 0x1b,
+	0xf8, 0xac, 0x5f, 0x84, 0x09, 0x76, 0x54, 0xaf, 0xd2, 0x1a, 0xba, 0x20, 0x6d, 0x28, 0x48, 0xcf,
+	0x41, 0xca, 0x21, 0xb6, 0x57, 0xb7, 0x6a, 0x0c, 0x4d, 0xce, 0x18, 0x11, 0xac, 0x2f, 0x41, 0xda,
+	0xb5, 0x98, 0x2c, 0x31, 0x65, 0x72, 0xca, 0xb5, 0xd8, 0x43, 0x01, 0x17, 0x4c, 0x58, 0xec, 0xb0,
+	0xa9, 0x65, 0xb1, 0xb0, 0xe0, 0x38, 0x66, 0x81, 0xb4, 0x70, 0xfa, 0xb8, 0xdd, 0x82, 0x65, 0x00,
+	0xdb, 0x8e, 0x5c, 0xaa, 0xb2, 0x4c, 0x60, 0xa4, 0x53, 0xff, 0xd4, 0x60, 0xbe, 0xe5, 0xd5, 0xdd,
+	0x90, 0xbf, 0x65, 0x1e, 0xcd, 0xc3, 0xb8, 0x4f, 0x7d, 0x9b, 0xa0, 0xaf, 0xc6, 0x0c, 0x09, 0xb4,
+	0x67, 0xd7, 0x58, 0x2c, 0xbb, 0xde, 0x71, 0xc2, 0x7c, 0x06, 0x97, 0xba, 0x99, 0x16, 0xf9, 0x6f,
+	0x19, 0xc0, 0x63, 0x66, 0x40, 0xea, 0xf4, 0x90, 0x38, 0x68, 0x65, 0xca, 0x48, 0x7b, 0xcc, 0x90,
+	0x88, 0xc2, 0x1e, 0xfa, 0x5e, 0x42, 0xf7, 0x02, 0x5a, 0x7f, 0x47, 0xee, 0x29, 0xac, 0xc1, 0xe5,
+	0x9e, 0x72, 0xa2, 0xec, 0x7e, 0xa6, 0xc1, 0xec, 0x0e, 0x73, 0xbf, 0xa2, 0x9c, 0xdc, 0xb7, 0xd8,
+	0xe3, 0xc0, 0xb3, 0xc9, 0x99, 0x75, 0x68, 0x08, 0xea, 0x96, 0x0e, 0x08, 0xe8, 0x97, 0x61, 0x5a,
+	0x3a, 0xd9, 0x0f, 0xeb, 0x55, 0x12, 0x60, 0x9c, 0xc6, 0x8c, 0x29, 0xc4, 0x3d, 0x42, 0x14, 0xe6,
+	0x76, 0xd8, 0x68, 0xd4, 0x8e, 0xa2, 0xdc, 0x46, 0xa8, 0xb0, 0x08, 0x0b, 0x09, 0xc5, 0x22, 0xa5,
+	0x7f, 0x1f, 0xc7, 0x92, 0x15, 0x67, 0xbb, 0xfe, 0x6e, 0x95, 0x91, 0xe0, 0x90, 0x38, 0xbb, 0x21,
+	0xaf, 0xd2, 0xd0, 0x77, 0x2a, 0xcd, 0x3e, 0x06, 0x2c, 0x01, 0xe6, 0xa8, 0x8c, 0xb9, 0x4c, 0xda,
+	0x94, 0x40, 0x60, 0xc8, 0x8b, 0x30, 0x47, 0x15, 0x33, 0x93, 0x0a, 0x67, 0xb5, 0x77, 0xae, 0xf3,
+	0xf4, 0x44, 0x4e, 0x45, 0xde, 0xff, 0x14, 0x72, 0x89, 0xfb, 0x32, 0x7d, 0x88, 0xe7, 0xee, 0x73,
+	0x65, 0x6a, 0x36, 0x46, 0xb6, 0x79, 0x72, 0xae, 0x7f, 0x04, 0x0b, 0x09, 0x6a, 0x51, 0xae, 0x21,
+	0x23, 0x4e, 0x16, 0x90, 0x74, 0x3e, 0x46, 0x7a, 0xdf, 0x62, 0x4f, 0x19, 0x71, 0xf4, 0x63, 0x28,
+	0x24, 0xc8, 0xc8, 0xde, 0x1e, 0xb1, 0xb9, 0x77, 0x48, 0x90, 0x81, 0x0c, 0xc2, 0x14, 0x4e, 0xa4,
+	0xa2, 0x9a, 0x48, 0x57, 0x87, 0x98, 0x48, 0xdb, 0x3e, 0x37, 0xf2, 0x31, 0x89, 0x77, 0x5b, 0x7c,
+	0xa3, 0xc4, 0xf8, 0x62, 0x80, 0x6c, 0xd9, 0x6b, 0xa6, 0x51, 0xfb, 0xde, 0xbc, 0xb0, 0x03, 0xe9,
+	0x14, 0x66, 0x0e, 0xad, 0x5a, 0x48, 0xcc, 0x80, 0xd8, 0xc4, 0x13, 0x85, 0x82, 0xe1, 0xdf, 0x7c,
+	0x70, 0xca, 0x29, 0xfa, 0xef, 0xab, 0x95, 0x0b, 0x47, 0x56, 0xbd, 0x76, 0xa7, 0x10, 0x67, 0x57,
+	0x30, 0x32, 0x88, 0x30, 0x14, 0xac, 0x5f, 0x83, 0x09, 0xc6, 0x2d, 0x1e, 0xca, 0x4e, 0x39, 0x53,
+	0xbe, 0x50, 0x54, 0x7b, 0x84, 0xba, 0xf1, 0x04, 0x0f, 0x0d, 0x75, 0x49, 0x5f, 0x81, 0x29, 0x69,
+	0x22, 0xde, 0x52, 0x2d, 0x00, 0x10, 0xb5, 0x25, 0x30, 0xfa, 0x55, 0x98, 0x95, 0x17, 0xc4, 0xb0,
+	0x95, 0xe5, 0x97, 0x42, 0xcb, 0x33, 0x88, 0xae, 0x30, 0xf6, 0x08, 0xbb, 0x54, 0x6c, 0xd4, 0xa5,
+	0xfb, 0x8f, 0xba, 0xc2, 0x15, 0x58, 0xeb, 0x93, 0xd8, 0x51, 0x01, 0xfc, 0x30, 0x86, 0x2b, 0x43,
+	0xfc, 0xde, 0xb6, 0x3f, 0x38, 0xff, 0x45, 0xb1, 0x11, 0xdf, 0x21, 0x81, 0x4a, 0x7e, 0x05, 0x09,
+	0x63, 0xe4, 0x93, 0x99, 0x18, 0x4b, 0x19, 0x89, 0xde, 0x52, 0x55, 0x9e, 0x83, 0x94, 0x72, 0x70,
+	0xa0, 0x7a, 0x6e, 0x04, 0xeb, 0x57, 0x60, 0xa6, 0xf5, 0xac, 0x9c, 0x36, 0x2e, 0x59, 0xb4, 0xb0,
+	0xd2, 0x6f, 0x27, 0x6b, 0xd3, 0xc4, 0x5b, 0xad, 0x4d, 0xc2, 0xca, 0x3a, 0x61, 0xcc, 0x72, 0xa5,
+	0xe3, 0xd3, 0x46, 0x0b, 0xd4, 0x2f, 0x01, 0x08, 0x87, 0xab, 0xfa, 0x4d, 0x4b, 0x3d, 0x3d, 0x5f,
+	0x95, 0xed, 0x55, 0x98, 0xf5, 0x7c, 0x53, 0xf5, 0x7e, 0x59, 0xab, 0xb2, 0xe0, 0x32, 0x9e, 0xdf,
+	0x5e, 0xa0, 0xb1, 0x01, 0x3a, 0x85, 0x37, 0xa2, 0x01, 0x1a, 0x8f, 0xea, 0xf4, 0x80, 0x05, 0x66,
+	0x09, 0xd2, 0xbc, 0x69, 0xd2, 0xc0, 0x73, 0x3d, 0x3f, 0x9b, 0x91, 0xea, 0xf0, 0xe6, 0x2e, 0xc2,
+	0xa2, 0x71, 0x5a, 0x8c, 0x11, 0x9e, 0x9d, 0xc1, 0x03, 0x09, 0x88, 0xf4, 0x23, 0x87, 0xc4, 0xe7,
+	0x6a, 0x02, 0xcd, 0xa2, 0x78, 0x40, 0x94, 0x1c, 0x42, 0xef, 0x43, 0xa1, 0x77, 0x06, 0x44, 0x89,
+	0xf2, 0x10, 0x77, 0x97, 0x8d, 0x2a, 0x0d, 0xf8, 0x13, 0x1e, 0xda, 0x07, 0x5b, 0x5b, 0x95, 0x6f,
+	0xfa, 0xaf, 0x8e, 0xfd, 0x86, 0xfa, 0x12, 0x4e, 0xae, 0x38, 0xb7, 0x48, 0xd4, 0x21, 0x0e, 0x7c,
+	0x83, 0xec, 0x85, 0xbe, 0x83, 0x57, 0x88, 0xf3, 0x56, 0xd2, 0x64, 0x3e, 0x09, 0x6e, 0xd1, 0x1e,
+	0x22, 0x3b, 0x71, 0x46, 0x62, 0xd5, 0x22, 0x52, 0xc8, 0xe3, 0x34, 0xee, 0x90, 0x1b, 0xe9, 0xf5,
+	0x5c, 0x43, 0xad, 0xe5, 0xc2, 0x6b, 0x58, 0x9c, 0x3c, 0x94, 0x2f, 0x1d, 0xf7, 0xc4, 0x3b, 0x47,
+	0x1f, 0xed, 0x6c, 0xd0, 0x3b, 0xdf, 0x51, 0x50, 0xcb, 0xa9, 0x72, 0xa9, 0xd8, 0xf7, 0x45, 0xa7,
+	0x98, 0x14, 0xb3, 0x39, 0x26, 0x92, 0xdc, 0x38, 0x17, 0x24, 0xf0, 0x6a, 0x46, 0x77, 0xd7, 0xad,
+	0x65, 0x41, 0xf9, 0xbf, 0x69, 0x18, 0xdd, 0x61, 0xae, 0xfe, 0x93, 0x06, 0xe7, 0x3b, 0x17, 0xaa,
+	0x9b, 0x03, 0x74, 0xe9, 0xb6, 0xaa, 0xe4, 0x3e, 0x39, 0x03, 0x51, 0xb4, 0xdf, 0xfc, 0xa8, 0xc1,
+	0xb9, 0x8e, 0xf7, 0x83, 0xf2, 0x90, 0x1c, 0xdb, 0x68, 0x72, 0x77, 0x4e, 0x4f, 0x13, 0x29, 0xf1,
+	0xab, 0x06, 0x17, 0x7b, 0xec, 0x50, 0xb7, 0x06, 0xb3, 0xed, 0x4e, 0x99, 0xfb, 0xfc, 0xac, 0x94,
+	0x91, 0x5a, 0x87, 0x30, 0x1d, 0xdb, 0xa5, 0x8a, 0x83, 0x39, 0xb6, 0xdf, 0xcf, 0x7d, 0x7c, 0xba,
+	0xfb, 0x91, 0xdc, 0xe7, 0x1a, 0x64, 0x7b, 0xee, 0x43, 0x77, 0x86, 0x63, 0xda, 0x8d, 0x36, 0xb7,
+	0x79, 0x76, 0xda, 0x48, 0xb9, 0x67, 0x1a, 0x2c, 0xf4, 0x9a, 0x55, 0xb7, 0x4f, 0xcb, 0x3f, 0x22,
+	0xcd, 0x6d, 0x9c, 0x99, 0x34, 0xd2, 0xec, 0x3b, 0x98, 0x49, 0xbc, 0xd8, 0x5d, 0x1f, 0xcc, 0x34,
+	0x4e, 0x91, 0xbb, 0x75, 0x5a, 0x8a, 0x58, 0x21, 0x75, 0xbc, 0xd8, 0x0f, 0x51, 0x48, 0x49, 0x9a,
+	0x61, 0x0a, 0xa9, 0xd7, 0x0b, 0xbf, 0xfe, 0x3d, 0xcc, 0x26, 0x3f, 0x87, 0xdc, 0x18, 0xcc, 0x2e,
+	0x41, 0x92, 0xbb, 0x7d, 0x6a, 0x92, 0xf6, 0x18, 0x24, 0x06, 0xd4, 0x10, 0x31, 0x88, 0x53, 0x0c,
+	0x13, 0x83, 0xee, 0x63, 0x0b, 0x9b, 0x6a, 0xe7, 0xd0, 0xba, 0x39, 0x4c, 0x23, 0x48, 0x10, 0x0d,
+	0xd3, 0x54, 0x7b, 0x8e, 0x29, 0xec, 0x67, 0x3d, 0x66, 0xd4, 0xad, 0x61, 0xa3, 0x9b, 0xa4, 0x1c,
+	0xa6, 0x9f, 0xf5, 0x9f, 0x3d, 0x9b, 0x5f, 0xbe, 0x78, 0x9d, 0xd7, 0x5e, 0xbe, 0xce, 0x6b, 0x7f,
+	0xbf, 0xce, 0x6b, 0x3f, 0xbf, 0xc9, 0x8f, 0xbc, 0x7c, 0x93, 0x1f, 0xf9, 0xe3, 0x4d, 0x7e, 0xe4,
+	0xdb, 0x1b, 0x6d, 0xfb, 0x9a, 0xe0, 0x7d, 0x4d, 0x7e, 0xd7, 0x6b, 0x89, 0x29, 0x35, 0x4b, 0xed,
+	0x5f, 0x08, 0xc5, 0xfa, 0x56, 0x9d, 0xc0, 0x8f, 0x70, 0x37, 0xff, 0x0f, 0x00, 0x00, 0xff, 0xff,
+	0x8e, 0xcd, 0x56, 0x06, 0x3c, 0x14, 0x00, 0x00,
 }
 
 // Reference imports to suppress errors if they are not otherwise used.
@@ -1489,6 +1584,7 @@ type MsgClient interface {
 	MigrateTssFunds(ctx context.Context, in *MsgMigrateTssFunds, opts ...grpc.CallOption) (*MsgMigrateTssFundsResponse, error)
 	AbortStuckCCTX(ctx context.Context, in *MsgAbortStuckCCTX, opts ...grpc.CallOption) (*MsgAbortStuckCCTXResponse, error)
 	RefundAbortedCCTX(ctx context.Context, in *MsgRefundAbortedCCTX, opts ...grpc.CallOption) (*MsgRefundAbortedCCTXResponse, error)
+	UpdateRateLimiterFlags(ctx context.Context, in *MsgUpdateRateLimiterFlags, opts ...grpc.CallOption) (*MsgUpdateRateLimiterFlagsResponse, error)
 }
 
 type msgClient struct {
@@ -1598,6 +1694,15 @@ func (c *msgClient) RefundAbortedCCTX(ctx context.Context, in *MsgRefundAbortedC
 	return out, nil
 }
 
+func (c *msgClient) UpdateRateLimiterFlags(ctx context.Context, in *MsgUpdateRateLimiterFlags, opts ...grpc.CallOption) (*MsgUpdateRateLimiterFlagsResponse, error) {
+	out := new(MsgUpdateRateLimiterFlagsResponse)
+	err := c.cc.Invoke(ctx, "/zetachain.zetacore.crosschain.Msg/UpdateRateLimiterFlags", in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
 // MsgServer is the server API for Msg service.
 type MsgServer interface {
 	AddToOutTxTracker(context.Context, *MsgAddToOutTxTracker) (*MsgAddToOutTxTrackerResponse, error)
@@ -1611,6 +1716,7 @@ type MsgServer interface {
 	MigrateTssFunds(context.Context, *MsgMigrateTssFunds) (*MsgMigrateTssFundsResponse, error)
 	AbortStuckCCTX(context.Context, *MsgAbortStuckCCTX) (*MsgAbortStuckCCTXResponse, error)
 	RefundAbortedCCTX(context.Context, *MsgRefundAbortedCCTX) (*MsgRefundAbortedCCTXResponse, error)
+	UpdateRateLimiterFlags(context.Context, *MsgUpdateRateLimiterFlags) (*MsgUpdateRateLimiterFlagsResponse, error)
 }
 
 // UnimplementedMsgServer can be embedded to have forward compatible implementations.
@@ -1650,6 +1756,9 @@ func (*UnimplementedMsgServer) AbortStuckCCTX(ctx context.Context, req *MsgAbort
 func (*UnimplementedMsgServer) RefundAbortedCCTX(ctx context.Context, req *MsgRefundAbortedCCTX) (*MsgRefundAbortedCCTXResponse, error) {
 	return nil, status.Errorf(codes.Unimplemented, "method RefundAbortedCCTX not implemented")
 }
+func (*UnimplementedMsgServer) UpdateRateLimiterFlags(ctx context.Context, req *MsgUpdateRateLimiterFlags) (*MsgUpdateRateLimiterFlagsResponse, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method UpdateRateLimiterFlags not implemented")
+}
 
 func RegisterMsgServer(s grpc1.Server, srv MsgServer) {
 	s.RegisterService(&_Msg_serviceDesc, srv)
@@ -1853,6 +1962,24 @@ func _Msg_RefundAbortedCCTX_Handler(srv interface{}, ctx context.Context, dec fu
 	return interceptor(ctx, in, info, handler)
 }
 
+func _Msg_UpdateRateLimiterFlags_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(MsgUpdateRateLimiterFlags)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(MsgServer).UpdateRateLimiterFlags(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/zetachain.zetacore.crosschain.Msg/UpdateRateLimiterFlags",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(MsgServer).UpdateRateLimiterFlags(ctx, req.(*MsgUpdateRateLimiterFlags))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
 var _Msg_serviceDesc = grpc.ServiceDesc{
 	ServiceName: "zetachain.zetacore.crosschain.Msg",
 	HandlerType: (*MsgServer)(nil),
@@ -1901,6 +2028,10 @@ var _Msg_serviceDesc = grpc.ServiceDesc{
 			MethodName: "RefundAbortedCCTX",
 			Handler:    _Msg_RefundAbortedCCTX_Handler,
 		},
+		{
+			MethodName: "UpdateRateLimiterFlags",
+			Handler:    _Msg_UpdateRateLimiterFlags_Handler,
+		},
 	},
 	Streams:  []grpc.StreamDesc{},
 	Metadata: "crosschain/tx.proto",
@@ -2857,6 +2988,69 @@ func (m *MsgRefundAbortedCCTXResponse) MarshalToSizedBuffer(dAtA []byte) (int, e
 	return len(dAtA) - i, nil
 }
 
+func (m *MsgUpdateRateLimiterFlags) 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 *MsgUpdateRateLimiterFlags) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *MsgUpdateRateLimiterFlags) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	{
+		size, err := m.RateLimiterFlags.MarshalToSizedBuffer(dAtA[:i])
+		if err != nil {
+			return 0, err
+		}
+		i -= size
+		i = encodeVarintTx(dAtA, i, uint64(size))
+	}
+	i--
+	dAtA[i] = 0x12
+	if len(m.Creator) > 0 {
+		i -= len(m.Creator)
+		copy(dAtA[i:], m.Creator)
+		i = encodeVarintTx(dAtA, i, uint64(len(m.Creator)))
+		i--
+		dAtA[i] = 0xa
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *MsgUpdateRateLimiterFlagsResponse) 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 *MsgUpdateRateLimiterFlagsResponse) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *MsgUpdateRateLimiterFlagsResponse) 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
@@ -3301,6 +3495,30 @@ func (m *MsgRefundAbortedCCTXResponse) Size() (n int) {
 	return n
 }
 
+func (m *MsgUpdateRateLimiterFlags) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	l = len(m.Creator)
+	if l > 0 {
+		n += 1 + l + sovTx(uint64(l))
+	}
+	l = m.RateLimiterFlags.Size()
+	n += 1 + l + sovTx(uint64(l))
+	return n
+}
+
+func (m *MsgUpdateRateLimiterFlagsResponse) 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
 }
@@ -6223,6 +6441,171 @@ func (m *MsgRefundAbortedCCTXResponse) Unmarshal(dAtA []byte) error {
 	}
 	return nil
 }
+func (m *MsgUpdateRateLimiterFlags) 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: MsgUpdateRateLimiterFlags: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: MsgUpdateRateLimiterFlags: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Creator", 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.Creator = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field RateLimiterFlags", 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 err := m.RateLimiterFlags.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 *MsgUpdateRateLimiterFlagsResponse) 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: MsgUpdateRateLimiterFlagsResponse: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: MsgUpdateRateLimiterFlagsResponse: 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