Skip to main content

Builder fees

A builder fee lets an application earn from the swaps it originates. The Yutu router adds the fee to the pool price, attributes it on chain, and sends the full amount to the builder. Yutu takes no share.

Builder fees are live on the Yutu testnet.

NetworkValue
Chain ID7
JSON-RPChttps://rpc.yutu.finance
Maximum builder fee50bp
Current builder balance requirement1 HYPE

Testnet contracts​

ContractAddress
SwapRouter0xCe37F45bbF6697dCBB9838b7DEda34DBc1d02E98
BuilderRegistry0x99059a19393c2feE2617EDC9da7acD7a6E76EBF4
Pool, tBTC/tUSD0x46A72b7948d47C61aaB472967a9D34F7082b3Ed7
Pool, HYPE/tUSD0x5cA2320202c0b8d34b81A048e85585590c0970DF
tUSD0xd5349aA42a5698547Cb375d961575b6d40C97F48
WHYPE0x7208AE16C5EB3e232c1Fb89D683f9e1B499cceAd

Testnet addresses change after a state reset. Check deploy/DEPLOYMENTS.md in the Yutu repository before shipping an integration.

Router entry points​

sellNative(
IDepthPool pool,
uint256 minQuoteOutE6,
address builder,
uint16 builderBps
) payable

buyNative(
IDepthPool pool,
uint64 baseOutE6,
uint256 maxQuoteInE6,
address builder,
uint16 builderBps
)

sellBase(
IDepthPool pool,
uint64 baseInE6,
uint256 minQuoteOutE6,
address builder,
uint16 builderBps
)

buyBase(
IDepthPool pool,
uint64 baseOutE6,
uint256 maxQuoteInE6,
address builder,
uint16 builderBps
)

Use the Native methods when the pool base is WHYPE. The router wraps and unwraps HYPE so the user receives or sends native HYPE. Use the Base methods for ERC-20 base assets such as tBTC.

Base and quote parameters use six decimals. The HYPE attached to sellNative as msg.value is denominated in wei.

Attach a builder fee​

Front ends​

Pass the builder address and fee rate on every router call:

router.buyBase(
pool,
baseOutE6,
maxQuoteInE6,
0xYourBuilderAddress,
20
);

Here 20 means 20 basis points, or 0.20%.

Per-call attribution is required for front ends. When a wallet calls the router, msg.sender is the user rather than the interface that prepared the transaction. The builder address in the call supplies the missing attribution.

Contract integrations​

A contract can register a standing code once:

BuilderRegistry.register(address builder, uint16 bps);

The integrating contract must call register itself. The registry uses msg.sender as its key, which prevents another account from assigning a code to that contract. The router applies the registration whenever the contract calls it with both builder and builderBps set to zero.

An explicit code takes priority over the standing registration. To override a registration with a zero fee for one call, pass a real builder address with builderBps = 0. Passing (address(0), 0) uses the registered code.

deregister() removes the calling contract's standing code.

Fee rules​

RuleRouter behaviour
Fee capRejects a rate above 50bp
Missing builderRejects a non-zero rate with the zero address
Builder balanceCharges only while the builder holds at least 1 HYPE
Dormant codeSkips the fee and settles the trade
Yutu shareSends zero to Yutu

The balance requirement isn't a lock. The router reads the builder's native HYPE balance when the swap executes. Its owner can change the threshold, but the contract fixes the upper bound at 500 HYPE.

When a builder is below the threshold, the router emits BuilderFeeSkipped. A successful payment emits BuilderFeePaid with the builder, pool, token, payer, and amount.

What the user pays​

The builder fee is additive. It doesn't reduce the amount received by the pool or the fee paid to LPs.

For a buy, maxQuoteInE6 caps the pool cost and builder fee together. For a sell, minQuoteOutE6 is the amount delivered to the user after the builder fee. The router checks both bounds after calculating the fee.

This has been measured on testnet. A fill quoted at 40,033,005 units with a 20bp code paid the builder 80,092 units while the pool still received 40,033,005 units.

Pools remain directly callable without a builder fee. A builder can only charge a caller who includes its code or calls through a contract that registered it.

User approval and disclosure​

Yutu doesn't require a separate builder-fee approval transaction. The user signs the swap transaction containing the builder address, rate, and all-in price bound.

An interface can still display one rate and submit another. A malicious front end could show 0bp and send 50bp. The contract cap limits the charge to 0.50%, and users can call the pool directly, but an integration should display the encoded rate and total before requesting a signature.

Integration checklist​

  • Read current contract addresses from deploy/DEPLOYMENTS.md.
  • Choose per-call attribution for a front end or registration for a calling contract.
  • Keep the builder address funded above the current HYPE requirement.
  • Show the builder rate and total cost in the quote.
  • Set maxQuoteInE6 or minQuoteOutE6 against the user's all-in result.
  • Track BuilderFeePaid and BuilderFeeSkipped events.
  • Leave direct pool access available as the zero-builder-fee route.