Skip to content

Conversation

@mergify
Copy link
Contributor

@mergify mergify bot commented Oct 24, 2025

Changelist

This PR implements a Market Fee Discount feature that allows governance to configure flexible fee discount periods for specific markets/CLOB pairs. During an active discount period, fees can be reduced by any percentage (from 0% to 100% of normal fees) for designated markets during specified time periods.

Detailed tech spec

Key Changes:

  • Proto definitions for PerMarketFeeDiscountParams message with charge_ppm field for flexible discount percentages
  • State management functions to get/set/list market fee discounts by CLOB pair
  • Governance message handler (MsgSetMarketFeeDiscountParams) with validation for time ranges, CLOB pair existence, and charge_ppm limits
  • gRPC query handlers to retrieve market fee discount configurations
  • Fee calculation integration: GetPerpetualFeePpm() now checks for active fee discounts and applies proportional discount based on charge_ppm
  • CLOB module updates: Pass clobPairId to fee calculation function
  • TypeScript client codegen for indexer integration

Breaking Changes:

  • GetPerpetualFeePpm() signature updated to include clobPairId parameter (all callers updated in this PR)

Example Governance Proposal

{
  "messages": [{
    "@type": "/dydxprotocol.feetiers.MsgSetMarketFeeDiscountParamss",
    "authority": "dydx10d07y265gmmuvt4z0w9aw880jnsr700jnmapky",
    "params": [{
      "clob_pair_id": 1,
       "start_time": "2024-07-31T00:00:00Z",
       "end_time": "2024-08-07T00:00:00Z", 
      "charge_ppm": 0
    }]
  }],
  "title": "Free Trading Week for ETH-USD"
}

Test Plan

Unit Tests

  • ✅ Fee discount with charge_ppm = 0 returns zero fees (100% discount)
  • ✅ Fee discount with charge_ppm = 500000 returns 50% of normal fees
  • ✅ Fee discount with charge_ppm = 1000000 returns normal fees (no discount)
  • ✅ Expired discounts do not affect fees (normal tier fees apply)
  • ✅ Discounts are market-specific (only affect configured CLOB pairs)
  • ✅ Discount applies proportionally to both maker and taker fees
  • ✅ Discount applies to maker rebates (negative fees reduced proportionally)
  • ✅ Validation rejects charge_ppm > 1000000
  • ✅ Validation rejects invalid time ranges, non-existent CLOB pairs, excessive durations
  • ✅ Query handlers return correct data for single/all market fee discount lookups

Manual Testing on Staging

  1. Place Order WITHOUT Fee Discount
    Fill Result (BEFORE discount):
{
  "id": "6fba0e3e-bf39-54f2-9ac2-b316d25c1fe8",
  "side": "BUY",
  "liquidity": "TAKER",
  "type": "LIMIT",
  "market": "BTC-USD",
  "marketType": "PERPETUAL",
  "price": "107442",
  "size": "0.0001",
  "fee": "0.005373",
  "affiliateRevShare": "0",
  "createdAt": "2025-10-17T16:15:55.617Z",
  "createdAtHeight": "61353",
  "orderId": "4e9d5278-22f3-5902-bba1-d70853fd9c70",
  "clientMetadata": "0",
  "subaccountNumber": 0
}
  1. Submit and Pass Governance Proposal for BTC-USD
{
  "messages": [
    {
      "@type": "/dydxprotocol.feetiers.MsgSetMarketFeeDiscountParams",
      "authority": "dydx10d07y265gmmuvt4z0w9aw880jnsr700jnmapky",
      "params": [
        {
          "clob_pair_id": 0,
          "start_time": "2025-10-01T00:00:00Z",
          "end_time": "2025-10-31T00:00:00Z",
          "charge_ppm": 0
        }
      ]
    }
  ],
  "deposit": "20000000adv4tnt",
  "metadata": "",
  "title": "Test Fee Discount Campaign - 100% Off BTC-USD",
  "summary": "Testing 100% fee discount (free trading) for CLOB pair 0 (BTC-USD)",
  "expedited": true
}
  1. Verify Proposal Applied
$ ./build/dydxprotocold query feetiers get-market-fee-discount-params
params:
- charge_ppm: 0
  clob_pair_id: 0
  end_time_unix: "1767139200"
  start_time_unix: "1759363200"
  1. Place Order WITH Fee Discount
{
  "id": "86a13a26-8bb9-558c-aee3-966bedfc2b8d",
  "side": "BUY",
  "liquidity": "TAKER",
  "type": "LIMIT",
  "market": "BTC-USD",
  "marketType": "PERPETUAL",
  "price": "107382",
  "size": "0.0001",
  "fee": "0",
  "affiliateRevShare": "0",
  "createdAt": "2025-10-17T16:20:41.758Z",
  "createdAtHeight": "61613",
  "orderId": "4e9d5278-22f3-5902-bba1-d70853fd9c70",
  "clientMetadata": "0",
  "subaccountNumber": 0
}

Author/Reviewer Checklist

  • If this PR has changes that result in a different app state given the same prior state and transaction list, manually add the state-breaking label.
  • If the PR has breaking postgres changes to the indexer add the indexer-postgres-breaking label.
  • If this PR isn't state-breaking but has changes that modify behavior in PrepareProposal or ProcessProposal, manually add the label proposal-breaking.
  • If this PR is one of many that implement a specific feature, manually label them all feature:[feature-name].
  • If you wish to for mergify-bot to automatically create a PR to backport your change to a release branch, manually add the label backport/[branch-name].
  • Manually add any of the following labels: refactor, chore, bug.

Summary by CodeRabbit

  • New Features

    • Per-market fee discounts: new messages/tx to set discounts, gRPC/LCD queries to fetch one or all market discounts, and a CLI command to view them.
  • Improvements

    • Fee computation now applies per-market discounts to taker/maker fees.
  • Tests

    • Added unit and integration tests for validation, keeper logic, RPC/CLI queries, message handling, and fee computation.
  • Chores

    • CI workflows updated to trigger on the new branch.

This is an automatic backport of pull request #3130 done by [Mergify](https://mergify.com).

(cherry picked from commit 33a4abb)

# Conflicts:
#	protocol/x/feetiers/client/cli/query.go
#	protocol/x/feetiers/keeper/grpc_query.go
#	protocol/x/feetiers/keeper/grpc_query_test.go
#	protocol/x/feetiers/keeper/keeper.go
#	protocol/x/feetiers/keeper/keeper_test.go
@mergify mergify bot requested a review from a team as a code owner October 24, 2025 19:44
@mergify mergify bot added the conflicts label Oct 24, 2025
@mergify
Copy link
Contributor Author

mergify bot commented Oct 24, 2025

Cherry-pick of 33a4abb has failed:

On branch mergify/bp/release/indexer/v9.4.x-2/pr-3130
Your branch is up to date with 'origin/release/indexer/v9.4.x-2'.

You are currently cherry-picking commit 33a4abb2.
  (fix conflicts and run "git cherry-pick --continue")
  (use "git cherry-pick --skip" to skip this patch)
  (use "git cherry-pick --abort" to cancel the cherry-pick operation)

Changes to be committed:
	modified:   indexer/packages/v4-protos/src/codegen/dydxprotocol/bundle.ts
	new file:   indexer/packages/v4-protos/src/codegen/dydxprotocol/feetiers/per_market_fee_discount.ts
	modified:   indexer/packages/v4-protos/src/codegen/dydxprotocol/feetiers/query.lcd.ts
	modified:   indexer/packages/v4-protos/src/codegen/dydxprotocol/feetiers/query.rpc.Query.ts
	modified:   indexer/packages/v4-protos/src/codegen/dydxprotocol/feetiers/query.ts
	modified:   indexer/packages/v4-protos/src/codegen/dydxprotocol/feetiers/tx.rpc.msg.ts
	modified:   indexer/packages/v4-protos/src/codegen/dydxprotocol/feetiers/tx.ts
	modified:   indexer/packages/v4-protos/src/codegen/gogoproto/bundle.ts
	modified:   indexer/packages/v4-protos/src/codegen/google/bundle.ts
	new file:   proto/dydxprotocol/feetiers/per_market_fee_discount.proto
	modified:   proto/dydxprotocol/feetiers/query.proto
	modified:   proto/dydxprotocol/feetiers/tx.proto
	modified:   protocol/app/msgs/all_msgs.go
	modified:   protocol/app/msgs/internal_msgs.go
	modified:   protocol/app/msgs/internal_msgs_test.go
	modified:   protocol/lib/ante/internal_msg.go
	modified:   protocol/x/clob/keeper/mev.go
	modified:   protocol/x/clob/keeper/orders.go
	modified:   protocol/x/clob/keeper/process_single_match.go
	modified:   protocol/x/clob/types/expected_keepers.go
	modified:   protocol/x/feetiers/client/cli/query_test.go
	modified:   protocol/x/feetiers/keeper/msg_server.go
	modified:   protocol/x/feetiers/keeper/msg_server_test.go
	new file:   protocol/x/feetiers/keeper/per_market_fee_discount.go
	new file:   protocol/x/feetiers/keeper/per_market_fee_discount_test.go
	modified:   protocol/x/feetiers/types/errors.go
	modified:   protocol/x/feetiers/types/keys.go
	new file:   protocol/x/feetiers/types/per_market_fee_discount.go
	new file:   protocol/x/feetiers/types/per_market_fee_discount.pb.go
	new file:   protocol/x/feetiers/types/per_market_fee_discount_test.go
	modified:   protocol/x/feetiers/types/query.pb.go
	modified:   protocol/x/feetiers/types/query.pb.gw.go
	modified:   protocol/x/feetiers/types/tx.pb.go
	modified:   protocol/x/feetiers/types/types.go
	modified:   protocol/x/vault/keeper/vault_test.go

Unmerged paths:
  (use "git add <file>..." to mark resolution)
	both modified:   protocol/x/feetiers/client/cli/query.go
	both modified:   protocol/x/feetiers/keeper/grpc_query.go
	both modified:   protocol/x/feetiers/keeper/grpc_query_test.go
	both modified:   protocol/x/feetiers/keeper/keeper.go
	both modified:   protocol/x/feetiers/keeper/keeper_test.go

To fix up this pull request, you can check it out locally. See documentation: https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/reviewing-changes-in-pull-requests/checking-out-pull-requests-locally

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 24, 2025

Important

Review skipped

Bot user detected.

To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.


Comment @coderabbitai help to get the list of available commands and usage tips.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Development

Successfully merging this pull request may close these issues.

2 participants