HIP-4 documentation

Testnet · Exploratory documentation — not official Hyperliquid documentation.

Trading fees (L1)

Evidence from hl-node strings, spotMetaAndAssetCtxs, userFees, and a real outcome fill on testnet: outcome CLOB fees behave like ordinary spot fees today, while a native governance hook (VoteGlobalAction::SetOutcomeFeeScale) exists for future global rescaling.

This page is HyperCore L1 only. Third-party HyperEVM parimutuel contracts document a separate platform fee (e.g. 90 bps) — see EVM overview.

Full markdown: HIP4-fees.md. Structured POST /info entries: Info endpoint.

Claim 1 — Native fee governance hook

Proof (hl-node strings)

004a194b: "struct variant VoteGlobalAction::SetOutcomeFeeScale with 1 element"
00648e5b: "struct variant VoteGlobalAction::SetOutcomeFeeScale"
001c7cec: "%can only change fee scale once every "

What this proves

  • HyperCore exposes SetOutcomeFeeScale as a real variant.
  • The action has one field; binary text references a cooldown between changes.

What this does not prove

Exact post-change formula, live stored scale on testnet, or whether state lives in OutcomeTracker vs elsewhere.

Claim 2 — Outcome assets on spot rails

Proof (binary + public metadata)

Deploy / user-outcome actions:

struct variant OutcomeDeploy::RegisterOutcome with 4 elements
struct variant OutcomeDeploy::RegisterTokensAndStandaloneOutcome with 3 elements
struct variant UserOutcomeAction::SplitOutcome with 2 elements
struct variant UserOutcomeAction::MergeOutcome with 1 element
struct variant UserOutcomeAction::MergeQuestion with 1 element
struct variant UserOutcomeAction::NegateOutcome with 3 elements

Core state structs:

struct OutcomeSpec with 4 elements
struct QuestionSpec with 5 elements
struct OutcomeTracker with 11 elements
struct SettledOutcomeSpec with 3 elements
struct SettledQuestionSpec with 4 elements

Example @ pairs from spotMetaAndAssetCtxs:

[
  {
    "tokens": [
      11,
      0
    ],
    "name": "@10",
    "index": 10,
    "isCanonical": false
  },
  {
    "tokens": [
      12,
      0
    ],
    "name": "@11",
    "index": 11,
    "isCanonical": false
  },
  {
    "tokens": [
      13,
      0
    ],
    "name": "@12",
    "index": 12,
    "isCanonical": false
  }
]

Compare fee behavior to spot first — not a separate prediction-only fee engine.

Claim 3 — No extra deployer trading fee share (observed)

Live Hypurr outcome base tokens report deployerTradingFeeShare: "0.0".

[
  {
    "name": "CHUTORO",
    "index": 11,
    "tokenId": "0x709a9be4d62c016171995ea52d7888b0",
    "evmContract": null,
    "deployerTradingFeeShare": "0.0"
  },
  {
    "name": "OTORO",
    "index": 12,
    "tokenId": "0xe020bcb111ceb9cab517e273bdbd12df",
    "evmContract": null,
    "deployerTradingFeeShare": "0.0"
  },
  {
    "name": "ODDISH",
    "index": 13,
    "tokenId": "0x0b647df03c2e8922c7225364c2cf2b7d",
    "evmContract": null,
    "deployerTradingFeeShare": "0.0"
  }
]

Claim 4 — Base spot schedule on testnet

userFees with a sentinel user returns the default schedule: spot taker 7 bps, maker 4 bps.

Example request

curl -s https://api.hyperliquid-testnet.xyz/info \
  -H 'Content-Type: application/json' \
  --data '{"type":"userFees","user":"0xffffffffffffffffffffffffffffffffffffffff"}'

Observed response (excerpt)

{
  "feeSchedule": {
    "cross": "0.00045",
    "add": "0.00015",
    "spotCross": "0.0007",
    "spotAdd": "0.0004"
  },
  "userCrossRate": "0.0",
  "userAddRate": "0.0",
  "userSpotCrossRate": "0.0",
  "userSpotAddRate": "0.0",
  "activeReferralDiscount": "0.0"
}

Claim 5 — Real fill matches spot fee math

Taker fill on @10: fee is denominated in the base outcome token (feeToken), not USDC — normalize before comparing to notional.

userFillsByTime

curl -s https://api.hyperliquid-testnet.xyz/info \
  -H 'Content-Type: application/json' \
  --data '{"type":"userFillsByTime","user":"0xae551d73161bac3315c5ade0e2d499a44ebe2236","startTime":1769956276000,"endTime":1769956277000}'

Representative fill

{
  "coin": "@10",
  "px": "0.59475",
  "sz": "1000.0",
  "dir": "Buy",
  "crossed": true,
  "fee": "0.56",
  "feeToken": "CHUTORO"
}

Normalization

notional_usdc = px * sz
              = 0.59475 * 1000
              = 594.75 USDC

fee_usdc_equiv = fee_token_amount * px
               = 0.56 * 0.59475
               = 0.33306 USDC

effective_rate = fee_usdc_equiv / notional_usdc
               = 0.33306 / 594.75
               = 0.00056
               = 5.6 bps

Same user — userFees

{
  "userSpotCrossRate": "0.00056",
  "userSpotAddRate": "0.00032"
}

Match

HIP-4 fill effective taker rate = 0.00056
userSpotCrossRate               = 0.00056

Claim 6 — Active scale not named in stripped binary

HIP-3 exposes obvious deployer_fee_scale style names; no parallel outcome_fee_scale string was found in the same pass.

- explicit HIP-3 fee-scale storage names:
  - deployer_fee_scale
  - last_deployer_fee_scale_change_time
- no similarly explicit named field such as:
  - outcome_fee_scale
  - last_outcome_fee_scale_change_time
  - outcome_fees_collected

Safest statement: behavioral neutrality on testnet, not "scale = X from strings".

Conclusion (testnet evidence)
  1. hl-node proves SetOutcomeFeeScale exists.
  2. Outcomes trade on spot-style books; metadata aligns.
  3. Observed tokens show deployerTradingFeeShare = 0.
  4. Normalized fills match userSpotCrossRate.

HIP-4 trading fees on testnet currently behave like normal spot trading fees, while HyperCore retains a governance path that could rescale outcome fees globally.