Skip to content

a Gains degen pair is a fixed leverage product, not a ceiling - #2963

Merged
Flotapponnier merged 1 commit into
devfrom
fix/gains-fixed-leverage-pairs
Oct 18, 2026
Merged

Flotapponnier merged 1 commit into
devfrom
fix/gains-fixed-leverage-pairs

Conversation

@Flotapponnier

Copy link
Copy Markdown
Collaborator

pairMinLeverage and pairMaxLeverage both read 500x on pairs 300 and 313, so Gains' degen cohort is a fixed leverage product, not a ceiling. The publisher refused only a leverage above the maximum, so the 10x, 25x, 50x, 100x and 200x tabs each carried a Gains row for a position that cannot be opened.

Read on chain:

pair min max what a trader can choose
0 BTC/USD 1.1 200 1.1x to 200x
1 ETH/USD 1.1 200 1.1x to 200x
300 BTCDEGEN 500 500 only 500x
313 ETHDEGEN 500 500 only 500x

The fix is also the more useful bench

A trader who wants 50x on BTC is not locked out of Gains, they use the standard pair. So Gains now reads both products per market and each leverage publishes the one that can actually be opened, taking the one that leaves more room where both qualify.

What the BTC tabs say now:

leverage product room
10x standard 8.9300%
25x standard 3.5300%
100x standard 0.6800%
200x standard 0.3050%
500x degen 0.1200%
1000x neither, Gains absent —

The standard pair carries a 90% threshold interpolating to 75% between 25x and 60x, and a 0.035% fee a leg against the degen pair's 0.02%, all read from the same contract.

The max leverage column is now the venue ceiling across its products, which is what that column means, rather than the ceiling of whichever product happened to serve the tab.

Selector provenance

pairMinLeverage(uint256) is 0x59a992d0, derived from the signature rather than guessed, and checked by deriving pairMaxLeverage the same way and matching the already-known-good 0x281b693c. A failed read leaves the minimum at zero, which termsAt treats as no minimum, so a missing selector degrades to the previous behaviour rather than hiding every row.

Tests

TestGainsDegenPairIsFixedLeverage refuses 10x through 499x on the degen pair and accepts only 500x. TestGainsPicksTheOpenableProduct pins which product serves each tab and that neither serves 1000x. Both fail against the code as it shipped this afternoon.

gofmt, go build, go vet, go test ./cmd/script/ green. OCB_LIVE=1 go test -run TestLeverageTermsLive reads both Gains products live: standard at 200x giving 0.3050%, degen at 500x giving 0.1200%.

Found by

The leverage-distribution agent, while measuring what leverage traders actually use: all 1,097 Gains degen opens over 7 days are exactly 500.0x, which is not trader behaviour but the only value the contract allows.

pairMinLeverage and pairMaxLeverage both read 500x on pairs 300 and 313,
so 500x is their only legal value. The publisher refused only a leverage
ABOVE the maximum, so the 10x, 25x, 50x, 100x and 200x tabs each carried
a Gains row for a position that cannot be opened.

The fix is also the more useful bench. A trader who wants 50x on BTC is
not locked out of Gains, they use the standard pair: 1.1x to 200x, a 90
percent threshold interpolating to 75 between 25x and 60x, and a 0.035
percent fee a leg against the degen pair's 0.02. So Gains now reads both
products per market and each leverage publishes the one a trader could
actually open, taking the one that leaves more room where both qualify.

What the tabs say now on BTC:

  10x   standard  8.9300%
  25x   standard  3.5300%
  100x  standard  0.6800%
  200x  standard  0.3050%
  500x  degen     0.1200%
  1000x neither, so Gains is absent

The max leverage column is the venue ceiling across its products, which
is what that column means, and no longer the ceiling of whichever
product happened to serve the tab.

pairMinLeverage's selector is derived from the signature rather than
guessed, and checked by deriving pairMaxLeverage the same way and
matching the known good 0x281b693c. A failed read leaves the minimum at
zero, which termsAt treats as no minimum, so a missing selector degrades
to the previous behaviour rather than hiding every row.
@Flotapponnier
Flotapponnier merged commit e9a363a into dev Oct 18, 2026
2 checks passed
Flotapponnier added a commit that referenced this pull request Oct 18, 2026
… is gone (#3035)

* the max leverage tab printed Gains at 500x beside its 200x room

#2963 lets each product answer the "Each venue at its max" tab at its own
ceiling and keeps the larger room. Gains' standard pair at 200x leaves
0.305% and the degen pair at 500x 0.12%, so the tab published 500x in the
max leverage column next to the standard pair's room. Only the product
that reaches the venue's ceiling answers that tab now.

* Gains and Lighter read their own markets: Mobula's perp pairs catalog is gone

GET api.mobula.io/api/2/perp/pairs answers 404 since 2026-10-12; Mobula
deprecated it. It was the only source of Gains' active market count and
of the asset-class split for Gains and Lighter, so three boards
(perp-active-markets, perp-asset-breadth, perp-capital-efficiency) have
shown Gains, and perp-asset-breadth Lighter, as unresponsive for six days.

Gains: backend-arbitrum.gains.trade/trading-variables. Gains delists a
pair by setting its max leverage override to 1 (0.001x) and never removes
it, so those are left out: 178 tradable pairs of 493 (Mobula listed 355).
The pair groups give the class; an unknown group withholds the split.
Gains also seeds the cohort's crypto and RWA symbol sets that Mobula used
to seed for the HIP-3 dexes.

Lighter: no class in the payload, so its symbols go through the router's
cross-venue classification, with crypto as the default for a symbol no
venue tags (it is a crypto-first venue, unlike a HIP-3 RWA dex).

The copy of the three specs stops citing Mobula as the source.
Flotapponnier added a commit that referenced this pull request Oct 18, 2026
release: Gains and Lighter back on the perp boards (cherry-pick #2963, #3035, #3036)
bakabhai993 pushed a commit to bakabhai993/OpenChainBench that referenced this pull request Oct 18, 2026
…ench#2963)

pairMinLeverage and pairMaxLeverage both read 500x on pairs 300 and 313,
so 500x is their only legal value. The publisher refused only a leverage
ABOVE the maximum, so the 10x, 25x, 50x, 100x and 200x tabs each carried
a Gains row for a position that cannot be opened.

The fix is also the more useful bench. A trader who wants 50x on BTC is
not locked out of Gains, they use the standard pair: 1.1x to 200x, a 90
percent threshold interpolating to 75 between 25x and 60x, and a 0.035
percent fee a leg against the degen pair's 0.02. So Gains now reads both
products per market and each leverage publishes the one a trader could
actually open, taking the one that leaves more room where both qualify.

What the tabs say now on BTC:

  10x   standard  8.9300%
  25x   standard  3.5300%
  100x  standard  0.6800%
  200x  standard  0.3050%
  500x  degen     0.1200%
  1000x neither, so Gains is absent

The max leverage column is the venue ceiling across its products, which
is what that column means, and no longer the ceiling of whichever
product happened to serve the tab.

pairMinLeverage's selector is derived from the signature rather than
guessed, and checked by deriving pairMaxLeverage the same way and
matching the known good 0x281b693c. A failed read leaves the minimum at
zero, which termsAt treats as no minimum, so a missing selector degrades
to the previous behaviour rather than hiding every row.

(cherry picked from commit e9a363a)
bakabhai993 pushed a commit to bakabhai993/OpenChainBench that referenced this pull request Oct 18, 2026
… is gone (ChainBench#3035)

* the max leverage tab printed Gains at 500x beside its 200x room

ChainBench#2963 lets each product answer the "Each venue at its max" tab at its own
ceiling and keeps the larger room. Gains' standard pair at 200x leaves
0.305% and the degen pair at 500x 0.12%, so the tab published 500x in the
max leverage column next to the standard pair's room. Only the product
that reaches the venue's ceiling answers that tab now.

* Gains and Lighter read their own markets: Mobula's perp pairs catalog is gone

GET api.mobula.io/api/2/perp/pairs answers 404 since 2026-10-12; Mobula
deprecated it. It was the only source of Gains' active market count and
of the asset-class split for Gains and Lighter, so three boards
(perp-active-markets, perp-asset-breadth, perp-capital-efficiency) have
shown Gains, and perp-asset-breadth Lighter, as unresponsive for six days.

Gains: backend-arbitrum.gains.trade/trading-variables. Gains delists a
pair by setting its max leverage override to 1 (0.001x) and never removes
it, so those are left out: 178 tradable pairs of 493 (Mobula listed 355).
The pair groups give the class; an unknown group withholds the split.
Gains also seeds the cohort's crypto and RWA symbol sets that Mobula used
to seed for the HIP-3 dexes.

Lighter: no class in the payload, so its symbols go through the router's
cross-venue classification, with crypto as the default for a symbol no
venue tags (it is a crypto-first venue, unlike a HIP-3 RWA dex).

The copy of the three specs stops citing Mobula as the source.

(cherry picked from commit 59c886b)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant