Core Concepts
This page explains the fundamental concepts you need to understand when working with Sera.
Price Indices
Sera uses an Arithmetic Price Book where prices are represented as indices rather than raw values. This provides:
- Gas-efficient storage (uint16 vs uint256)
- Predictable price levels
- Easy price level iteration
price = minPrice + (tickSpace × priceIndex)
| Parameter | Description |
|---|
minPrice | The minimum price supported by the market |
tickSpace | The spacing between each price level |
priceIndex | An integer from 0 to 65,535 (uint16) |
Example
For a market with minPrice = 0.001 and tickSpace = 0.00001:
| Price Index | Actual Price |
|---|
| 0 | 0.001000 |
| 100 | 0.002000 |
| 500 | 0.006000 |
| 1000 | 0.011000 |
Converting Between Price and Index
Price → Index:
// Get the index for a target price
const { index, correctedPrice } = await priceBook.priceToIndex(
targetPrice,
false // roundingUp: false for bids, true for asks
);
Index → Price:
const price = await priceBook.indexToPrice(priceIndex);
Raw Amounts vs Token Amounts
Sera uses “raw amounts” internally for gas efficiency. Understanding the conversion is crucial.
Quote Unit
Each market has a quoteUnit that defines how many quote tokens equal one “raw unit”:
rawAmount = quoteAmount / quoteUnit
quoteAmount = rawAmount × quoteUnit
Conversions
| Conversion | Formula |
|---|
| Raw → Quote | quoteAmount = rawAmount × quoteUnit |
| Quote → Raw | rawAmount = quoteAmount / quoteUnit |
| Raw → Base | baseAmount = rawAmount × quoteUnit / price |
| Base → Raw | rawAmount = baseAmount × price / quoteUnit |
Example
For a market with quoteUnit = 1000000 (6 decimals):
// You want to buy 100 USDC worth
const quoteAmount = 100_000000n; // 100 USDC (6 decimals)
const rawAmount = quoteAmount / 1000000n; // = 100 raw units
Order Types
Limit Orders
Limit orders sit on the order book until filled or cancelled.
| Parameter | Bid (Buy) | Ask (Sell) |
|---|
priceIndex | Maximum price willing to pay | Minimum price willing to receive |
rawAmount | Quote tokens to spend | Not used (set to 0) |
baseAmount | Not used (set to 0) | Base tokens to sell |
postOnly | If true, order fails if it would fill immediately | Same |
Market Orders
Market orders execute immediately against existing orders.
| Parameter | Bid (Buy) | Ask (Sell) |
|---|
limitPriceIndex | Maximum price willing to pay | Minimum price willing to receive |
rawAmount | Max quote to spend (expendInput) / Min quote to receive (!expendInput) | Min quote to receive (expendInput) / Max quote to spend (!expendInput) |
baseAmount | Min base to receive (expendInput) / Max base to spend (!expendInput) | Max base to spend (expendInput) / Min base to receive (!expendInput) |
expendInput | If true, spend all input tokens | Same |
Order Lifecycle
┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
│ Create │────▶│ Open │────▶│ Filled │────▶│ Claimed │
└──────────┘ └──────────┘ └──────────┘ └──────────┘
│ ▲
│ ┌──────────┐ │
└──────────▶│ Cancelled │ │
└──────────┘ │
│ │
└───────────────┘
| Status | Description |
|---|
open | Order is on the book, waiting to be filled |
filled | Order has been completely filled, proceeds ready to claim |
partial | Order is partially filled |
cancelled | Order was cancelled by the owner |
claimed | Proceeds have been claimed |
Fees
Sera uses a maker-taker fee model:
| Fee Type | Description | Typical Value |
|---|
| Taker Fee | Paid by the party that takes liquidity | 0.1% (10 bps) |
| Maker Fee | Paid/received by the party that provides liquidity | -0.05% (rebate) |
Negative maker fees mean makers receive a rebate for providing liquidity. For testnet, all fees are set to 0.
Fee values are stored as basis points × 100:
1000 = 0.1% = 10 bps
-500 = -0.05% = 5 bps rebate
Order NFTs
Each limit order creates an NFT representing ownership. This enables:
- Transferability: Transfer order ownership to another address
- Composability: Use orders in other DeFi protocols
- Claim Delegation: Anyone holding the NFT can claim proceeds
// Get the NFT ID from an order
const nftId = order.nftId;
// Transfer order ownership
await orderNFT.transferFrom(owner, newOwner, nftId);
Next Steps