REP: 2002
Title: RadiantMM - Constant Product Market Maker Protocol
Author: Radiant Community Contributors
Status: Draft
Type: Standard
Created: 2026-01-25
License: MIT
Requires: Introspection Opcodes, Reference System
This REP specifies RadiantMM, a Constant Product Market Maker (CPMM) protocol for the Radiant blockchain. RadiantMM enables trustless, permissionless token swaps using a micro-pools architecture that leverages Radiant's native introspection opcodes and reference system. The protocol allows anyone to create liquidity pools, provide liquidity, and execute swaps without intermediaries.
A RadiantMM pool is a single UTXO containing:
- RXD value (native satoshis)
- Locking script enforcing CPMM invariant
- State data (token amount, owner pubkey hash)
- Token reference (for Glyph token pools)
<code_script> OP_STATESEPARATOR <state_script>
Code Script: Immutable logic enforcing CPMM rules State Script: Mutable data (token amount)
Inputs:
[0] Creator's RXD
[1] Creator's tokens (if token pool)
Outputs:
[0] RadiantMM Pool UTXO
- value: initial RXD amount
- script: RadiantMM locking script
- state: initial token amount, creator pkh
Inputs:
[n] RadiantMM Pool UTXO
[...] Trader's funding UTXOs
Outputs:
[n] RadiantMM Pool UTXO (rebalanced)
[...] Trader's received assets
[...] Change outputs
Constraints:
- Output pool must have same locking bytecode as input
K_output >= K_inputwhereK = rxd_value * token_amount- Fee of 0.3% deducted from trade
Inputs:
[0] RadiantMM Pool UTXO
unlockingScript: <signature> <pubkey>
Outputs:
[...] Any outputs (owner discretion)
Constraints:
hash160(pubkey) == owner_pkh(from state)- Valid signature
The constant product invariant:
K = x * y
where:
x = RXD amount (satoshis)
y = Token amount (smallest unit)
K = constant product
For trades:
x_new * y_new >= x_old * y_old
Accounting for 0.3% fee:
(x_new - fee) * y_new >= x_old * y_old
fee = |x_new - x_old| * 3 / 1000
# RadiantMM Pool Contract v1.0
# Check execution path
OP_DEPTH
OP_IF
# WITHDRAWAL PATH
# Stack: <sig> <pubkey>
OP_DUP
OP_HASH160
<owner_pkh> # From state script
OP_EQUALVERIFY
OP_CHECKSIG
OP_ELSE
# TRADE PATH
# Stack: empty
# 1. Verify contract continuity
OP_INPUTINDEX
OP_OUTPUTBYTECODE
OP_INPUTINDEX
OP_UTXOBYTECODE
OP_EQUALVERIFY
# 2. Calculate input K
OP_INPUTINDEX
OP_UTXOVALUE # x_old (RXD in)
<token_amount_in> # y_old (from state)
OP_MUL # K_old = x_old * y_old
# 3. Calculate fee
OP_INPUTINDEX
OP_UTXOVALUE # x_old
OP_INPUTINDEX
OP_OUTPUTVALUE # x_new
OP_SUB
OP_ABS # |x_new - x_old|
3
OP_MUL
1000
OP_DIV # fee
# 4. Calculate output K (with fee deducted)
OP_INPUTINDEX
OP_OUTPUTVALUE # x_new
OP_SWAP
OP_SUB # x_new - fee
<token_amount_out> # y_new (from output state)
OP_MUL # K_new = (x_new - fee) * y_new
# 5. Verify K_new >= K_old
OP_SWAP
OP_GREATERTHANOREQUAL
OP_ENDIF
The state script stores mutable pool data:
<token_amount:8bytes> <owner_pkh:20bytes>
- token_amount: Little-endian 64-bit integer
- owner_pkh: HASH160 of owner's public key
For Glyph token pools, token amounts are verified via:
Option A: State Script (recommended)
# Read token amount from state
OP_INPUTINDEX
OP_STATESCRIPTBYTECODE_UTXO
# Parse token amount from state bytes
Option B: Reference Counting
# Count tokens via reference
<token_ref>
OP_REFVALUESUM_UTXOS
# Compare with expected amount
Multiple pools can be spent in a single transaction:
Transaction:
Inputs:
[0] Pool A
[1] Pool B
[2] Pool C
[n] Trader funding
Outputs:
[0] Pool A (rebalanced)
[1] Pool B (rebalanced)
[2] Pool C (rebalanced)
[n] Trader receives tokens
[n+1] Change
Each pool independently validates its own K constraint.
Spot Price:
price = x / y (RXD per token)
Execution Price (with slippage):
tokens_out = y - (K / (x + rxd_in))
rxd_out = x - (K / (y + tokens_in))
To prevent dust attacks and ensure meaningful trades:
- Minimum RXD per pool: 10,000 satoshis
- Minimum token amount: 1 unit
- Minimum trade: 546 satoshis (dust limit)
- DeFi Foundation: Enables trustless token trading on Radiant
- Liquidity: Provides on-chain liquidity for Glyph tokens
- Price Discovery: Establishes market prices for tokens
- Composability: Atomic swaps enable complex DeFi interactions
- Passive Income: LPs earn fees from trading activity
- No Global State: Each pool is independent
- Permissionless: Anyone can create pools
- Scalable: No coordination required
- Simple: Reduces contract complexity
- Aggregatable: Multiple pools combine for larger trades
| Approach | Complexity | Scalability | Permissionless |
|---|---|---|---|
| Order Book | High | Limited | Yes |
| Single Pool | Medium | Bottleneck | Requires governance |
| Micro-Pools | Low | High | Yes |
1. Why CPMM (x*y=k)?
- Proven formula (Uniswap, etc.)
- Simple to implement in Script
- Provides continuous liquidity at any price
- Well-understood impermanent loss characteristics
2. Why 0.3% Fee?
- Industry standard (Uniswap V2)
- Balances LP incentives with trader costs
- Simple calculation:
amount * 3 / 1000
3. Why No MEV Protection (Phase 1)?
- Reduces complexity
- Radiant's fast blocks limit MEV window
- Can be added in future REP
4. Why State Script for Token Amounts?
- Native support via
OP_STATESEPARATOR - Efficient encoding
- Compatible with introspection opcodes
1. Order Book DEX
- Rejected: Complex state management, poor UX for small trades
2. Single Global Pool
- Rejected: Requires governance, creates bottleneck
3. NFT-Based LP Tokens
- Deferred: Adds complexity, can be added later for public pools
RadiantMM is fully compatible with existing Radiant infrastructure:
- No consensus changes required: Uses existing opcodes
- Wallet compatibility: Standard P2SH transactions
- Indexer support: Pools discoverable via script pattern matching
- Existing tokens: Works with current Glyph token standard
Indexers identify RadiantMM pools by matching the locking script pattern:
RADIANTMM_PATTERN = bytes.fromhex("76a914{pkh}88ac7c...")
def is_radiantmm_pool(utxo):
return utxo.script.startswith(RADIANTMM_CODE_PREFIX)def execute_trade(pools, rxd_in, min_tokens_out):
# Sort pools by price
pools = sorted(pools, key=lambda p: p.price)
# Route trade across pools
tokens_out = 0
remaining_rxd = rxd_in
for pool in pools:
if remaining_rxd <= 0:
break
# Calculate optimal amount for this pool
amount = min(remaining_rxd, optimal_amount(pool))
tokens = pool.get_tokens_for_rxd(amount)
tokens_out += tokens
remaining_rxd -= amount
# Verify slippage
require(tokens_out >= min_tokens_out, "Slippage exceeded")
# Build transaction
return build_swap_tx(pools, rxd_in, tokens_out)interface RadiantMMSDK {
// Pool discovery
getPools(tokenRef: string): Promise<Pool[]>;
getPoolsByLiquidity(minRxd: number): Promise<Pool[]>;
// Price queries
getSpotPrice(tokenRef: string): number;
getExecutionPrice(tokenRef: string, amount: number): number;
// Trading
swap(params: SwapParams): Promise<Transaction>;
// Liquidity
createPool(params: CreatePoolParams): Promise<Transaction>;
withdrawPool(poolUtxo: UTXO, key: PrivateKey): Promise<Transaction>;
}1. Overflow Attack
- Risk: Arithmetic overflow in K calculation
- Mitigation: 64-bit arithmetic limits pool size; validate inputs
2. Front-Running (MEV)
- Risk: Miners/observers can front-run trades
- Mitigation: Slippage limits; future MEV protection REP
3. Price Manipulation
- Risk: Flash loan style attacks
- Mitigation: Use TWAP for price oracles; multiple pool aggregation
4. Dust Attacks
- Risk: Creating many tiny pools
- Mitigation: Minimum pool size requirements
5. Reentrancy
- Risk: None - UTXO model prevents reentrancy by design
- Formal verification of Script logic
- Fuzzing with edge case inputs
- Economic modeling of attack scenarios
- Independent security audit before mainnet
Initial Pool:
RXD: 10,000 satoshis
TOKEN: 1,000 units
K: 10,000,000
Trade: Buy 100 TOKEN
RXD Required:
new_token = 1000 - 100 = 900
new_rxd = K / new_token = 10,000,000 / 900 = 11,111.11
rxd_in = 11,111.11 - 10,000 = 1,111.11
fee = 1,111.11 * 3 / 1000 = 3.33
total_rxd_in = 1,114.44
Final Pool:
RXD: 11,114.44 satoshis
TOKEN: 900 units
K: 10,003,000 (>= 10,000,000 ✓)
Pool UTXO:
value: 10,000 satoshis
script: <RadiantMM with owner_pkh=abc123...>
Unlock with:
<valid_sig> <pubkey_hashing_to_abc123>
Result: Pool destroyed, funds released
- Contract finalization and testing
- Basic SDK implementation
- Testnet deployment
- Security audit
- Web interface for swaps
- Pool creation UI
- Wallet integrations
- Indexer infrastructure
- Analytics dashboard
- Documentation and guides
- MEV protection mechanisms
- Public pools with LP tokens
- Alternative AMM curves
This document is licensed under the MIT License.