Testnet

StellarBin — Technical Architecture Document

A discrete-bin, dynamic-fee liquidity market maker (DLMM) for Stellar, built with Soroban smart contracts. Covers the DLMM concept, the on-chain contract architecture, who it's for, where it falls short today, and how it plugs into Stellar's DEX-routing ecosystem.

Live testnet app: app.stellarbin.xyz
-3 -2 -1 0 +1 +2 +3 0.9925 0.9950 0.9975 1.0000 1.0025 1.0050 1.0075 active bin (pool 0, bin_step = 25 bps)
01

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.

Current status

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.

02

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).
03

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-10 (active)+1+2+3
Price ratio0.99250.99500.99751.00001.00251.00501.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.
04

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.

Documented test coverage (math library)

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.

05

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)

ContractAddress
DLMM (core protocol)CCW5MVYJFJPBJNJY7GN6BHC5BQR47RXVIM2T2X4F3YSQC7MQ7J4GNESH
VaultCCDVBRMT3BI65JV2C7AQJOSIGT76MNNTXSVYDKGXKPBSOKVWQRGKU7VI
Math libraryCB7U2EL6L4AR2IWANOSXDYVHWL3D3PD3XOZU6PUA4MDAVWCOT3AAVX4Z
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 keyTypeDescription
POOL_CFGPoolConfigPool configuration: tokens, fee, admin
ACTIVEi32Current active bin
LAST_TSu64Timestamp of the last trade
("BIN", bin_id)BinReservesToken reserves for a specific bin

DLMM contract functions

FunctionParametersReturnsDescription
initializeadmin, token_x, token_y, bin_step_bps, base_fee_bps, active_bin_idOne-time pool initialization
add_liquidity_bincaller, bin_id, amount_x, amount_yAdd liquidity to a specific bin
remove_liquidity_bincaller, bin_idWithdraw all liquidity from a bin
swap_exact_in_bincaller, x_to_y, amount_in, min_amount_outSwapResultSwap with a slippage guard
simulate_swapx_to_y, amount_inSwapResultRead-only quote, no state change
get_active_bini32Current active bin id
get_bin_reservesbin_idBinReservesToken X & Y reserves in a bin
get_configPoolConfigFull pool configuration

Math library functions

FunctionParametersReturnsDescription
get_bin_pricebin_step_bps, offseti128Bin price, fixed-point at 1018
get_dynamic_feebase_fee_bps, seconds_since_last_tradei128Effective 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:

ContextUnitExample
Token amounts in contractsStroops (107)1 XLM = 10,000,000 stroops
Fixed-point math (SCALAR)10181.0 = 1,000,000,000,000,000,000
FeesBasis points (bps)25 bps = 0.25%
Bin pricesSCALAR-scaled i128get_bin_price(25, 0) = SCALAR
06

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.

FunctionParametersReturnsDescription
initializeadmin, asset, deposit_cap, performance_fee_bpsVault setup
depositdepositor, amounti128 (shares)Deposit the underlying asset, receive shares
withdrawcaller, sharesi128 (assets)Redeem shares for the underlying asset
allocate_to_yieldamountAdmin-only: allocate idle assets to a yield venue
nav_per_sharei128Net asset value per share
balance_ofaddri128Share balance of an address
total_assetsi128Total 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.

07

Transaction flow

Submitting a signed on-chain action, whether from the reference web app or a third-party integrator, follows the same six steps:

  1. Encode the call arguments client-side (e.g. amount in, minimum amount out, direction).
  2. Build an unsigned transaction invoking the target contract function.
  3. Simulate the transaction via Soroban RPC to derive fees and required authorizations.
  4. Assemble the final transaction using the simulation result.
  5. Request a signature from the connected wallet (Freighter or Albedo in the reference client).
  6. 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).

08

Deployment status

NetworkStatus
TestnetLive — contracts deployed and seeded, addresses in Section 5, reference client reachable at app.stellarbin.xyz
Futurenet / DevnetDeployment procedure documented (Stellar CLI steps); not evidenced as currently deployed
MainnetDeployment 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.

09

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.

10

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.

AggregatorStellar liquidity it coversIntegration mechanismStatus for StellarBin
Soroswap AggregatorSoroswap AMM (mainnet); Phoenix & Aqua (testnet)Adapter contract implementing SoroswapAggregatorAdapterTraitNot yet integrated; existing simulate_swap / swap_exact_in_bin functions are compatible primitives
WOWMAX14 listed EVM chains; a separate "Stellar DEX router" referenced in WOWMAX's own GitHub/social channels but not on its main chain listNot publicly documented for Stellar as of research dateNot 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.

11

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_yield is 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.
12

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:

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.