Swaps and the referrer share
Quote and execute swaps against ubi.fun pools, and pass your address to earn 5% of the fee on volume you route.
Every USDC-paired ubi.fun coin trades in a Uniswap v4 pool whose cash side is USDC and whose hook is our PositionManager. v3 tokens pair with another asset and route through two hops, below. You can route into these pools with any v4-capable router that passes hook data: our PoolSwap contract takes the referrer as an argument, and the Universal Router takes it as the swap’s hook data.
The referrer share, first
5% of every swap fee goes to whoever routed the swap. This is fixed in the fee split, not a partnership program: pass your address, and the hook assigns your share to the ReferralEscrow as it collects the fee. Claim whenever you like; TokensAssigned events tell you what you have accrued. If no referrer is passed, the share cascades down the split instead, so you are leaving money on the table by omitting it.
You can read the live distribution for any pool from the PositionManager:
function getPoolFeeDistribution(bytes32 poolId)
view returns ((uint24 swapFee, uint24 referrer, uint24 protocol, bool active));
Pool key
Build the v4 pool key from the PoolCreated event: the two currencies are the memecoin and USDC, ordered per _currencyFlipped (false means USDC is currency0), with the PositionManager as the hooks address. The hook fixes fee to 0 (fees are taken by the hook, not the pool) and tickSpacing to 60; rather than assembling the key yourself, read it back exactly with PositionManager.poolKey(memecoin).
Quoting
Use the V4Quoter for exact-in and exact-out quotes off-chain. For the quote to match execution, the quoter call must carry the same referrer you will swap with, abi-encoded as the hook data:
import { encodeAbiParameters } from 'viem'
// '0x' means no referrer; otherwise a single abi-encoded address.
const hookData = referrer
? encodeAbiParameters([{ type: 'address' }], [referrer])
: '0x'
Executing
PoolSwap’s entry point:
function swap(
PoolKey calldata key, // (currency0, currency1, fee, tickSpacing, hooks)
SwapParams calldata params, // (zeroForOne, amountSpecified, sqrtPriceLimitX96)
address referrer // your address; the router abi-encodes it into hookData
) payable returns (int256);
zeroForOnefollows v4 semantics against the pool key ordering, so derive it from_currencyFlippedand the direction the user wants.amountSpecifiedis negative for exact-in, positive for exact-out.sqrtPriceLimitX96is your slippage bound, for the pool part of the fill only. An exact-input buy can be filled first from the hook’s own coin balance, at the pool’s current price, and a buy filled that way entirely runs whatever the limit. PoolSwap has no minimum output; for a hard minimum on the whole fill, swap through the Universal Router (V4_SWAPwithamountOutMinimum), as the MCP’sprepare_swapdoes. Approve the input token to PoolSwap first: USDC for buys, the coin for sells.- Amounts are USDC 6 decimals on the cash side and 18 decimals on the coin side.
During a coin’s fair launch window, swaps fill at the fixed fair launch price first; the PoolSwap event’s three amount-pair legs show how a fill was sourced. Whitelisted launches route through WhitelistPoolSwap with a Merkle proof instead.
v3 tokens
A v3 token trades against a pair asset (gold first) in a v4 pool whose hook is the v3 PositionManager, so a trade in USDC takes two hops: USDC to the pair asset on its Uniswap v3 pool, then the pair asset to the token, and the reverse for sells. The site, the MCP’s prepare_swap and @ubi.fun/sdk (createUbiV3) all send it as one Universal Router 2.1.2 transaction:
- Buy:
V3_SWAP_EXACT_IN(USDC to the pair asset, into the router), thenV4_SWAP(settle the router’s pair balance, swap it for the token with your referrer as hook data, take the token to the buyer). The token’s minimum output guards the whole route. - Sell:
V4_SWAP(the token to the pair asset, into the router), thenV3_SWAP_EXACT_IN(the router’s pair balance to USDC for the seller, with the USDC minimum), thenSWEEPof the pair asset back to the seller in case the v3 pool filled only part. - Approvals: the router pulls the input through Permit2. Approve USDC to Permit2 for buys. v3 tokens already give Permit2 an unlimited allowance that cannot be changed, so sells need only the Permit2 allowance for the router.
- Quotes: the v3 QuoterV2 for the pair hop and the V4Quoter, with your referrer as hook data, for the token hop. The V4Quoter runs the hook, so the token’s buy or sell fee, an anti-snipe fee and a large-trade fee are all included.
- Exact input only: while a token’s anti-snipe fee runs (up to 10 minutes after trading opens), exact-output buys revert.
- Referrer share: the v3 hook assigns it to the v3 ReferralEscrow: buys accrue the token, sells accrue the pair asset.
Fees on your volume, end to end
For a swap you route with your referrer address set: 5% of the fee accrues to you in ReferralEscrow, 24% funds the daily holder pool, 15% goes to the protocol, and 56% goes to the creator’s side of the split; on coins launched with a creator vault, the daily payout then settles each fee to 77% creator side, 13% UBI holders and 10% protocol (the v2 fee split). Nothing about the user’s execution price changes based on whether a referrer is set. The fee rate itself is per coin: HolderShareFeeCalculator.poolConfig(poolId) returns the coin’s fee in basis points (150 to 500) for coins launched with a creator vault, and 0 for older coins, which pay the 1.25% base fee. Quotes through the V4Quoter already include it. Full breakdown: Where every fee goes.