Sui.

Post

Share your knowledge.

obito.
Jul 13, 2025
Expert Q&A

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
2
6
Share
Comments
.

Answers

6
Morgan.
Jul 19 2025, 11:00

One 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() and set_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 funding field (a FundingRate struct).

  • 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 priceOracle field.

  • 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

  • makerFee and takerFee (default for everyone)
  • specialFee table for VIP users or promotions
  • get_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 to insurancePool
  • 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 Perpetual to PerpetualV2 using migrate_perpetual(...)
  • Version checks ensure object consistency before updates
4
Best Answer
Comments
.
Ashford.
Sep 6 2025, 08:19

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.

4
Comments
.
BigSneh.
Jul 29 2025, 22:54

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.

  1. 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.

  1. Margin + Collateral Design

Each trader has a MarginAccount object:

struct MarginAccount has key { id: UID, owner: address, balance: Coin, positions: vector, }

Ensure balance reflects locked collateral, and positions are updated atomically during trades.

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

  1. 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.

  1. 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.

  1. 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 }

  1. 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

  1. 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

  1. 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

3
Comments
.
SuiLover.
Jul 29 2025, 15:42
  1. 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.

  2. 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.

  3. 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.

  4. 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.

  5. 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.

  6. 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.

  7. Position Structs:

struct Position has key { owner: address, size: u64, is_long: bool, entry_price: u64, collateral: u64, last_funding_index: u64, }

  1. 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 }

  1. 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 }

0
Comments
.

Do you know the answer?

Please log in and share it.