Post
Share your knowledge.
How can I create a Perp DEX model
I'm particularly interested in how perpetual DEXs like Bluefin are implemented on Sui. How can I design a perpetual futures protocol that handles margin, funding rates, and liquidations efficiently on-chain? Specifically, how are virtual AMM mechanisms or order book models structured and how does the system maintain balance between long and short positions as price volatility changes?
- Sui
- Architecture
- Move
Answers
6One of the perp DEX in SuI is bluefin. You can reference the code of package through this link https://suivision.xyz/package/0xbf8ccc28a4ef26e8f5f5ea384096c52a38552a9cd84306294631ece2348bb2cf?tab=Code This is source code convert from bytecode
Read the module perpetual It manages the state of each perpetual market, including:
- Risk settings (margin, leverage)
- Fees (maker/taker)
- Funding rate system
- Oracle pricing
- Open user positions
Main Struct: PerpetualV2
struct PerpetualV2 has key {
id: UID, // Unique market ID
version: u64, // Version control
name: String, // Market name (e.g., ETH-PERP)
imr: u128, // Initial Margin Requirement
mmr: u128, // Maintenance Margin Requirement
makerFee / takerFee: u128, // Trading fees
insurancePoolRatio: u128, // Share of fees going to insurance
insurancePool: address, // Insurance pool address
feePool: address, // Fee collector address
delisted: bool, // Is this market closed?
delistingPrice: u128, // Fixed price if delisted
isTradingPermitted: bool, // Is trading currently allowed?
startTime: u64, // When market was launched
checks: TradeChecks, // Order validation config
positions: Table<address, UserPosition>, // Each trader's position
specialFee: Table<address, SpecialFee>, // VIP fee overrides
priceOracle: u128, // Latest oracle price
funding: FundingRate, // Funding rate config
priceIdentifierId: vector<u8>, // Link to oracle
}
Key Concepts & How They Work
1. Margin Requirements
- IMR (Initial Margin Requirement): Needed to open a position (e.g., 10% of size)
- MMR (Maintenance Margin Requirement): Minimum to avoid liquidation (e.g., 5%)
- Stored per market (ETH-PERP, BTC-PERP, etc.)
- Controlled via
set_initial_margin_required_v2()andset_maintenance_margin_required_v2()
2. Funding Rate
-
Keeps long and short positions balanced.
-
If too many longs: longs pay shorts, and vice versa.
-
Funding logic handled in
fundingfield (aFundingRatestruct). -
Updated using:
set_funding_rate_v2(clock, caps, fund_cap, perp, rate, is_positive, oraclePrice)
3. Oracle Integration
-
Oracle price fetched from an external module like
price_info. -
Updated by:
update_oracle_price(&mut perp, &price_info_object) -
Price stored in
priceOraclefield. -
Used for:
- Liquidation checks
- Funding calculations
- Delisting price validation
4. User Positions Table
positions: Table<address, UserPosition>
- Each trader’s position is stored here.
- Includes info like:
- Long/short
- Entry price
- Size
- PnL (unrealized)
- You manage this when a user opens or closes a trade.
5. Fees
makerFeeandtakerFee(default for everyone)specialFeetable for VIP users or promotionsget_fee_v2(address, perp, is_maker)returns the correct fee- All fees go to
feePool, a Sui address
6. Insurance Pool
- A % of every trade (defined by
insurancePoolRatio) goes toinsurancePool - Used to cover bad debt or liquidation losses
7. Event Emission
The module emits rich event logs for:
- Market creation:
PerpetualCreationEvent - Margin updates:
IMRUpdateEvent,MMRUpdateEvent - Fee changes:
MakerFeeUpdateEvent,TakerFeeUpdateEvent - Trading status:
TradingPermissionStatusUpdate - Delisting:
DelistEvent
These events make it easy for indexers and frontends to stay in sync.
8. Delisting Logic
delist_perpetual_v2(admin, &mut perp, price)
- Locks the market from trading
- Sets a fixed price for closing open positions
9. Versioning & Migration
- Supports migrating from
PerpetualtoPerpetualV2usingmigrate_perpetual(...) - Version checks ensure object consistency before updates
Hey, great question! Building perpetuals on Sui is really interesting given its object model. For margin and positions, you'd typically represent each user's account and their open positions as individual Sui objects. This makes managing margin requirements and collateral quite efficient, as updates are direct. Funding rates are usually calculated off-chain based on the long-short imbalance in the system and then applied on-chain through a keeper or a scheduled transaction, effectively transferring value between the over-leveraged and under-leveraged sides. Liquidations work similarly: external keepers monitor positions and, if margin drops below a threshold, they call a public liquidate function on the protocol object to close the position. Regarding the core mechanism, most high-performance perpetuals like Bluefin often lean towards an off-chain order book with on-chain settlement. This allows for extremely fast trade execution and a traditional CEX-like experience while leveraging Sui for secure, transparent settlement of funds, margin updates, and position management. A purely on-chain order book can be tricky due to transaction ordering and throughput, though Sui's parallel execution helps. If you go the virtual AMM (vAMM) route, you'd have a main pool object that holds 'virtual' assets, much like a spot AMM. Trades update these virtual reserves and determine the price. The 'other side' of the trade is essentially the protocol's own liquidity. Maintaining balance between long and short positions and managing price volatility is absolutely crucial here. This is primarily done through dynamic funding rates – if there are too many longs, longs pay shorts, incentivizing people to open short positions and balance the book. Oracles also play a vital role, providing external price feeds to 'anchor' the vAMM's price to the real world, preventing divergence and making sure the funding rates reflect real market conditions. It’s all about creating incentives for traders to naturally rebalance the pool.
Designing a Perpetual DEX on Sui, like what Bluefin is doing, requires adapting key components from traditional perpetual protocols (like dYdX or GMX) to Sui’s object-centric Move model, with a focus on performance, safety, and composability. Below is a structured breakdown on how to approach it.
- Architecture Overview
You need five core modules:
Position Manager – tracks open long/short positions as objects
Margin Account – holds collateral, calculates leverage
vAMM or Orderbook Engine – matches trades and determines price
Funding Rate Oracle – updates long/short imbalance
Liquidator Bot/Module – closes undercollateralized positions
Sui’s object model allows every position and account to be a versioned, mutable, and type-safe object. This model is ideal for encapsulating individual trades and tracking margin health with precision.
- Margin + Collateral Design
Each trader has a MarginAccount object:
struct MarginAccount has key {
id: UID,
owner: address,
balance: Coin
Ensure balance reflects locked collateral, and positions are updated atomically during trades.
- Position Object
Positions are unique per market and direction (long/short):
struct Position has key { id: UID, market: MarketId, size: u64, // notional size entry_price: u64, direction: bool, // long=true, short=false last_funding_checkpoint: u64, }
Position updates happen via move calls tied to market events (fills, funding adjustments).
- vAMM Model (Uniswap-style)
A virtual AMM maintains an internal price curve:
Use x*y = k or a more sophisticated curve.
No actual asset swaps—just virtual balances.
When users open/close positions, the vAMM shifts the price curve.
Track base_reserve and quote_reserve inside a Market object:
struct Market has key { id: UID, base_reserve: u64, quote_reserve: u64, funding_index: u64, }
When a trader goes long, they're "buying" virtual base. Update reserves accordingly.
- Funding Rate Mechanism
Funding rate incentivizes market balance:
Calculate funding_rate = premium_index * time_elapsed
Update trader’s Position.last_funding_checkpoint on interaction
Pay/receive SUI or USDC from margin account depending on side
Can be computed off-chain and fed in via oracles or keeper bots.
- Liquidations
Liquidators monitor margin accounts:
Use oracle price (e.g. Pyth) to compute margin ratio
If below threshold (e.g. 6.25%), call liquidate_position
Reward liquidator from remaining margin
public fun liquidate( position: &mut Position, account: &mut MarginAccount, oracle_price: u64, ) { // compare margin ratio, forcibly close trade, return remainder }
- Orderbook Alternative (CLOB)
If using a central limit order book (like Bluefin):
Orders = objects with type Order { size, price, side, user }
Match engine runs off-chain, signs fill bundles
Submit signed fill bundles on-chain via verify_and_settle
- Using Oracles
Integrate Pyth for pricing:
Deploy pyth::PriceFeed on-chain
Use it to determine mark price for liquidations and funding
Remember to handle stale price guards
- Sui Advantages
Fine-grained ownership of positions and accounts
Parallelism via object independence
Gas metering optimized via composable Move code
Safe upgrades via upgrade_policy and capability control
-
Core Architecture: Choose between a virtual AMM (vAMM) or order book. vAMMs are easier to manage on-chain but less efficient in volatile markets. Order books offer precision but require off-chain components or more complex smart contracts.
-
vAMM Model: Use a constant product formula (x * y = k) where price is a function of virtual reserves. Trades adjust the virtual price, not real assets, and PnL is settled through margin accounts.
-
Margin Management: Implement a MarginAccount object storing collateral, open positions, and entry prices. Each trader interacts with their own margin object for performance and parallelism.
-
Funding Rates: Use periodic oracles to compute funding rates based on index vs. vAMM prices. Store these as shared objects and apply them at epoch intervals to balance long/short open interest.
-
Liquidation Engine: Define health factors (e.g., margin ratio < 10%) that trigger liquidation. Use shared objects (like a LiquidationQueue) to allow anyone to liquidate unhealthy accounts and earn a fee.
-
Price Oracles: Integrate Sui-compatible price feeds like Pyth. Use shared object state to store trusted prices with timestamp validation to prevent stale data usage.
-
Position Structs:
struct Position has key { owner: address, size: u64, is_long: bool, entry_price: u64, collateral: u64, last_funding_index: u64, }
- Execution Example:
public entry fun open_position(ctx: &mut TxContext, margin: &mut MarginAccount, is_long: bool, size: u64) { // validate margin // calculate entry price from vAMM // update position state }
- Funding Mechanism:
public fun apply_funding(position: &mut Position, current_funding_index: u64) { let funding_delta = current_funding_index - position.last_funding_index; position.entry_price += funding_delta; // for longs, subtract for shorts }
Do you know the answer?
Please log in and share it.
Sui is a Layer 1 protocol blockchain designed as the first internet-scale programmable blockchain platform.
- How to Maximize Profit Holding SUI: Sui Staking vs Liquid Staking616
- Why does BCS require exact field order for deserialization when Move structs have named fields?65
- Multiple Source Verification Errors" in Sui Move Module Publications - Automated Error Resolution55
- Sui Move Error - Unable to process transaction No valid gas coins found for the transaction419
- Sui Transaction Failing: Objects Reserved for Another Transaction410