Diffusal
Protocol

RFQ Flow

How Request for Quote (RFQ) trading works in the Diffusal protocol

The RFQ (Request for Quote) system enables users to trade options directly with the Main Market Maker (MMM). Unlike the limit order book where users trade against each other, RFQ provides instant execution at prices quoted by professional market makers.


Overview

RFQ trading combines off-chain quoting with on-chain settlement:

PhaseLocationDescription
Quote RequestOff-chainUser requests a price from the MMM
Quote ResponseOff-chainMMM signs and sends a quote with EIP-712
ExecutionOn-chainUser submits the signed quote to the contract
SettlementOn-chainPositions are minted, premium is transferred

Key Benefits:

  • Instant execution — No waiting for order book matching
  • Professional pricing — MMMs provide competitive, market-aware quotes
  • Atomic settlement — Positions created in a single transaction
  • Flexible sizing — Partial fills supported

Participants

Main Market Maker (MMM)

The MMM is a privileged address that:

CapabilityDescription
Quote provisionProvides prices to users off-chain
Signature authoritySigns EIP-712 quotes
Position takingTakes the opposite side of user trades
Liquidation immunityCannot be liquidated by the protocol

The MMM is registered by the protocol owner and can be queried via the PositionManager.

User (Quote Taker)

The user:

  1. Requests quotes from MMM off-chain (via API, chat, etc.)
  2. Receives a signed quote with price, size, and expiry
  3. Submits the quote on-chain to execute the trade
  4. Pays or receives premium based on trade direction
  5. Receives a long or short position

Quote Structure

An RFQ quote contains all parameters needed for on-chain execution:

Quote Fields

FieldDescription
mmmMain Market Maker address (quote signer)
takerAuthorized taker address (or zero for anyone)
seriesIdOption series identifier
takerIsBuyingDirection flag: true = taker buys long
pricePremium per contract in WAD (1e18 = $1.00)
sizeMaximum contracts available
nonceReplay protection counter
quoteExpiryQuote validity deadline (unix timestamp)

Series Parameters

The quote also includes full series parameters for lazy registration:

FieldDescription
pairIdTrading pair (e.g., ETH-USD)
strikeStrike price in WAD
optionExpiryOption expiration timestamp
isCalltrue for call, false for put

Series ID Verification:

seriesId=keccak256(pairId,strike,optionExpiry,isCall)\text{seriesId} = \text{keccak256}(\text{pairId}, \text{strike}, \text{optionExpiry}, \text{isCall})

The contract verifies that the provided seriesId matches the hash of the series parameters. This prevents the MMM from accidentally signing for the wrong series.


Execution Flow

High-Level Flow

Off-Chain Phase:

  1. User requests a quote from the MMM (e.g., "I want to buy 10 ETH-USD calls, strike $3000, Dec 31")
  2. MMM calculates the price, creates a quote (e.g., $150 per contract, size = 10), and signs it with EIP-712
  3. MMM sends the signed quote to the user

On-Chain Phase: 4. User submits the quote to the RFQ contract 5. Contract validates: signature is from registered MMM, quote not expired, series not expired, nonce matches MMM's current nonce, fill amount ≤ remaining quote size, and taker is authorized (or quote allows anyone) 6. Contract executes: registers series if new (lazy creation), mints positions (long to buyer, short to seller), transfers premium from buyer to seller, and collects RFQ fee from taker 7. Emits event with fill details

Validation Steps

The contract performs these checks before executing any trade:

CheckRequirement
Quote expiryblock.timestamp < quoteExpiry
Option expiryblock.timestamp < optionExpiry
MMM registrationSigner must be a registered MMM
Signature validityEIP-712 signature must match quote hash
Taker authorizationCaller must be authorized (or quote is open)
Nonce validityQuote nonce must match MMM's current nonce
Fill capacityRequested amount must not exceed remaining
Series ID matchseriesId == hash(pairId, strike, optionExpiry, isCall)

Trade Direction

The takerIsBuying flag determines who gets which position and who pays:

Taker Buys Long (takerIsBuying = true)

The MMM mints a pair, gives the long position to the taker and keeps the short. The taker pays the premium to the MMM.

After trade:

  • Taker: holds long position, paid premium
  • MMM: holds short position, received premium

Taker Buys Short (takerIsBuying = false)

The MMM mints a pair, gives the short position to the taker and keeps the long. The MMM pays the premium to the taker (compensating them for taking on the obligation).

After trade:

  • Taker: holds short position, received premium
  • MMM: holds long position, paid premium

Trade Examples

Example 1: User Buys Calls

User wants to buy 10 ETH-USD 3000callsat3000 calls at 150 premium each. Before the trade, the user has no position and 2,000USDC;theMMMhasnopositionand2,000 USDC; the MMM has no position and 50,000 USDC.

After the trade (takerIsBuying = true, fillAmount = 10):

  • User receives +10 position (long), MMM receives -10 position (short)
  • Premium: 10 × 150=150 = 1,500 flows from User to MMM
  • After: User has 500USDC,MMMhas500 USDC, MMM has 51,500 USDC

Example 2: User Sells Puts

User wants to sell 5 ETH-USD 3000putsat3000 puts at 200 premium each (user takes short, receives premium). Before the trade, the user has no position and 5,000USDC;theMMMhasnopositionand5,000 USDC; the MMM has no position and 50,000 USDC.

After the trade (takerIsBuying = false, fillAmount = 5):

  • User receives -5 position (short), MMM receives +5 position (long)
  • Premium: 5 × 200=200 = 1,000 flows from MMM to User
  • After: User has 6,000USDC,MMMhas6,000 USDC, MMM has 49,000 USDC

Premium Calculation

The premium transferred is calculated from the quote price and fill amount:

premium=price×fillAmount1018\text{premium} = \frac{\text{price} \times \text{fillAmount}}{10^{18}}

Buyer always pays seller:

DirectionBuyerSellerPremium Flow
takerIsBuying = trueTakerMMMTaker → MMM
takerIsBuying = falseMMMTakerMMM → Taker

Fee Structure

RFQ trades have a dedicated fee rate separate from limit order fees.

Fee Calculation

rfqFee=premium×rfqFeeBps10000\text{rfqFee} = \frac{\text{premium} \times \text{rfqFeeBps}}{10000}

where rfqFeeBps is the RFQ fee rate in basis points (1 BPS = 0.01%).

Fee Flow

The premium flows from buyer to seller. Additionally, the RFQ fee is always paid by the taker to the feeRecipient, regardless of trade direction.


Nonce Management

Each MMM has an independent nonce counter for replay protection.

How Nonces Work

PropertyDescription
Per-MMM counterEach MMM has its own nonce
Quote validationQuote nonce must match current MMM nonce
Increment effectIncrementing nonce invalidates ALL pending quotes

Quote Cancellation

Individual quotes cannot be explicitly cancelled. To invalidate quotes:

MethodEffect
Wait for expiryQuote has a quoteExpiry timestamp
Increment nonceInvalidates ALL pending quotes from that MMM

Partial Fills

Quotes support partial fills—the taker can fill less than the full quote size.

Fill Tracking

StateDescription
quoteFilled[quoteHash]Amount already filled
Remainingquote.size - quoteFilled[quoteHash]

A quote can be filled multiple times by the same or different takers until fully filled.


Lazy Series Registration

RFQ supports lazy series registration—if the series doesn't exist, it's created automatically.

When filling an RFQ quote, the contract first checks if the series exists. If yes, it proceeds with the fill. If no, it validates the series parameters (verifying the hash matches seriesId, pairId is registered, optionExpiry is in the future, and strike > 0), then registers the series and proceeds with the fill.

This enables trading of new strikes/expiries without upfront admin setup.


Security Considerations

Signature Replay Protection

ProtectionMechanism
NonceQuote nonce must match MMM's current nonce
Fill trackingquoteFilled[quoteHash] prevents double-filling
ExpiryQuotes have limited validity via quoteExpiry

MMM Verification

  • Only registered MMMs can have their quotes executed
  • Signature must match the mmm address in the quote
  • MMM status is checked on every fill

Taker Restriction

Quote ConfigurationWho Can Fill
quote.taker = address(0)Anyone
quote.taker = specificAddressOnly that address

This allows MMMs to provide exclusive quotes to specific users.

Premium Direction

The takerIsBuying flag creates unambiguous payment direction:

  • Buyer always pays premium
  • Seller always receives premium
  • No ambiguity about who pays whom

Contract Integration

Storage

StoragePurpose
mmmNonce[mmm]Replay protection per MMM
quoteFilled[quoteHash]Partial fill tracking
rfqFeeBpsFee configuration

Dependencies

The DiffusalOptionsRFQ contract integrates with:

  • DiffusalOptionsPositionManager: For isMMM(address) to verify MMM registration, and updatePosition() to mint long/short positions
  • IERC20 (Collateral Token): For premium transfers between buyer and seller, and fee collection to feeRecipient

Summary

ComponentDescription
QuoteEIP-712 signed message from MMM with price, size, and series params
ExecutionOn-chain validation + position minting + premium transfer
DirectiontakerIsBuying=true: user gets long; false: user gets short
PremiumBuyer pays seller; calculated as price × fillAmount
FeeRFQ fee collected from taker, sent to feeRecipient
NoncePer-MMM counter; increment to invalidate all pending quotes
Partial fillsSupported via fill amount tracking per quote hash

The RFQ system provides:

  • Instant execution — No need to wait for order book matching
  • Professional pricing — MMMs provide competitive quotes
  • Atomic settlement — Positions created in a single transaction
  • Flexible sizing — Partial fills supported via fillAmount
  • Security — EIP-712 signatures, nonce protection, taker restrictions

Contract Implementation

ContractRole
DiffusalOptionsRFQCore RFQ logic, EIP-712 validation, and fee collection
DiffusalOptionsPositionManagerMMM registration and position minting
DiffusalOptionsSeriesRegistryLazy series registration and validation
DiffusalCollateralVaultCollateral for margin requirements

  • Order Book — Peer-to-peer limit order trading where anyone can be a maker
  • Options Creation — How series are lazily registered on first trade
  • Margin System — Collateral requirements for positions

On this page