Skip to main content

Discrete Liquidity Market Maker

Ramses DLMM pools divide price space into discrete bins. Each bin has one fixed price and its own reserves. Swaps consume liquidity at the active bin’s price and move to the next non-empty bin when that liquidity is exhausted. This differs from Ramses concentrated-liquidity pools:
At the Robinhood snapshot at block 22,674,244, DLMM is fee-only, the factory is not connected to Voter, and sampled pools do not have rewarder hooks. The rewarder and 100%-to-voters flow described below are optional protocol architecture.

Bins and the price grid

Each pool has an immutable binStep, expressed in basis points. One basis point is 0.01%, so binStep = 1 creates a 0.01% geometric step between adjacent bins. For bin ID id:
The contracts represent this price as an unsigned 128.128 fixed-point number. Use getPriceFromId() and getIdFromPrice() rather than reimplementing the fixed-point math unless exact parity has been tested. Inside one bin, liquidity follows a constant-sum relationship:
The active bin may contain both assets. Relative to the pool’s actual tokenX and tokenY ordering:
  • Bins below the active ID may contain only tokenY
  • The active bin may contain both tokenX and tokenY
  • Bins above the active ID may contain only tokenX
Always read getTokenX() and getTokenY() from the pool. Display order in an interface is not a substitute for contract order.

Swaps and price impact

A swap executes against the active bin and then traverses the pool’s sparse tree of non-empty bins.
  • Execution within one bin has no curve-driven price movement
  • Crossing N bin IDs changes the execution price by N geometric steps; sparse traversal may skip empty bins
  • A large trade can cross many bins, so its average execution price can differ materially from the starting price
  • A swap reverts if the selected route cannot completely satisfy the requested amount
Direct pool swaps expect input tokens to have already been transferred and do not expose caller-facing deadline or minimum-output protection. Users and integrators should normally use DLMMRouter.

LP positions

DLMMPool inherits an ERC1155-like multi-token implementation:
  • Each bin ID is a separate fungible LP share
  • balanceOf(owner, binId) returns an owner’s share balance in that bin
  • totalSupply(binId) returns all shares issued for that bin
  • balanceOfBatch() reads multiple owner/bin pairs
  • approveForAll() authorizes a router or manager to burn or transfer bin shares
The token intentionally does not implement ERC1155 receiver callbacks or token URIs. Integrations should use the exposed DLMMToken interface instead of assuming complete ERC1155 behavior. When liquidity is removed, each bin returns tokenX and tokenY pro rata to the shares burned. LP swap fees retained by the pool increase bin reserves and therefore increase the redemption value of those shares. There is no separate LP fee claim for that retained portion.

Adding liquidity

The router accepts independent token distributions across signed offsets from the pool’s active bin at execution:
When constructing the transaction, read the pool’s active ID, use it as activeIdDesired, and calculate:
The router checks that liveActiveId remains within idSlippage of activeIdDesired, but it uses liveActiveId to calculate the actual deposit bins. If the active ID moves within the permitted range, the entire distribution moves with it. Set idSlippage = 0 when absolute bin placement is required. distributionX and distributionY use 1e18-scaled weights. Sum a token’s array to 1e18 to allocate its full supplied amount. A sum below 1e18 leaves the remainder for refundTo; over-allocation can revert and should be rejected by the integration. Important safeguards:
  • Read the active ID immediately before constructing the transaction
  • Set idSlippage, token minimums, and a deadline
  • Set to to the router caller; the public add-liquidity functions reject any other LP recipient
  • Set refundTo deliberately; unused amounts are returned there, which may differ from the LP recipient to
  • Expect a composition fee when adding an imbalanced amount to the active bin, because the pool performs an implicit composition swap
  • Estimate gas and batch very wide distributions

Swap fees

The trader-paid DLMM fee is:
The static component is:
where 1e18 represents 100%. In basis points:
The variable component rises quadratically with the volatility accumulator and binStep. The accumulator increases when on-chain swaps move across bins, decays according to the pool’s filter and decay settings, and is capped by maxVolatilityAccumulator.
The variable fee does not observe CEX prices or off-chain volatility. It reacts only after DLMM swaps move through the on-chain price grid.
The main fee parameters are: The total trader fee is capped at 10%. protocolShare changes where the collected fee goes; it does not add another fee to the trade.

Fee and reward routing

Ramses’ Robinhood product policy distinguishes fee-only and gauged DLMM pools: For an ungauged pool, the protocol portion collected by DLMMFeeCollector goes to treasury. The 100%-to-voters gauged policy requires the collector’s independently mutable treasuryFees value to be zero; otherwise that configured skim goes to treasury before the remainder reaches FeeDistributor. Because fee parameters and protocol share are governance-configurable, integrations must read getStaticFeeParameters() from the pool instead of inferring the split from a label.

Rewarder hooks and anti-JIT behavior

The optional DLMMRewarder is a pool hook and the DLMM equivalent of an emission target:
  • Voter sends RAM emissions to the rewarder
  • The rewarder distributes RAM over a configurable band of at most 11 bins around the active bin
  • Rewards are weighted by liquidity valued at the active-bin price, then divided among each bin’s share holders
  • Claims are made by the owner for their own address
When the rewarder hook is linked:
  • Minting to a different recipient requires an authorized manager
  • All LP-share batch transfers are disabled while the rewarder is linked
  • Burning liquidity remains available
  • Recently modified liquidity may forfeit only newly accrued rewards during the anti-JIT cooldown; LP principal is not seized
Rewarder implementations are upgradeable through their beacon. Pool contracts are deterministic immutable clones; changing the factory’s pool implementation affects future pools rather than existing pool clones.

Integration checklist

  1. Discover pools through DLMMFactory; do not manufacture pool addresses from UI data.
  2. Confirm the pool’s actual token order, active ID, bin step, static fee parameters, and hook state.
  3. Quote the full amount and reject partial quotes where amountInLeft or amountOutLeft is non-zero.
  4. Use router deadlines, minimum amounts, and active-ID slippage.
  5. Index per-bin balances and TransferBatch, DepositedToBins, WithdrawnFromBins, and Swap events.
  6. Treat hooks and fee settings as mutable governance-controlled state.
  7. Do not assume the generated HyperEVM API Reference indexes Robinhood DLMM data.

Additional resources