Create
Documentation
Guides

Fees and referrals

Where fees come from#

Every trade pays a fee on the quote leg, in the quote asset, from the first trade onward. There are two components:

ComponentGoes toSet by
curve / hook feesplit between the protocol and the creatorthe launch config and fee policy
creator taxentirely to the creator, never splitTokenParams.creatorTaxBps at launch

Both are frozen into the launch at creation. A later policy change by the owner affects only launches created after it, so an existing token's economics cannot be altered underneath its holders.

Referrals#

A referred trade is cheaper for the trader and pays the referrer:

  • the trader pays a discount on the standard fee,
  • the referrer receives a share of what is paid,
  • the pool books the remainder.

Bindings are permanent and never rewritten. A user can bind themselves ahead of time with referralRegistry.setReferrer(address), or a referrer can be passed to the four-argument curve.buy on their first trade.

On the curve, an invalid referrer reverts the buy. In the pool, the hook is far more forgiving — a rejected binding just charges the standard fee rather than failing the swap.

One security property worth knowing if you build a router: pool-phase hookData can only ever name the referrer, never the trader. The trader always comes from msgSender(). So nobody can bind a stranger's referrer with a dust swap.

Claiming#

Everything owed to anyone accumulates in the fee escrow, and every claim is pull-only by msg.sender — you cannot claim on someone else's behalf. That is deliberate: it means a recipient who cannot receive a transfer (a blocklisted address, a reverting contract) can never block a sweep for everybody else.

ts
const owed = await client.readContract({
  address: FEE_ESCROW, abi: escrowAbi,
  functionName: "balanceOfToken", args: [account, USDC],
});

if (owed > 0n) {
  await walletClient.writeContract({
    address: FEE_ESCROW, abi: escrowAbi, functionName: "claimToken", args: [USDC],
  });
}
Warning
The escrow stores one balance per (recipient, token). It does not distinguish creator fees from referral fees — that split is attribution derived off-chain from events. So claimToken withdraws both at once, and a UI showing them as two separately claimable pots is lying about what the button does. Show the split as attribution; make one claim.

Fees on Arc are the 6-decimal USDC ERC-20, so claimToken is the path. The native claim() is unreachable unless a launch quotes in the native asset, which no approved pair token does.

Pool-phase fees need a sweep first#

Curve fees accrue in the curve and are swept to the escrow by curve.sweepFees(). Pool fees accrue in the hook and are swept by hook.sweepPoolFees(poolId, minOut) — which may need to convert memecoin-denominated inventory back to the quote asset against the pool's own liquidity, which is why it takes a slippage bound.

Referral accruals in the pool are settled with hook.claimReferralFees(referrer, currency), which is permissionless — anyone can settle anyone's accrual into the escrow. The referrer then claims from the escrow as above. Two steps, not one.