Skip to main content

Fee Architecture

Ramses V3 uses tick spacing to determine pool characteristics and allows governance-controlled fee adjustment per pool, diverging from Uniswap V3’s fixed fee tiers.
While Uniswap V3 uses predefined static fee tiers that are immutable after pool creation, Ramses V3 decouples tick spacing from fees. Each tick spacing has a default initial fee, but governance can adjust the swap fee of any pool at any time via factory.setFee(pool, newFee).

Fee Model

How Fees Are Set

Fees in Ramses V3 are not determined by an on-chain algorithm during swaps. Instead:
  1. Each tick spacing has a default initial fee set in the factory’s tickSpacingInitialFee mapping
  2. When a pool is created, it inherits the initial fee for its tick spacing
  3. Governance can adjust any pool’s fee at any time via RamsesV3Factory.setFee(pool, fee)
  4. The pool stores its current fee and applies it to all swaps

Default Tick Spacing / Fee Mapping

Fees are denominated in parts per million (1/1,000,000). For example, 100 = 0.01%, 3000 = 0.30%.

Swap Fee Distribution

LP Fee Collection

Swap fees are distributed pro-rata to all in-range liquidity at the time of the swap:
  • In-Range Positions: Positions where tickLower ≤ currentTick < tickUpper earn fees
  • Out-of-Range Positions: Positions outside the active price earn 0 fees
  • Fee Accrual: Fees accumulate continuously as long as a position remains in-range
  • Manual Collection: LPs must call collect() to claim accumulated fees (not auto-compounded)

Protocol Fee Split (feeProtocol)

The feeProtocol setting determines what percentage of swap fees are routed to the protocol (FeeCollector) vs staying with LPs. It is also denominated in parts per million (1/1,000,000). The fee split differs dramatically based on whether a pool has a gauge:

Gauged Pools (100% to voters)

When a gauge is attached to a pool via the Voter contract, gaugeFeeSplitEnable sets the pool’s feeProtocol to 1,000,000 (100%). This means all swap fees are routed to the FeeCollector, which distributes them to the pool’s FeeDistributor for xRAM voters to claim. LPs on gauged pools earn emissions from the gauge instead of swap fees.

Non-Gauged Pools (95% to LPs, 5% to treasury)

Pools without a gauge use the factory’s default feeProtocol of 50,000 (5%). This means:
  • 95% of swap fees go to LPs (collected via pool.collect())
  • 5% goes to the FeeCollector, which sends it to the treasury (since there’s no gauge/FeeDistributor)

Fee Flow

Protocol Fee Distribution

Contract: FeeCollector.sol When collectProtocolFees(pool) is called, the FeeCollector:
  1. Calls pool.collectProtocol() to pull the protocol’s share of fees
  2. If the pool has no gauge (or gauge is not alive): sends everything directly to the treasury
  3. If the pool has a live gauge: splits fees between the FeeDistributor (for voters) and the treasury based on the treasuryFees ratio

FeeCollector Interface

Distribution Cycle

  1. Accumulation: Fees accumulate in pools continuously
  2. Collection: Anyone can call collectProtocolFees(pool) to trigger collection and distribution (permissionless)
  3. Voter Claims: On gauged pools, xRAM holders claim from FeeDistributor proportional to their voting weight
  4. LP Claims: On non-gauged pools, LPs collect their 95% share anytime via collect()

Integrator Considerations

Querying Current Fees

Always query the current fee before estimating swap outputs:

Slippage Protection

Since fees can be changed by governance, set appropriate slippage tolerance:

Events

Additional Resources