Context
Why a second venue at all
The primary market (LMSR PM) mints portable Yes / No ERC-20s. This DEX is the first concrete place those tokens can go, but we also want to demonstrate dual price discovery before event resolution and price alignment between multiple venues.
Intent
The ERC-20 prediction market proves that LMSR claims can leave the venue as ordinary tokens. Now we want to ask where they can go to and build a contract that uses those tokens without knowing anything about logarithmic market scoring rules or any claims associated with event outcomes.
We select a contract from the CFMM contract family, a Uniswap-V2-style constant-product DEX whose pools hold two tokens and price them against each other on a curve. We allow Yes / No ERC-20 tokens of the same event (and optionally PTE) which have been already issued by the LMSR primary market. By this construction we want to demonstrate a few things: secondary trading, liquidity provision, and how prices and price finding processes might differ between different venues, especially if the underlying mechanisms are different.
Where it runs
The DEX dapp is live at
dex.tokenengineeringlabs.com
on the same networks as the tokenized market: Sepolia and
UZH ETH PoS. Pools are created against markets from
pm-erc20.tokenengineeringlabs.com; using the same token notations across both frontends (for example PTE-E9S,
E9S-{id}-Y / -N).
What this is not
This is not a primary market, and has nothing to do with the event resolution, the eligibility to claim collateral at resoution, not is it a required step in the prediction-market lifecycle. You can buy Yes on the primary market, never open the DEX, and still settle after resolution. The DEX is an optional secondary surface: useful when someone wants to rebalance exposure against pool reserves (although this is also directly possibly by adjusting LMSR inventory), provide liquidity, or study how two independent pricing rules sit on the same ERC-20 balances.
Architecture
Factory, pair, router
Three contract types — who may create pools, where reserves live, and
what wallets approve — plus how a pool stays linked to an LMSR
marketId.
Contract types
The DEX splits the usual constant-product pattern into three pieces:
-
DexFactory— registry and gate for creating pools. Pool creation requiresPOOL_CREATOR_ROLE; swaps do not. -
ConstantProductPair— one pool instance: holds the two ERC-20 reserves, enforces , and issues its own LP ERC-20 to liquidity providers. -
DexRouter— the entrypoint traders and LPs approve. It routesswap,addLiquidity, andremoveLiquidityinto the right pair.
Outcome tokens and PTE are not deployed by the DEX. They are the same contracts the prediction market already minted or referenced. The pool only needs their addresses, allowances, and balances.
xy = k; the router is what wallets approve. Claim tokens
are imported addresses, not DEX-minted assets.
Pool types and fees
DexFactory.createMarketPool creates at most one pool per
(marketId, poolType). v1
PoolType values are only:
-
YES_NO— Yes claim ↔ No claim. -
YES_PTE— Yes claim ↔ PTE collateral (predictionMarket.bettingToken()). There is noNO_PTEenum in this deployment.
The swap fee is set once as immutable feeBps on the pair
(default constant DEFAULT_FEE_BPS = 30, i.e. 0.30%; hard max
MAX_FEE_BPS = 1000). After creation the fee does not change —
operator policy is visible up front and cannot drift mid-experiment.
Resolution gate (contract vs UI)
On-chain, ConstantProductPair gates trading with
_requireMarketActive(): it reads the linked market’s
resolved flag and reverts with
"market resolved" on swap and
mint (add liquidity). burn (remove liquidity)
does not call that check, so LPs can always unwind residual
reserves after resolution.
The dapp is stricter for teaching UX: when the underlying PM market is expired or resolved, the pool workspace freezes swap / add controls and leaves remove-liquidity as the exit path. Expiry alone does not flip the Solidity gate — only resolution does — but the UI treats a closed market as done for new flow.
Settlement of winning claims still happens on the primary market (burn winners, pay PTE). The DEX does not pay out event outcomes; it only returns whatever ERC-20 balances remain in the pair.
Lifecycle
Flows
Operator creates and seeds; anyone swaps; LPs enter and exit — all against tokens that already exist in wallets.
Create pool
Pool creation is the privileged step that wires a secondary market to a primary one:
-
An address with POOL_CREATOR_ROLE picks an existing
LMSR
marketId, a pool type (Yes/No or Yes/PTE), and afeeBps. -
The factory deploys a
ConstantProductPairand records the link to that market. -
The operator (or another funded LP) seeds initial reserves via
addLiquidityso the invariant has a starting .
Until someone deposits both sides, the pool exists but has nothing to trade against. Seeding is a separate economic choice from creating the market on the LMSR venue.
xy = k pool linked to an existing
LMSR market (here #38). The pool will trade that market’s
claim ERC-20s; it does not call buyShares. Fee is fixed
at creation.
Add and remove liquidity
Liquidity providers deposit both reserve assets in the ratio the pool currently prices, receive the pair’s LP ERC-20, and later burn LP tokens to withdraw a proportional share of reserves (minus fees collected by the pool’s accounting). After market resolution, new deposits stop; withdrawals remain so inventory is not stranded.
Swap
A swap is an ordinary ERC-20 exchange against the pair’s reserves under
the constant-product rule (with the pool’s feeBps taken
from the input). The trader’s wallet sends token A and receives token B;
the pair’s balances update; Yes/No totalSupply on the
outcome contracts does not change.
That last point is the whole composability claim in one sentence: the secondary venue can rearrange who holds claims without rewriting the primary market’s inventory . Only LMSR mint and burn move .
Economics
Two prices, one token
Dual venues share the same claim ERC-20s but not the same pricing rule. Curvature, issuance, LP, and exit paths are the interesting part — not just that two numbers can differ.
Dual price discovery
After tokenization, the same Yes token can show two different prices at once:
- Primary (LMSR). The cost of minting or burning against
the market’s cost function
— the quote the
prediction-market UI shows for
buyShares/sellShares. - Secondary (CFMM). The marginal rate implied by pool
reserves under , after the
pool’s immutable
feeBps.
Those quotes are free to diverge. When they do, anyone who can trade on both venues can attempt arbitrage: buy cheap on one side, sell rich on the other, until costs (fees, gas, inventory, resolution risk) stop the trade. That loop is an economic coupling. There is no protocol call from the DEX into the LMSR that “syncs” prices.
LMSR is already a market — primary and secondary in one
It helps to be precise about what “primary” means here. An LMSR venue is not only an issuer. It is a continuous automated market against a shared cost function: every buy mints claims into existence (issuance), every sell burns them back (redemption), and the marginal price after each trade is whatever the cost function says at the new inventory . In that sense the LMSR is both the place where shares are created and the place where they are priced against collateral — a primary issue desk and a secondary book in one mechanism.
How sensitive that book is to a given trade size is governed by the liquidity / curvature parameter chosen at market creation. Small : the same moves prices a lot (cheap to open, twitchy). Large : prices move slowly (deeper book, more subsidy). That curvature is the LMSR’s answer to “how much does this trade hurt the mid?”
The DEX is secondary only — same idea, different bonding curve
The CFMM is also a bonding-curve market, but it never issues claims. It only re-prices and redistributes tokens that already exist. Liquidity providers deposit Yes / No (or Yes / PTE) into a pair; those balances become the inventory other traders can swap against under . A swap changes pool reserves and therefore the DEX mid — and nothing else about LMSR .
So both venues answer “what is Yes worth right now?” with a curve, but they answer different operational questions:
- LMSR: what does it cost to create or destroy this exposure against the shared subsidy / collateral pool?
- DEX: what does it cost to exchange existing balances against whoever LPed into this pair?
That is why a trade of size
can have completely
different slippage on the two venues even when the starting mids look
close. LMSR slippage is shaped by
and the current
; CFMM slippage is shaped by
reserve depth, the constant-product geometry, and feeBps.
Cross-checking average trade slippage, quoted mid, or a median fill
across venues is therefore a real empirical exercise on this stack — not
a duplicate meter reading the same formula twice.
xy = k.
What do you do with your shares?
Once Yes or No sits in a wallet, the holder faces a portfolio choice the ledger market never offered:
- Hold to resolution. Do nothing until the market resolves, then claim through the primary venue if you hold the winning side. You earn the event payoff (or zero) — not trading fees.
- Sell back to the LMSR. Burn via
sellShareswhile the market is still open; exit into PTE at the primary curve. - Trade on the DEX. Swap into the other claim or into PTE against pool reserves without touching issuance.
- Provide liquidity. Deposit into a Yes/No or Yes/PTE pool, receive LP tokens, and earn a share of the pool’s swap fees while your inventory sits in the curve. You are paid for making the secondary book — and you take on inventory / impermanent-loss style risk relative to simply holding the claims.
LP is the clearest “new verb” tokenization unlocks here: the same shares that used to be trapped as ledger balances can now earn fee income by staffing a second venue.
Withdrawing, selling back, and waiting for convergence
LP is not free optionality. To sell back into the LMSR, or to hold a naked
claim through resolution, you usually need the underlying Yes/No (or PTE)
in your wallet again — which means
removeLiquidity first. That exit has consequences:
- You realize whatever reserve ratio the pool currently prices (your LP share of token0 / token1), which may differ from the mix you deposited.
- You stop earning fees the moment you leave the pool.
-
Only after withdrawal can you
sellShareson the primary market, transfer peer-to-peer, or simply wait for resolution and claim.
If the two venues disagree, waiting can be a strategy as much as trading: in expectation, active arbitrage and overlapping trader sets push the quotes toward each other until frictions dominate. That convergence in expectation is an economic claim, not a consensus rule — spreads can persist when pools are thin, fees are wide, gas is expensive, or resolution is near and inventory risk dominates.
Closing the book: resolution and exploit prevention
After the event is decided, continuing to swap against stale reserves
would be a gift to anyone who already knows the outcome. The pair
therefore gates swap and mint (add liquidity)
once the linked market’s resolved flag is true;
burn / remove liquidity stays open so LPs are not stranded.
The dapp goes further for teaching UX and freezes new flow when the
market is expired or resolved, leaving remove as the
exit path.
Settlement value still comes only from the primary market’s claim path. The DEX never pays winners; it only returns whatever ERC-20 balances remain in the pair. That separation is deliberate exploit prevention: secondary trading cannot mint a free lottery ticket after the result is known, and it cannot rewrite LMSR inventory after the fact.
What a DEX swap does not do
- It does not mint or burn Yes / No.
- It does not move PTE collateral held by the prediction market.
- It does not change LMSR .
- It does not resolve the event or pay winners.
- It does not sync the LMSR quote on-chain.
It only moves ERC-20 balances between the trader and the pair (and
updates the pair’s internal reserves / LP accounting). For the ownership
/ mint-boundary diagram on the primary-market article, see
ERC-20 prediction market
(docs/pm-erc20-lmsr-dex-composability-brief.md).
Surface
How the dapp presents it
Course-style onboarding, a pools list linked to LMSR markets, and a Simple / Analytical mode toggle for teaching depth.
Onboarding
The live UI mirrors the prediction-market dapp’s checklist pattern: connect a wallet, match the app network (Sepolia or UZH ETH PoS), import the deployment-tagged PTE, approve the DEX router, then open a pool to swap or provide liquidity. Gas is native ETH on the chosen chain; trading inventory is PTE and claim ERC-20s.
Pools as the unit of attention
Traders do not browse “all ERC-20s.” They browse pools linked to prediction markets — each row carries the market question, pool type, fee, and the actions that matter (swap, add, remove). That framing keeps the secondary venue readable in a classroom: the pool is a consequence of a named event market, not an anonymous pair address.
Simple vs Analytical
The dapp exposes a header toggle (shared pattern with the PM app). Simple (default) keeps swap and liquidity controls — connect, approve, trade — without CFMM curves or heavy stats. Analytical adds the curve / reserve breakdown on the pool workspace. Same contracts; two depths of UI.
Curation chrome
Pool cards also carry light curation controls from the E9 UI sweep:
Hide for me (browser-local), and curator
Archive for all when the caller has PM
CREATOR_ROLE or factory POOL_CREATOR_ROLE.
Purple wallet affordances import the pool’s outcome claim tokens and the
LP ERC-20 the same way the PM dapp imports Yes/No.
Bridge
Toward the World Cup experiment
Dual-venue rails on UZH ETH PoS are what make a live classroom market more than a single buy button.
Why this comes before the field write-up
The UZH World Cup prediction market is a field experiment: participants traded live during a summer-school setting on the tokenized market stack. To talk honestly about what they could do — primary buys, wallet custody of claims, optional secondary swaps, operator-seeded liquidity — the secondary venue has to be documented as its own surface.
This article is that surface. The World Cup write-up can then focus on
experiment design, participation, and what the classroom learned, instead
of pausing to explain
and
POOL_CREATOR_ROLE.
Takeaway
ERC-20 claims make a second venue possible; the CFMM DEX makes it concrete. The LMSR both issues and prices; the DEX only re-prices what LPs supply — same token, different bonding curve, different slippage for the same . Holders can wait for resolution, sell primary, swap secondary, or earn fees as LPs; in expectation the two quotes converge when arbitrage is cheap enough. Operators gate pool creation; resolution freezes trading but not LP exit; LMSR inventory moves only on the primary market. That dual-venue surface is the composability demo — and the mechanical preface to the World Cup experiment narrative.
Related
- ERC-20 Prediction Market — primary LMSR venue that mints the claim tokens this DEX trades.
- On-Ledger Market for Event Contingent Claims — precursor without transferable claims (no DEX hook).
- UZH World Cup Prediction Market — field experiment on these rails (write-up next).
- Claim Representation and Implementation Standards — why one ERC-20 per outcome does not scale to combinatorial markets.