📜Contracts
Deployed on HyperEVM
Key Links
$BTC Market Proxy Contract (HyperEVM): 0xB7C609cFfa0e47DB2467ea03fF3e598bF59361A5 $PUMP Market Proxy Contract (HyperEVM): 0xc97Bd36166f345aB1C5d97c9DF196Ee6fFA2485e Contract Repository: https://github.com/Convexity-Research/options-contracts.git SDK Repository: https://github.com/Convexity-Research/optfun-sdk
Architecture & Implementation Choices
1. Upgradeable Proxy Pattern
The contract uses OpenZeppelin's UUPS (Universal Upgradeable Proxy Standard) pattern, allowing for future improvements while maintaining state continuity.
2. ERC2771 Meta-Transactions
Implements gasless trading through trusted forwarders, enabling users to trade without holding native tokens for gas.
3. Cycle-Based Trading
Each cycle is identified by its expiry timestamp (Unix timestamp)
Strike price is set to the oracle price at cycle initiation
Trading is only allowed during active cycles (before expiry)
4. Three-Level Bitmap Orderbook
The orderbook uses an efficient three-level bitmap structure for O(1) best price discovery:
L1 (Summary): 256-bit summary of which 65k-tick blocks have liquidity
L2 (Mid): 256-bit bitmap for each L1 block, showing which 256-tick sub-blocks have orders
L3 (Detail): 256-bit bitmap for each L2 block, showing exact ticks with liquidity
5. Position Tracking
User positions are tracked efficiently in a packed struct:
struct UserAccount {
bool activeInCycle;
bool liquidationQueued;
uint64 balance; // Collateral balance
uint64 liquidationFeeOwed;
uint64 scratchPnL; // Temporary PnL storage during settlement
uint48 _gap; // Reserved for future use
uint32 longCalls; // Actual positions
uint32 shortCalls;
uint32 longPuts;
uint32 shortPuts;
uint32 pendingLongCalls; // Pending limit orders
uint32 pendingShortCalls;
uint32 pendingLongPuts;
uint32 pendingShortPuts;
}
6. Two-Phase Settlement
To ensure fair social loss distribution:
Phase 1: Calculate PnL, debit losers immediately, store winners' PnL
Phase 2: Credit winners pro-rata based on available funds after accounting for bad debt
7. Taker Queue System
Unfilled market orders are queued in buckets corresponding to each market side, allowing them to be filled by incoming limit orders.
8. Oracle Integration
Uses a precompiled contract at address 0x0000000000000000000000000000000000000806
for price feeds, ensuring reliable and gas-efficient price updates.
Constants & Configuration
uint256 constant TICK_SZ = 1e4; // 0.01 USDT tick size
uint256 constant MAX_OPEN_LIMIT_ORDERS = 256; // Max orders per user
uint256 constant MM_BPS = 10; // 0.10% Maintenance Margin
uint256 constant CONTRACT_SIZE = 100; // Position size divisor
int256 constant makerFeeBps = -200; // -2.00% (rebate to makers)
int256 constant takerFeeBps = 700; // +7.00% (fee from takers)
uint256 constant liquidationFeeBps = 10; // 0.1% liquidation fee
uint256 constant DEFAULT_EXPIRY = 1 minutes; // Cycle duration
Public/External Functions
Collateral Management
depositCollateral(uint256 amount, bytes memory signature)
Deposits USDT collateral with whitelist signature verification.
Parameters:
amount
: Amount of USDT to deposit (6 decimals)signature
: Signature from whitelist signer to authorize the address
Effects: Adds user to whitelist and credits their balance
Events:
CollateralDeposited
depositCollateral(uint256 amount)
Deposits USDT collateral for already whitelisted users.
Parameters:
amount
: Amount of USDT to depositRequirements: User must be whitelisted
Events:
CollateralDeposited
withdrawCollateral(uint256 amount)
Withdraws USDT collateral from the platform.
Parameters:
amount
: Amount to withdrawRequirements:
User must have no open positions or orders
Sufficient balance available
Events:
CollateralWithdrawn
Trading Functions
long(uint256 size, uint256 cycleId)
Places a "long" position (buy call + sell put) for directional upward exposure.
Parameters:
size
: Number of contracts (scaled by CONTRACT_SIZE)cycleId
: Target cycle (0 for current active cycle)
Effects: Places market orders for CALL_BUY and PUT_SELL
Use Case: Betting that price will go up
short(uint256 size, uint256 cycleId)
Places a "short" position (buy put + sell call) for directional downward exposure.
Parameters:
size
: Number of contractscycleId
: Target cycle (0 for current active cycle)
Effects: Places market orders for PUT_BUY and CALL_SELL
Use Case: Betting that price will go down
placeOrder(MarketSide side, uint256 size, uint256 limitPrice, uint256 cycleId)
Places individual orders with full control over side and price.
Parameters:
side
: Market side (CALL_BUY, CALL_SELL, PUT_BUY, PUT_SELL)size
: Order sizelimitPrice
: Limit price (0 for market order)cycleId
: Target cycle
Returns: Order ID
Effects:
Market orders: Immediately matched against orderbook, remainder queued
Limit orders: Added to orderbook if not crossing
cancelOrder(uint256 orderId)
Cancels an existing limit order.
Parameters:
orderId
: ID of order to cancelRequirements:
Market must be live
Caller must own the order
User cannot be liquidatable
Effects: Removes order from orderbook and updates position tracking
Events:
LimitOrderCancelled
Risk Management
liquidate(address trader)
Liquidates an undercollateralized trader.
Parameters:
trader
: Address to liquidateRequirements:
Market must be live
Trader must be liquidatable (balance < required margin)
Effects:
Cancels all maker orders
Clears taker queue entries
Places market orders to close net short positions
Queues liquidation fee collection
Events:
Liquidated
isLiquidatable(address trader)
/ isLiquidatable(address trader, uint64 price)
Checks if a trader can be liquidated.
Parameters:
trader
: Address to checkprice
: Oracle price (optional, fetches current if not provided)
Returns: Boolean indicating liquidation eligibility
Formula:
balance < requiredMargin(netShortExposure * maintenanceMargin + currentLoss)
Cycle Management
startCycle()
Initiates a new 1-minute trading cycle.
Requirements:
No active cycle, or active cycle is expired and settled
Valid oracle price available
Effects:
Creates new cycle with current timestamp + 1 minute as expiry
Sets strike price to current oracle price
Resets settlement state
Events:
CycleStarted
settleChunk(uint256 max)
Processes settlement for a batch of traders.
Parameters:
max
: Maximum number of traders to processTwo-Phase Process:
Phase 1: Calculate PnL, debit losers, accumulate winners' PnL
Phase 2: Credit winners proportionally after social loss calculation
Effects: Updates trader balances and positions
Events:
PriceFixed
,Settled
,CycleSettled
Settlement Mechanics
PnL Calculation
For each trader, PnL is calculated based on the intrinsic value of their positions:
Call Options: max(settlementPrice - strikePrice, 0) * longCalls - max(settlementPrice - strikePrice, 0) * shortCalls
Put Options: max(strikePrice - settlementPrice, 0) * longPuts - max(strikePrice - settlementPrice, 0) * shortPuts
Social Loss Distribution
When total losses exceed available collateral:
Phase 1: Debit all losers immediately, accumulate total positive PnL
Phase 2: Calculate loss ratio =
badDebt / totalPositivePnL
Credit winners:
winnerPnL * (1 - lossRatio)
Fee Structure
Maker Fee: -2.00% (rebate - makers get paid)
Taker Fee: +7.00% (fee - takers pay)
Liquidation Fee: 0.1% of notional value being liquidated
Risk Parameters
Margin Requirements
Maintenance Margin: 0.10% of strike notional value
Buffer: Current loss + maintenance margin on net short exposure
Liquidation Trigger: Balance < required margin
Position Limits
Max Open Orders: 256 limit orders per user
No Position Limits: Users can take unlimited size positions if they have sufficient collateral
Events
The contract emits comprehensive events for all major operations:
CycleStarted
,CycleSettled
CollateralDeposited
,CollateralWithdrawn
LimitOrderPlaced
,LimitOrderFilled
,LimitOrderCancelled
TakerOrderPlaced
,TakerOrderRemaining
Liquidated
,Settled
,PriceFixed
Security Features
Pausable: Emergency pause functionality
Upgradeable: UUPS proxy pattern for controlled upgrades
Access Control: Owner-only functions for critical operations
Reentrancy Protection: SafeERC20 for token transfers
Overflow Protection: Solidity 0.8+ automatic overflow checks
Liquidation Protection: Automatic liquidation prevents system insolvency
Risk Parameters
Margin Requirements
Maintenance Margin: 0.10% of strike notional value
Buffer: Current loss + maintenance margin on net short exposure
Liquidation Trigger: Balance < required margin
Position Limits
Max Open Orders: 256 limit orders per user
No Position Limits: Users can take unlimited size positions if they have sufficient collateral
Events
The contract emits comprehensive events for all major operations:
CycleStarted
,CycleSettled
CollateralDeposited
,CollateralWithdrawn
LimitOrderPlaced
,LimitOrderFilled
,LimitOrderCancelled
TakerOrderPlaced
,TakerOrderRemaining
Liquidated
,Settled
,PriceFixed
Security Features
Pausable: Emergency pause functionality
Upgradeable: UUPS proxy pattern for controlled upgrades
Access Control: Owner-only functions for critical operations
Reentrancy Protection: SafeERC20 for token transfers
Overflow Protection: Solidity 0.8+ automatic overflow checks
Liquidation Protection: Automatic liquidation prevents system insolvency
Last updated