CeosHook (Uniswap V4)
CeosHook is a Uniswap V4 hook contract that collects a 2.5% fee on every swap involving graduated company tokens. The fee is routed to FeeSplitterV2 for protocol revenue distribution.
Overview
When a company token graduates from its bonding curve to a Uniswap V4 pool (at $10K market cap), the pool is initialized with CeosHook attached. Every subsequent swap through that pool triggers the hook’s afterSwap callback, which deducts a 2.5% fee from the output amount.
| Property | Value |
|---|---|
| Hook Type | afterSwap |
| Fee Rate | 2.5% of swap output |
| Fee Recipient | FeeSplitterV2 (0xf672ef2D80874E2E7Cd01b282Db14b08cAdcEB7c) |
| Applies To | All graduated company token pools |
| PoolManager | 0x05E73354cFDd6745C338b50BcFDfA3Aa6fA03408 |
Architecture
User Swap → PoolManager.swap() → CeosHook.afterSwap() → 2.5% fee extracted
↓
FeeSplitterV2
├── 50% $RUN burn
├── 25% Protocol Treasury treasury
└── 25% Scout FundThe hook is injected at pool initialization time by the CompanyTokenLauncher during the graduation process:
// In CompanyTokenLauncher._graduateToV4():
PoolKey memory key = PoolKey({
currency0: currency0,
currency1: currency1,
fee: poolFee,
tickSpacing: tickSpacing,
hooks: IHooks(ceosHook) // CeosHook address
});
poolManager.initialize(key, sqrtPriceX96);Hook Lifecycle
Pool Initialization
The CompanyTokenLauncher sets the ceosHook address via setCeosHook() (admin function). When a company token graduates, the hook address is embedded in the PoolKey.hooks field. The PoolManager validates the hook address against the V4 hook address flag scheme.
afterSwap Callback
After each swap in a hooked pool, the PoolManager calls afterSwap on the hook contract. CeosHook:
- Calculates 2.5% of the swap output amount.
- Transfers the fee to FeeSplitterV2.
- Returns the modified amounts to the PoolManager.
Fee Distribution
The 2.5% fee collected by CeosHook flows into FeeSplitterV2, which splits it according to the protocol revenue model:
| Destination | Share | Purpose |
|---|---|---|
| $RUN Burn | 50% | Deflationary pressure on $RUN supply |
| Dev Treasury | 25% | Protocol development and operations |
| Scout Fund | 25% | Protocol-owned liquidity via ScoutFundV2 |
Configuration
The CeosHook address is set on CompanyTokenLauncher by an admin:
// Set the hook address (DEFAULT_ADMIN_ROLE required)
companyTokenLauncher.setCeosHook(ceosHookAddress);Once set, all future token graduations will use this hook. Existing pools cannot have their hooks changed — the hook is immutable per pool.
Integration with CompanyTokenLauncher
The CeosHook is referenced during graduation only. The relevant configuration on CompanyTokenLauncher:
/// @notice CeosHook address for V4 pools (address(0) = no hook)
address public ceosHook;
/// @notice Pool fee in hundredths of a bip (3000 = 0.3%)
uint24 public poolFee;
/// @notice Tick spacing for the V4 pool
int24 public tickSpacing;Security Considerations
- The hook runs within the PoolManager’s execution context via a callback. It cannot arbitrarily move user funds outside the swap flow.
- The fee is extracted from swap output, not from user balances. Users see the net output amount after the fee deduction.
- The hook address is immutable per pool — once a pool is initialized, its hook cannot be replaced.
- The PoolManager enforces that the hook address matches the V4 hook flags encoded in its address.
- FeeSplitterV2 is a trusted recipient. The hook’s fee transfer is a direct
SafeERC20.safeTransfer.