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.
| Network | Value |
|---|---|
| Chain ID | 7 |
| JSON-RPC | https://rpc.yutu.finance |
| Maximum builder fee | 50bp |
| Current builder balance requirement | 1 HYPE |
Testnet contracts
| Contract | Address |
|---|---|
| SwapRouter | 0xCe37F45bbF6697dCBB9838b7DEda34DBc1d02E98 |
| BuilderRegistry | 0x99059a19393c2feE2617EDC9da7acD7a6E76EBF4 |
| Pool, tBTC/tUSD | 0x46A72b7948d47C61aaB472967a9D34F7082b3Ed7 |
| Pool, HYPE/tUSD | 0x5cA2320202c0b8d34b81A048e85585590c0970DF |
| tUSD | 0xd5349aA42a5698547Cb375d961575b6d40C97F48 |
| WHYPE | 0x7208AE16C5EB3e232c1Fb89D683f9e1B499cceAd |
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
| Rule | Router behaviour |
|---|---|
| Fee cap | Rejects a rate above 50bp |
| Missing builder | Rejects a non-zero rate with the zero address |
| Builder balance | Charges only while the builder holds at least 1 HYPE |
| Dormant code | Skips the fee and settles the trade |
| Yutu share | Sends 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
maxQuoteInE6orminQuoteOutE6against the user's all-in result. - Track
BuilderFeePaidandBuilderFeeSkippedevents. - Leave direct pool access available as the zero-builder-fee route.