What is a DLMM
A DLMM splits liquidity into a row of discrete price bins instead of one continuous curve. Each bin trades at a fixed price; only the active bin, the one sitting at the current market price, has both assets available to swap. LPs pick which bins to fund. Fund bins close to the price and you get tight, efficient liquidity; spread across more bins and you get a wider, more passive position, closer to a classic AMM.
This bin-based approach (sometimes called a liquidity book) already runs in production on other chains. StellarBin brings the same pattern to Stellar: written from scratch in Rust for Soroban, with a fee that moves with trading activity instead of sitting fixed.
StellarBin runs on Stellar Testnet right now. Every contract address, balance, and token in this document is a test asset with no real value. There's a reference client live at app.stellarbin.xyz if you want to see it in action.
Target users & design goals
StellarBin is built for two kinds of users.
Liquidity providers want capital efficiency. The wide, shallow ranges of a constant-product AMM tie up capital that never actually gets used. Bins let LPs concentrate where the price sits right now, and anyone who'd rather not manage individual bins can deposit into the vault instead (Section 6).
Traders want tight spreads and low slippage, including on brand-new pairs. That's what Launch Pools are for: swaps stay closed until an activation time, so snipers can't get in before real liquidity has a chance to form (Section 3).
Three design goals follow from that:
- Pools are permissionless — anyone can spin up a Standard or Launch Pool without going through an admin allowlist.
- Fees move with volatility, so LPs aren't left exposed when fast traders start picking off stale prices (Section 4).
- Pricing math, core swap logic, and the vault live in separate contracts, so each piece can be audited and reused on its own (Section 5).
Discrete-bin liquidity model
Liquidity sits in discrete bins around the active bin. Each bin is one fixed price step away from the active bin, sized by the pool's bin_step_bps parameter. A bin's offset can go up to MAX_BIN_OFFSET = 500 steps from the active bin in either direction.
The math library's own unit tests (Section 5) pin down the pricing formula: price(offset) = (1 + bin_step_bps / 10000) ^ offset. For pool 0 (bin step 25 bps), that gives the price ladder shown at the top of this document — derived values for illustration, not on-chain reserve data:
| Bin offset | -3 | -2 | -1 | 0 (active) | +1 | +2 | +3 |
|---|---|---|---|---|---|---|---|
| Price ratio | 0.9925 | 0.9950 | 0.9975 | 1.0000 | 1.0025 | 1.0050 | 1.0075 |
A swap that crosses bin boundaries walks through multiple bins in one transaction (see bins_crossed in the swap result, Section 5). Two pool modes are supported:
- Standard Pool — tradeable immediately after creation.
- Launch Pool — swaps stay gated until a set activation time, anti-snipe protection for new listings.
Dynamic fee model
The fee isn't fixed. get_dynamic_fee scales it by how long it's been since the last trade — back-to-back trades pay close to double the base fee, and it decays back to base_fee_bps once the pool goes quiet for 300+ seconds (confirmed by the test case below). The logic: charge more when the market's moving fast and informed traders are more likely picking off stale bin prices, less when things are calm.
test_bin_price_active (offset 0 → price = SCALAR), test_bin_price_positive (step 10000 bps, offset +1 → price = 2.0), test_bin_price_negative (offset −1 → price ≈ 0.5), test_dynamic_fee_no_activity (0 seconds since last trade → 2× base fee), test_dynamic_fee_stale (300+ seconds → base fee only), and test_compute_y_from_x.
On-chain contract architecture
Three Soroban contracts make up the protocol. The core DLMM contract calls into the math library for pricing and fees. The vault stands alone, no dependency on either of the other two.
flowchart LR
subgraph Client["Any Soroban-compatible client"]
C["Swap / liquidity client"]
W["Wallet: Freighter / Albedo"]
end
subgraph Chain["Stellar Soroban"]
RPC["Soroban RPC"]
DLMM["DLMM contract
bins, swaps, liquidity"]
MATH["Math library
bin pricing, dynamic fee"]
VAULT["Vault contract
share-based yield"]
end
W -- "signs" --> C
C -- "simulate / build tx" --> RPC
C -- "submit signed tx" --> RPC
RPC --> DLMM
DLMM --> MATH
RPC --> VAULT
dlmm ──depends on──▶ math vault ──standalone──▶ (no dependency on math or dlmm) math ──standalone──▶ (pure library, can be deployed as an on-chain utility)
Deployed contracts (Stellar Testnet)
| Contract | Address |
|---|---|
| DLMM (core protocol) | CCW5MVYJFJPBJNJY7GN6BHC5BQR47RXVIM2T2X4F3YSQC7MQ7J4GNESH |
| Vault | CCDVBRMT3BI65JV2C7AQJOSIGT76MNNTXSVYDKGXKPBSOKVWQRGKU7VI |
| Math library | CB7U2EL6L4AR2IWANOSXDYVHWL3D3PD3XOZU6PUA4MDAVWCOT3AAVX4Z |
| Native XLM (Stellar Asset Contract) | CDLZFC3SYJYDZT7K67VZ75HPJVIEUVNIXF47ZG2FB2RMQQVU2HHGCYSC |
| TESTUSD (Stellar Asset Contract) | CCA733ILFGI7SESYWNBYTKHUJTJTSU2ORRT6SFNSDZWHYSE4WDLLDUND |
Pool 0 is the default seeded Standard Pool: XLM / TESTUSD, bin step 25 bps, base fee 10 bps.
DLMM contract storage
| Storage key | Type | Description |
|---|---|---|
POOL_CFG | PoolConfig | Pool configuration: tokens, fee, admin |
ACTIVE | i32 | Current active bin |
LAST_TS | u64 | Timestamp of the last trade |
("BIN", bin_id) | BinReserves | Token reserves for a specific bin |
DLMM contract functions
| Function | Parameters | Returns | Description |
|---|---|---|---|
initialize | admin, token_x, token_y, bin_step_bps, base_fee_bps, active_bin_id | — | One-time pool initialization |
add_liquidity_bin | caller, bin_id, amount_x, amount_y | — | Add liquidity to a specific bin |
remove_liquidity_bin | caller, bin_id | — | Withdraw all liquidity from a bin |
swap_exact_in_bin | caller, x_to_y, amount_in, min_amount_out | SwapResult | Swap with a slippage guard |
simulate_swap | x_to_y, amount_in | SwapResult | Read-only quote, no state change |
get_active_bin | — | i32 | Current active bin id |
get_bin_reserves | bin_id | BinReserves | Token X & Y reserves in a bin |
get_config | — | PoolConfig | Full pool configuration |
Math library functions
| Function | Parameters | Returns | Description |
|---|---|---|---|
get_bin_price | bin_step_bps, offset | i128 | Bin price, fixed-point at 1018 |
get_dynamic_fee | base_fee_bps, seconds_since_last_trade | i128 | Effective fee in basis points |
Data types
// Returned by swap_exact_in_bin and simulate_swap struct SwapResult { amount_out: i128, // output token received (stroops) fee_paid: i128, // total fee deducted (stroops) bins_crossed: u32, // number of bins traversed by the swap final_bin: i32, // active bin after the swap } // Reserve balances for one bin struct BinReserves { reserve_x: i128, // token X in this bin (scaled 10^18) reserve_y: i128, // token Y in this bin (scaled 10^18) } // Pool configuration struct PoolConfig { token_x: Address, // base token SAC address token_y: Address, // quote token SAC address bin_step_bps: i128, // price spacing between bins, in bps base_fee_bps: i128, // base fee before volatility adjustment admin: Address, // pool admin }
Numeric conventions used throughout the contracts:
| Context | Unit | Example |
|---|---|---|
| Token amounts in contracts | Stroops (107) | 1 XLM = 10,000,000 stroops |
| Fixed-point math (SCALAR) | 1018 | 1.0 = 1,000,000,000,000,000,000 |
| Fees | Basis points (bps) | 25 bps = 0.25% |
| Bin prices | SCALAR-scaled i128 | get_bin_price(25, 0) = SCALAR |
Yield vault
The vault handles deposits and withdrawals through share-based accounting, ERC-4626 style: depositors get shares proportional to the vault's net asset value, and nav_per_share tracks how that value grows over time. It's a standalone contract, no dependency on DLMM or math.
| Function | Parameters | Returns | Description |
|---|---|---|---|
initialize | admin, asset, deposit_cap, performance_fee_bps | — | Vault setup |
deposit | depositor, amount | i128 (shares) | Deposit the underlying asset, receive shares |
withdraw | caller, shares | i128 (assets) | Redeem shares for the underlying asset |
allocate_to_yield | amount | — | Admin-only: allocate idle assets to a yield venue |
nav_per_share | — | i128 | Net asset value per share |
balance_of | addr | i128 | Share balance of an address |
total_assets | — | i128 | Total assets held by the vault |
allocate_to_yield exists but doesn't do anything yet — it's a stub, built with an external vault interface in mind, not wired to a live protocol on testnet. Sections 9 and 10 cover what it would take to finish this.
Transaction flow
Submitting a signed on-chain action, whether from the reference web app or a third-party integrator, follows the same six steps:
- Encode the call arguments client-side (e.g. amount in, minimum amount out, direction).
- Build an unsigned transaction invoking the target contract function.
- Simulate the transaction via Soroban RPC to derive fees and required authorizations.
- Assemble the final transaction using the simulation result.
- Request a signature from the connected wallet (Freighter or Albedo in the reference client).
- Submit the signed transaction to the network and await the result.
Read-only calls, quotes through simulate_swap, pool state through get_config or get_bin_reserves, use the same RPC simulation path with no signature needed. That's also exactly the pattern a DEX-aggregator adapter would use to pull a quote before executing (Section 10).
Deployment status
| Network | Status |
|---|---|
| Testnet | Live — contracts deployed and seeded, addresses in Section 5, reference client reachable at app.stellarbin.xyz |
| Futurenet / Devnet | Deployment procedure documented (Stellar CLI steps); not evidenced as currently deployed |
| Mainnet | Deployment procedure documented only; not deployed |
Before mainnet, the project's own checklist still has these open: a completed security audit, an admin account funded with enough XLM for storage deposits, a week of stable testnet operation, separate mainnet contract IDs, and active monitoring on swap/liquidity events.
Next improvements
Stacking StellarBin's contracts up against how mature bin-based DLMMs elsewhere handle things points to four concrete improvements.
1. A configurable protocol/LP/host fee split
Most production bin-based DLMMs split the trading fee three ways: most of it to the LP whose bin filled the trade, a smaller cut to a protocol treasury, and sometimes a slice to whichever front-end or aggregator routed the trade in (a "host fee"). 80-90% to LPs and 10-20% to the protocol is a typical range, with newer, riskier pools often taking a bigger protocol cut. StellarBin's PoolConfig (Section 5) only has one base_fee_bps field right now, no split. Adding one gives the protocol actual revenue, and gives it something to offer aggregators when negotiating a host fee (Section 10).
2. A claimable protocol-fee balance and on-chain events
Once there's a split, add a claim/withdraw function for the protocol's cut, and emit events for swaps, liquidity changes, and fee accrual. That gives the team, and any integrator, a way to verify revenue and LP yield on-chain instead of maintaining a separate off-chain ledger.
3. Complete the vault's external yield integration
allocate_to_yield (Section 6) doesn't do anything yet. Wire it to a live, audited yield protocol on Stellar and idle vault capital starts earning a base yield on top of trading fees. Section 10 covers the closest candidate available right now.
4. Independent security audit before mainnet
This is already on the mainnet checklist (Section 8). Worth repeating here because it's the prerequisite for the fee-split and yield-integration work above being trusted with real money.
Ecosystem integration & routing
Trading volume doesn't only have to come through StellarBin's own client. DEX aggregators scan on-chain liquidity and route trades to whichever pool prices best, so getting listed brings in flow the pool wouldn't see on its own. Three Stellar-focused aggregators were looked at as integration targets: Soroswap Aggregator, and WOWMAX.
Soroswap Aggregator
Soroswap Aggregator is a Soroban contract that splits a swap across multiple Soroban AMMs. It calls this DexDistribution, and it picks the protocols, how much of the trade goes to each, and the token path. Right now it covers the Soroswap AMM (mainnet) plus Phoenix and Aqua (testnet, per Soroswap's own docs). Each AMM plugs in through an adapter contract implementing SoroswapAggregatorAdapterTrait, one shared interface for init, data retrieval, and swap execution, so the Aggregator can talk to differently-built AMMs the same way.
For StellarBin, that means writing one adapter contract that translates the Aggregator's calls into StellarBin's own simulate_swap (for quotes) and swap_exact_in_bin (for execution). Both already exist in roughly the shape an adapter needs (Section 5), so this isn't starting from zero.
WOWMAX
WOWMAX is a DEX aggregator and on-chain copy-trading platform. Its marketing site lists 14 EVM chains — Ethereum, BNB Chain, Base, HyperEVM, Cronos, Linea, Scroll, Manta Pacific, Blast, Metis, Arbitrum, ZetaChain, Polygon, Soneium — and Stellar isn't one of them. But WOWMAX's own GitHub testing repo describes its stack as including "the Stellar DEX router" alongside a multi-bridge aggregator covering Allbridge, Squid's Coral V2 RFQ, and Near Intents, and its official social channels have posted about Stellar integration work, including cross-chain routing via Aurora/NEAR Intents.
The marketing site and the GitHub/social evidence don't line up. Treat WOWMAX's Stellar support as unconfirmed, not as an active integration target, until the WOWMAX team clarifies it directly through their developer docs and API.
| Aggregator | Stellar liquidity it covers | Integration mechanism | Status for StellarBin |
|---|---|---|---|
| Soroswap Aggregator | Soroswap AMM (mainnet); Phoenix & Aqua (testnet) | Adapter contract implementing SoroswapAggregatorAdapterTrait | Not yet integrated; existing simulate_swap / swap_exact_in_bin functions are compatible primitives |
| WOWMAX | 14 listed EVM chains; a separate "Stellar DEX router" referenced in WOWMAX's own GitHub/social channels but not on its main chain list | Not publicly documented for Stellar as of research date | Not yet integrated; Stellar scope unconfirmed — verify with WOWMAX directly |
Yield-vault integration candidate
For the vault's allocate_to_yield stub (Sections 6 and 9): the closest active, documented candidate found here is DeFindex. It publishes developer docs, a quickstart, and an API reference for routing deposits into Stellar yield strategies. Worth evaluating, not yet a confirmed integration.
Known limitations
- Testnet. Every balance and token in this document is a test asset with no real value.
- No audit has happened or been documented yet — it's an open item on the project's own mainnet checklist.
allocate_to_yieldis a stub, not connected to any live yield protocol.- Fees are a single base rate per pool, no protocol/LP/host split yet.
- No aggregator integration is live yet. All three (Soroswap Aggregator, WOWMAX) are prospective, and WOWMAX both need direct confirmation of what integration would even require.
Sources & scope of this document
Every claim above comes from the project's own repository or from publicly published third-party documentation, all retrieved on September 16, 2026:
- Repository README — github.com/dikikarim2004/StellarBin-DLMM
SMART_CONTRACT_GUIDE.md— architecture, storage layout, function reference, deployment steps, troubleshooting, and mainnet checklist- Live testnet application — app.stellarbin.xyz
- Soroswap.Finance documentation — docs.soroswap.finance (Aggregator concept, adapters, and supported AMMs)
- WOWMAX public site, developer documentation, and GitHub benchmark repository — wowmax.exchange, docs.wowmax.exchange, github.com/wowmax-exchange/wowmax-benchmarks
The bin-price ladder in the cover illustration and Section 3 is computed from get_bin_price's documented test behavior, not read from chain state. The fee-split ranges in Section 9 describe a general industry pattern, not a specific competitor. Nothing here claims performance, TVL, volume, or audit results beyond what the sources above actually say, and anything flagged "not publicly documented" or "unconfirmed" in Sections 10-11 needs a direct answer from that team before it goes in a submission.