Skip to content

fix(hyperliquid): omit the builder field when the fee resolves to 0 - #8449

Open
AzothZephyr wants to merge 1 commit into
hummingbot:masterfrom
AzothZephyr:fix/hyperliquid-omit-unapproved-builder-code
Open

AzothZephyr wants to merge 1 commit into
hummingbot:masterfrom
AzothZephyr:fix/hyperliquid-omit-unapproved-builder-code

Conversation

@AzothZephyr

Copy link
Copy Markdown

Problem

Every order fails for any user who has not approved the Hummingbot Foundation builder:

Error submitting order 0x4f111ae6...: Builder fee has not been approved.
Failed to submit SELL order to Hyperliquid_perpetual. Check API key and network connection.

The connector is unusable on mainnet until the user approves a builder they may not know about and may not want to pay.

Cause

_initialize_builder_fee() resolves the fee correctly — min(approved, configured), which is 0 when maxBuilderFee returns 0:

self._builder_fee_tenths_bps = min(approved_max_tenths_bps, CONSTANTS.FOUNDATION_BUILDER_FEE_TENTHS_BPS)

But _build_builder_field() attaches the field regardless of the resolved fee:

return {"b": self._builder_address.lower(), "f": self._builder_fee_tenths_bps}   # f == 0

Hyperliquid rejects an order carrying a builder the sender has not approved even when the fee is 0. The surrounding comments assume otherwise — "The fee only takes effect if the user has approved this builder in Condor; otherwise it is 0 bps" — which holds for the fee but not for the order.

Fix

Omit the field when the resolved fee is 0. That matches what the existing comments already assume the behaviour to be, and it collects nothing either way.

An approved user is unaffected: the fee is non-zero and the field is attached exactly as before. Vault and testnet handling is untouched.

Tests

Two existing tests asserted the field was still built at f=0, one of them noting "Still attributes to the Foundation builder address, just at 0 bps" — that is precisely the assumption the venue rejects. Both now assert the field is omitted.

Added:

  • test_builder_field_omitted_when_fee_is_zero
  • test_place_order_omits_builder_key_when_fee_is_zero — asserts the key is absent from the signed action rather than present with a zero value, driving the real _place_order path

148 passed for the full connector suite.

Verification

Reproduced on mainnet with an account where maxBuilderFee returns 0: every order failed with the message above. With the field omitted, orders submit and fill normally.

Every order fails for a user who has not approved the Foundation builder:

  Error submitting order ...: Builder fee has not been approved.

_initialize_builder_fee correctly resolves the fee to 0 in that case -
min(approved, configured) with approved = 0 - but _build_builder_field still
attaches {"b": <foundation>, "f": 0}, and Hyperliquid rejects any order
carrying a builder the sender has not approved regardless of the fee being
zero. The connector cannot place orders at all until the user approves a
builder they may not want.

Omitting the field at a 0 fee is what the existing comments already assume the
behaviour to be ("otherwise it is 0 bps"), and it collects nothing either way.
An approved user is unaffected: the fee is non-zero and the field is attached
exactly as before.

Two existing tests asserted the field was still built at f=0, one of them
noting "Still attributes to the Foundation builder address, just at 0 bps" -
that is the assumption the venue rejects, so both now assert it is omitted.
Adds coverage that the key is absent from the signed order action rather than
present with a zero value.

Reproduced on mainnet against an account with maxBuilderFee = 0; orders
succeed with the field omitted.
@greptile-apps

greptile-apps Bot commented Sep 5, 2026

Copy link
Copy Markdown

Greptile Summary

This PR prevents Hyperliquid perpetual orders from including an unapproved builder when the resolved fee is zero.

  • Omits the builder payload field for zero or non-positive resolved fees.
  • Preserves builder attribution for approved users with a positive fee.
  • Adds unit and order-path coverage verifying that the builder key is absent at zero fee.

Confidence Score: 5/5

The PR appears safe to merge with no actionable correctness or security issues identified.

The new guard matches the resolved builder-fee lifecycle, preserves positive-fee attribution, and is covered through both direct field construction and order payload generation.

Important Files Changed

Filename Overview
hummingbot/connector/derivative/hyperliquid_perpetual/hyperliquid_perpetual_derivative.py Adds a focused guard that omits the optional builder field when its resolved fee cannot collect anything and would cause venue rejection.
test/hummingbot/connector/derivative/hyperliquid_perpetual/test_hyperliquid_perpetual_derivative.py Updates zero-fee expectations and verifies the real order payload excludes the builder key.

Reviews (1): Last reviewed commit: "fix(hyperliquid): omit the builder field..." | Re-trigger Greptile

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