Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

F/add stake grants #20

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,5 @@
npm-debug.log*
yarn-debug.log*
yarn-error.log*

.idea
4 changes: 4 additions & 0 deletions docs/develop/modules/injective/exchange/02_other_concepts.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,7 @@ Governance approves a **FeeDiscountProposal** which defines a fee discount **sch
- If the fee discount proposal was passed less than 30 days ago, i.e. `BucketCount * BucketDuration` hasn't passed yet since the creation of the proposal, the fee volume requirement is ignored so we don't unfairly penalize market makers who onboard immediately.

Internally the trading volumes are stored in buckets, typically 30 buckets each lasting 24 hours. When a bucket is older than 30 days, it gets removed. Additionally for performance reasons there is a cache for retrieving the fee discount tier for an account. This cache is updated every 24 hours.

### Stake Delegations/Grants

Staked INJ requirements for fee discount tiers can be met through grants from other addresses that have staked their INJ. The total staked INJ value used for fee discount calculations is `OwnStake + StakeGrantedFromGranter - TotalStakeGrantedToOthers`. Note that although several grants can be made to a single address, **only one grant can be activated** for use at a single time. However, a single address can have multiple grants made to other addresses at the same time. Note that only INJ staked with 25 validators is used to calculate `OwnStake` for stake grant purposes. To ensure all staked INJ can be utilized for grants, stake with 25 or fewer validators. Granted stake cannot be regranted.
37 changes: 37 additions & 0 deletions docs/develop/modules/injective/exchange/03_state.md
Original file line number Diff line number Diff line change
Expand Up @@ -592,3 +592,40 @@ enum ExecutionType {
LimitMatchNewOrder = 4;
}
```

## GrantAuthorization

`GrantAuthorization` is used to track the grantee's address and amount of the granted stake that has been authorized by the granter for trading fee discounts.

```protobuf
type GrantAuthorization struct {
Grantee string
Amount math.Int
}

```

## ActiveGrant

`ActiveGrant` is used to track the granter's address and amount of the granted stake (for trading fee discounts) in the grant that has been activated by the grantee.

```protobuf
type ActiveGrant struct {
Granter string
Amount math.Int
}

```

## EffectiveGrant

`EffectiveGrant` is used to track the total amount of stake a granter has authorized in stake grants for trading fee discounts.

```protobuf
type EffectiveGrant struct {
Granter string
NetGrantedStake math.Int
IsValid bool
}

```
78 changes: 50 additions & 28 deletions docs/develop/modules/injective/exchange/04_state_transitions.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,11 @@ This document describes the state transition operations pertaining to:
- Derivative market param update proposal
- Trading rewards launch proposal
- Trading rewards update proposal
- Begin-blocker
- End-blocker
- Fee discount schedule proposal
- Stake grant authorizations
- Stake grant activation

## Deposit into exchange module account
## Deposit Into Exchange Module Account

Deposit action is carried out by `MsgDeposit` which consists of `Sender`, `SubaccountId` and `Amount` fields.

Expand All @@ -51,7 +52,7 @@ Deposit action is carried out by `MsgDeposit` which consists of `Sender`, `Subac
- Increment deposit amount for the `subaccountID` by `msg.Amount`
- Emit event for `EventSubaccountDeposit` with `msg.Sender`, `subaccountID` and `msg.Amount`

## Withdraw from exchange module account
## Withdraw From Exchange Module Account

Withdraw action is carried out by `MsgWithdraw` which consists of `Sender`, `SubaccountId` and `Amount` fields.

Expand All @@ -65,7 +66,7 @@ Withdraw action is carried out by `MsgWithdraw` which consists of `Sender`, `Sub
- Send coins from `exchange` module to `msg.Sender`
- Emit event for `EventSubaccountWithdraw` with `subaccountID`, `msg.Sender`, and `msg.Amount`

## Instant spot market launch
## Instant Spot Market Launch

Instant spot market launch action is carried out by `MsgInstantSpotMarketLaunch` which consists of `Sender`, `Ticker`, `BaseDenom`, `QuoteDenom`, `MinPriceTickSize` and `MinQuantityTickSize` fields.

Expand All @@ -77,7 +78,7 @@ Instant spot market launch action is carried out by `MsgInstantSpotMarketLaunch`
- Send instant listing fee(params.SpotMarketInstantListingFee) from `msg.Sender` to `exchange` module account
- Lastly send the instant listing fee to the community spend pool

## Instant perpetual market launch
## Instant Perpetual Market Launch

Instant perpetual market launch action is carried out by `MsgInstantPerpetualMarketLaunch` which consists of `Sender`, `Ticker`, `QuoteDenom`, `OracleBase`, `OracleQuote`, `OracleScaleFactor`, `OracleType`, `MakerFeeRate`, `TakerFeeRate`, `InitialMarginRatio`, `MaintenanceMarginRatio`, `MinPriceTickSize` and `MinQuantityTickSize` fields.

Expand All @@ -89,7 +90,7 @@ Instant perpetual market launch action is carried out by `MsgInstantPerpetualMar
- Launch perpetual market with required params on `msg` object and revert if fail
- Lastly send the instant listing fee to the community spend pool

## Instant expiry futures market launch
## Instant Expiry Futures Market Launch

Instant expiry futures market launch action is carried out by `MsgInstantExpiryFuturesMarketLaunch` which consists of `Sender`, `Ticker`, `QuoteDenom`, `OracleBase`, `OracleQuote`, `OracleScaleFactor`, `OracleType`, `Expiry`, `MakerFeeRate`, `TakerFeeRate`, `InitialMarginRatio`, `MaintenanceMarginRatio`, `MinPriceTickSize` and `MinQuantityTickSize` fields.

Expand All @@ -102,7 +103,7 @@ Instant expiry futures market launch action is carried out by `MsgInstantExpiryF
- Trigger `EventExpiryFuturesMarketUpdate` event with market info
- Lastly send the instant listing fee to the community spend pool

## Spot limit order creation
## Spot Limit Order Creation

Spot limit order creation is carried out by `MsgCreateSpotLimitOrder` which consists of `Sender` and `Order`.

Expand All @@ -119,15 +120,15 @@ Spot limit order creation is carried out by `MsgCreateSpotLimitOrder` which cons

**Note:** The order in transient store is executed on endblocker or if not, put on long-live store.

## Batch creation of spot limit orders
## Batch Creation of Spot Limit Orders

Batch creation of spot limit orders is carried out by `MsgBatchCreateSpotLimitOrders` which consists of `Sender` and `Orders`.

**Steps**

- Loop over the `msg.Orders` and create spot limit order as in `MsgCreateSpotLimitOrder`

## Spot market order creation
## Spot Market Order Creation

Spot market order creation is carried out by `MsgCreateSpotMarketOrder` which consists of `Sender` and `Order`.

Expand All @@ -143,7 +144,7 @@ Spot market order creation is carried out by `MsgCreateSpotMarketOrder` which co
- Decrement deposit's AvailableBalance by the balance hold
- Store the order in the transient spot market order store and transient market indicator store

## Cancel spot order
## Cancel Spot Order

Spot order cancellation is carried out by `MsgCancelSpotOrder` which consists of `Sender` and `MarketId`, `SubaccountId` and `OrderHash`.

Expand All @@ -157,15 +158,15 @@ Spot order cancellation is carried out by `MsgCancelSpotOrder` which consists of
- Delete the order state from ordersStore and ordersIndexStore
- Emit `EventCancelSpotOrder` event with marketID and order info

## Batch cancellation of spot orders
## Batch Cancellation of Spot Orders

Batch cancellation of spot orders is carried out by `MsgBatchCancelSpotOrders` which consists of `Sender` and `Data`.

**Steps**

- Loop over the `msg.Data` and cancel spot order as in `MsgCancelSpotOrder`

## Derivative limit order creation
## Derivative Limit Order Creation

Derivative limit order creation is carried out by `MsgCreateDerivativeLimitOrder` which consists of `Sender` and `Order`.

Expand All @@ -188,15 +189,15 @@ Derivative limit order creation is carried out by `MsgCreateDerivativeLimitOrder
- Store the order in the transient limit order store and transient market indicator store
- Update orderbook metadata for subaccount

## Batch creation of derivative limit orders
## Batch Creation of Derivative Limit Orders

Batch creation of derivative limit orders is carried out by `MsgBatchCreateDerivativeLimitOrders` which consists of `Sender` and `Orders`.

**Steps**

- Loop over the `msg.Orders` and create derivative limit order as in `MsgCreateDerivativeLimitOrder`

## Derivative market order creation
## Derivative Market Order Creation

Derivative market order creation is carried out by `MsgCreateDerivativeMarketOrder` which consists of `Sender` and `Order`.

Expand All @@ -222,7 +223,7 @@ Derivative market order creation is carried out by `MsgCreateDerivativeMarketOrd
- For an opposing position, if AggregateVanillaQuantity > position.quantity - AggregateReduceOnlyQuantity - order.FillableQuantity, the new reduce-only order might invalidate some existing reduce-only orders or itself be invalid, and do operations for that.
- Store the order in the transient derivative market order store and transient market indicator store

## Cancel derivative order
## Cancel Derivative Order

Derivative order cancellation is carried out by `MsgCancelDerivativeOrder` which consists of `Sender`, `MarketId`, `SubaccountId` and `OrderHash`.

Expand All @@ -237,15 +238,15 @@ Derivative order cancellation is carried out by `MsgCancelDerivativeOrder` which
- Update orderbook metadata for subaccount
- Emit `EventCancelDerivativeOrder` event with marketID and order info

## Batch cancellation of derivative orders
## Batch Cancellation of Derivative Orders

Batch cancellation of derivative orders is carried out by `MsgBatchCancelDerivativeOrders` which consists of `Sender` and `Data`.

**Steps**

- Loop over the `msg.Data` and cancel spot order as in `MsgCancelDerivativeOrder`

## Batch order updates
## Batch Order Updates

Batch updating orders is carried out by `MsgBatchUpdateOrders` which consists of `Sender` and `Orders`.

Expand All @@ -257,7 +258,7 @@ Batch updating orders is carried out by `MsgBatchUpdateOrders` which consists of
- Loop over the `msg.SpotOrdersToCreate` and create spot limit order as in `MsgCreateSpotOrder`. If the creation fails, continue to next order. Successful creations are reflected in the `MsgBatchUpdateOrdersResponse` as `SpotOrderHashes`.
- Loop over the `msg.DerivativeOrdersToCreate` and create derivative limit order as in `MsgCreateDerivativeOrder`. If the creation fails, continue to next order. Successful creations are reflected in the `MsgBatchUpdateOrdersResponse` as `DerivativeOrderHashes`.

## Transfer between subaccounts
## Transfer Between Subaccounts

Transfer between subaccounts is executed by `MsgSubaccountTransfer` which consists of `Sender`, `SourceSubaccountId`, `DestinationSubaccountId` and `Amount`.

Expand All @@ -269,7 +270,7 @@ Transfer between subaccounts is executed by `MsgSubaccountTransfer` which consis

**Note:** With subaccount transfer, no need to transfer actual coins from bank module but changing the records are enough.

## Transfer to external account
## Transfer to External Account

Transfer to external account is executed by `MsgExternalTransfer` which consists of `Sender`, `SourceSubaccountId`, `DestinationSubaccountId` and `Amount`.

Expand All @@ -284,7 +285,7 @@ Transfer to external account is executed by `MsgExternalTransfer` which consists
1. Event should be different for subaccount transfer and external transfer.
2. There's no difference in subaccount transfer and external transfer, still need to keep different messages?

## Liquidating a position
## Liquidating a Position

Liquidating a position is executed by `MsgLiquidatePosition` which consists of `Sender`, `SubaccountId`, `MarketId` and `Order`.

Expand Down Expand Up @@ -315,7 +316,7 @@ Liquidating a position is executed by `MsgLiquidatePosition` which consists of `
- If market is a perpetual market, upgrade VWAP data based on liquidation price and quantity
- If there's remaining in liquidation order, return back remains by cancelling order

## Increasing position margin
## Increasing Position Margin

Increasing position margin is executed by `MsgIncreasePositionMargin` which consists of `Sender`, `SourceSubaccountId`, `DestinationSubaccountId`, `MarketId` and `Amount`.

Expand All @@ -329,7 +330,7 @@ Increasing position margin is executed by `MsgIncreasePositionMargin` which cons
- Reduce deposit amount of `sourceSubaccountID` by `msg.Amount`
- Increase position margin by `msg.Amount` and update position in the store

## Exchange enable proposal
## Exchange Enable Proposal

The enable of market type is done by `ExchangeEnableProposal` which consists of `Title`, `Description` and `ExchangeType`.

Expand All @@ -339,7 +340,7 @@ The enable of market type is done by `ExchangeEnableProposal` which consists of
- If `p.ExchangeType` is spot market, enable spot exchange
- If `p.ExchangeType` is derivative market, enable derivative market

## Spot market launch proposal
## Spot Market Launch Proposal

Launch of spot market is handled by `SpotMarketLaunchProposal` which consists of `Title`, `Description`, `Ticker`, `BaseDenom`, `QuoteDenom`, `MinPriceTickSize` and `MinQuantityTickSize` fields.

Expand All @@ -351,7 +352,7 @@ Launch of spot market is handled by `SpotMarketLaunchProposal` which consists of
- Calculate RelayerFeeShareRate based on exchange module params. **Note:** for INJ currency, relayer share rate is set to 100%
- Save spot market with calculated `ticker`, `baseDenom`, `quoteDenom`, `exchangeParams.DefaultSpotMakerFeeRate`, `exchangeParams.DefaultSpotTakerFeeRate`, `relayerFeeShareRate`, `minPriceTickSize`, `minQuantityTickSize`, `marketID`, and `MarketStatus_Active`.

## Perpetual market launch proposal
## Perpetual Market Launch Proposal

Perpetual market launch is handled by `PerpetualMarketLaunchProposal` which consists of `Title`, `Description`, `Ticker`, `QuoteDenom`, `OracleBase`, `OracleQuote`, `OracleScaleFactor`, `OracleType`, `MakerFeeRate`, `TakerFeeRate`, `InitialMarginRatio`, `MaintenanceMarginRatio`, `MinPriceTickSize` and `MinQuantityTickSize` fields.

Expand All @@ -366,7 +367,7 @@ Perpetual market launch is handled by `PerpetualMarketLaunchProposal` which cons
- Calculate `defaultFundingInterval`, `nextFundingTimestamp`, `relayerFeeShareRate` from `exchange` module params
- Execute `SetDerivativeMarketWithInfo` to set market info into the storage with `market`, `marketInfo` and `funding` objects

## Expiry futures market launch proposal
## Expiry Futures Market Launch Proposal

Expiry futures market launch is handled by `ExpiryFuturesMarketLaunchProposal` which consists of `Title`, `Description`, `Ticker`, `QuoteDenom`, `OracleBase`, `OracleQuote`, `OracleScaleFactor`, `OracleType`, `Expiry`, `MakerFeeRate`, `TakerFeeRate`, `InitialMarginRatio`, `MaintenanceMarginRatio`, `MinPriceTickSize` and `MinQuantityTickSize` fields.

Expand All @@ -382,7 +383,7 @@ Expiry futures market launch is handled by `ExpiryFuturesMarketLaunchProposal` w
- Calculate RelayerFeeShareRate based on exchange module params. **Note:** for INJ currency, relayer share rate is set to 100%
- Execute `SetDerivativeMarketWithInfo` to set market info into the storage with `market`, `marketInfo` objects **Note:** TwapStartTimestamp is set to `expiry - thirtyMinutesInSeconds`.

## Spot market param update proposal
## Spot Market Param Update Proposal

The update of spot market param is handled by `SpotMarketParamUpdateProposal` which consists of `Title`, `Description`, `MarketId`, `MakerFeeRate`, `TakerFeeRate`, `RelayerFeeShareRate`, `MinPriceTickSize`, `MinQuantityTickSize` and `Status`.

Expand All @@ -393,7 +394,7 @@ The update of spot market param is handled by `SpotMarketParamUpdateProposal` wh
- Reset the params for `MakerFeeRate`, `TakerFeeRate`, `RelayerFeeShareRate`, `MinPriceTickSize`, `MinQuantityTickSize` and `Status` if not empty, if empty keep as it is.
- Validate `MakerFeeRate` is bigger than `TakerFeeRate`.

## Derivative market param update proposal
## Derivative Market Param Update Proposal

Derivative market param update is handled by `DerivativeMarketParamUpdateProposal` which consists of `Title`, `Description`, `MarketId`, `InitialMarginRatio`, `MaintenanceMarginRatio`, `MakerFeeRate`, `TakerFeeRate`, `RelayerFeeShareRate`, `MinPriceTickSize`, `MinQuantityTickSize` and `Status`.

Expand Down Expand Up @@ -445,3 +446,24 @@ Derivative market param update is handled by `DerivativeMarketParamUpdateProposa
- Set the first fee paid bucket timestamp as the current block time
- Set New Fee Discount Schedule, delete it along with Market Qualifications
- Set New Market Qualifications

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Add missing steps for Fee Discount Schedule Proposal

The section "Fee Discount Schedule Proposal" appears incomplete. While the heading is added, the steps are missing from the section content.

Would you like me to help draft the missing steps for the Fee Discount Schedule Proposal section? The steps should align with the existing format and detail the process of proposing and implementing fee discount schedules.

## Stake Grant Authorizations

**Steps**

- Check if an existing grant from the granter already exists for the grantee
- Calculate the new total amount of stake granted to the grantee by subtracting the existing grant amounts and adding the new grant amounts (essentially overwrites the existing grant amounts with the new grant amounts)
- Ensure valid grant authorizations by making sure total amount granted is less than or equal to total amount staked by granter
- Update grant amounts for grantee
- Set grant to active if the current active grant is from the same granter or if there is no current active grant
- Emit `EventGrantAuthorizations` with granter and grants


## Stake Grant Activation

**Steps**

- Check to make sure grant from granter to grantee exists
- Check to make sure granter is not granting more than their total staked amount
- If grant amount is 0, delete the grant, otherwise write new grant amount to store
- Emit `EventGrantActivation` with grantee, granter, and amount
Comment on lines +462 to +469
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Improve clarity of Stake Grant Activation section

The section needs more context about when and why stake grants are activated. Additionally, some steps need clarification:

  1. Step about checking grant existence should specify where to check
  2. The grant amount validation step needs more detail
  3. The deletion condition should be explained

Consider enhancing the section like this:

 ## Stake Grant Activation
+
+Stake grant activation is the process of enabling a previously authorized grant. 
+Only one grant can be active at a time for a grantee.
 
 **Steps**
 
-Check to make sure grant from granter to grantee exists
+- Verify the grant exists in the GrantAuthorization store for the granter-grantee pair
-Check to make sure granter is not granting more than their total staked amount
+- Validate that the granter's total granted amount (including this grant) does not exceed their total staked tokens
-If grant amount is 0, delete the grant, otherwise write new grant amount to store
+- If the grant amount is 0:
+  - Delete the grant from the GrantAuthorization store
+  - Clean up any associated metadata
+- Otherwise:
+  - Update the grant amount in the store
+  - Update the active grant status
 - Emit `EventGrantActivation` with grantee, granter, and amount
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
## Stake Grant Activation
**Steps**
- Check to make sure grant from granter to grantee exists
- Check to make sure granter is not granting more than their total staked amount
- If grant amount is 0, delete the grant, otherwise write new grant amount to store
- Emit `EventGrantActivation` with grantee, granter, and amount
## Stake Grant Activation
Stake grant activation is the process of enabling a previously authorized grant.
Only one grant can be active at a time for a grantee.
**Steps**
- Verify the grant exists in the GrantAuthorization store for the granter-grantee pair
- Validate that the granter's total granted amount (including this grant) does not exceed their total staked tokens
- If the grant amount is 0:
- Delete the grant from the GrantAuthorization store
- Clean up any associated metadata
- Otherwise:
- Update the grant amount in the store
- Update the active grant status
- Emit `EventGrantActivation` with grantee, granter, and amount
🧰 Tools
🪛 Markdownlint

464-464: null
Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)

38 changes: 36 additions & 2 deletions docs/develop/modules/injective/exchange/05_messages.md
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,6 @@ type MsgLiquidatePosition struct {
`MsgIncreasePositionMargin` describes a message to increase margin of an account.

```go
// A Cosmos-SDK MsgIncreasePositionMargin
type MsgIncreasePositionMargin struct {
Sender string
SourceSubaccountId string
Expand All @@ -417,7 +416,6 @@ type MsgIncreasePositionMargin struct {
`MsgBatchUpdateOrders` allows for the atomic cancellation and creation of spot and derivative limit orders, along with a new order cancellation mode. Upon execution, order cancellations (if any) occur first, followed by order creations (if any).

```go
// A Cosmos-SDK MsgBatchUpdateOrders
// SubaccountId only used for the spot_market_ids_to_cancel_all and derivative_market_ids_to_cancel_all.
type MsgBatchUpdateOrders struct {
Sender string
Expand All @@ -441,3 +439,39 @@ type MsgBatchUpdateOrders struct {
- `DerivativeOrdersToCancel` field describes specific derivative orders the sender wants to cancel.
- `SpotOrdersToCreate` field describes spot orders the sender wants to create.
- `DerivativeOrdersToCreate` field describes derivative orders the sender wants to create.



## Msg/AuthorizeStakeGrants

`MsgAuthorizeStakeGrants` is a message used to grant another address with staked INJ balance for fee discount purposes. It can also be used to revoke/remove grants if the amount granted is set to 0.

```go
type MsgAuthorizeStakeGrants struct {
Sender string
Grants []*GrantAuthorization
}
```
Comment on lines +449 to +454
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix struct name inconsistency and add type definition

The struct name in the code block should be MsgAuthorizeStakeGrants to match the section title. Also, the GrantAuthorization type definition is missing, which is crucial for understanding the Grants field.

 type MsgAuthorizeStakeGrants struct {
-	Sender  string 
-	Grants  []*GrantAuthorization 
+    Sender string
+    Grants []*GrantAuthorization
 }

+// GrantAuthorization defines the grant authorization structure
+type GrantAuthorization struct {
+    Grantee string
+    Amount  math.Int
+}

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 Markdownlint

451-451: Column: 1
Hard tabs

(MD010, no-hard-tabs)


452-452: Column: 1
Hard tabs

(MD010, no-hard-tabs)


**Fields description**

- `Sender` describes the creator of this msg.
- `Grants` describes a list of grantees' addresses and grant amounts



## Msg/ActivateStakeGrant

`MsgActivateStakeGrant` is a message used to select/activate a stake grant for fee discount purposes.

```go
type MsgAuthorizeStakeGrants struct {
Sender string
Granter string
}
```
Comment on lines +468 to +472
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix incorrect struct name and formatting

The struct name is incorrect and should be MsgActivateStakeGrant instead of MsgAuthorizeStakeGrants.

-type MsgAuthorizeStakeGrants struct {
-	Sender  string 
-	Granter string 
+type MsgActivateStakeGrant struct {
+    Sender  string
+    Granter string
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
type MsgAuthorizeStakeGrants struct {
Sender string
Granter string
}
```
type MsgActivateStakeGrant struct {
Sender string
Granter string
}
🧰 Tools
🪛 Markdownlint

469-469: Column: 1
Hard tabs

(MD010, no-hard-tabs)


470-470: Column: 1
Hard tabs

(MD010, no-hard-tabs)


**Fields description**

- `Sender` describes the creator of this msg.
- `Granter` describes the address of the granter.
Loading