Skip to Content
HyperQuote is live on HyperEVM — Start trading →

Options RFQ Flow

The Options RFQ flow follows the same request-for-quote pattern as HyperQuote spot swaps, extended with options-specific parameters (strike, expiry, option type) and EIP-712 typed data signing for maker quotes. This page walks through the full lifecycle from RFQ submission to on-chain execution.

Flow Overview

1. Taker submits RFQ (EIP-191 signed, via WebSocket relay) 2. Relay broadcasts (to connected makers) 3. Makers respond (EIP-712 signed quotes, via relay) 4. Taker selects quote (UI comparison, best premium) 5. Taker calls execute() (on-chain, OptionsEngine) 6. Contract verifies (signature, nonce, expiry, allowlists) 7. Position created (NFT minted, premium transferred, collateral locked)

Step 1: Taker Submits an RFQ

The taker (option seller in V1) constructs an RFQ containing:

FieldDescription
requesterTaker’s wallet address
underlyingUnderlying token address (wHYPE)
collateralCollateral token address (USDC, USDH, or USDT0)
isCalltrue for covered call, false for cash-secured put
strikeStrike price in 1e18 fixed-point
quantityAmount of underlying in underlying decimals
expiryUnix timestamp at 08:00 UTC
minPremiumMinimum acceptable premium (optional)
timestampRFQ creation time

A deterministic rfqId is computed by hashing all fields. The taker signs this hash using EIP-191 personal_sign (signMessage with the raw 32-byte hash), which proves they authored the request.

The signed RFQ is sent to the relay via a WebSocket RFQ_SUBMIT message.

Step 2: Relay Broadcasts to Makers

The relay server receives the RFQ, verifies the EIP-191 signature matches the requester address, and broadcasts the RFQ to all connected makers. Makers receive the full RFQ parameters and can decide whether to respond.

Step 3: Makers Respond with EIP-712 Quotes

A maker who wants to fill the RFQ constructs a Quote struct and signs it using EIP-712 typed structured data:

struct Quote { address maker; // maker's address (quote signer) address taker; // address(0) for open, or specific taker address underlying; // must match RFQ address collateral; // must match RFQ bool isCall; // must match RFQ bool isMakerSeller; // V1: always false (taker is seller) uint256 strike; // must match RFQ uint256 quantity; // must match RFQ uint256 premium; // maker's offered premium (collateral units) uint256 expiry; // must match RFQ uint256 deadline; // quote validity deadline (unix seconds) uint256 nonce; // maker's current nonce (replay protection) }

The EIP-712 domain is:

name: "HyperQuote Options" version: "1" chainId: <chain ID> verifyingContract: <OptionsEngine address>

The maker signs the typed data hash and sends the quote plus signature back through the relay as a QUOTE_BROADCAST message.

The taker’s UI verifies each incoming EIP-712 signature client-side before displaying the quote. Invalid signatures are silently discarded.

Step 4: Taker Selects a Quote

The UI displays all valid quotes sorted by premium (highest first, since the taker is the seller and wants the most premium). Each quote card shows:

  • Maker address (truncated)
  • Premium offered (in collateral token)
  • Collateral required from the taker
  • Quote expiry countdown

The taker selects their preferred quote and proceeds to execution.

Step 5: On-Chain Execution

The taker calls OptionsEngine.execute(quote, signature) where quote is the full Quote struct and signature is the maker’s EIP-712 signature.

Before executing, the taker must have approved the OptionsEngine to transfer:

  • Covered Call: quantity of the underlying token (wHYPE)
  • Cash-Secured Put: putCollateralRequired(strike, quantity, uDec, cDec) of the collateral token

The maker must have approved the OptionsEngine to transfer the premium amount in the collateral token.

Step 6: Contract Verification

The execute function runs a comprehensive validation sequence:

  1. Parameter validation — Quantity, premium, and strike must be non-zero.
  2. Role checkisMakerSeller must be false (V1 constraint).
  3. Token allowlists — Both underlying and collateral must be in the allowed sets.
  4. Expiry validation — Must be at 08:00 UTC, between 24 hours and 90 days from now.
  5. Quote deadlineblock.timestamp must not exceed quote.deadline.
  6. Nonce checkquote.nonce must be greater than or equal to the maker’s current nonce.
  7. Taker check — If quote.taker is not address(0), it must match msg.sender.
  8. Duplicate check — The quote digest must not have been used before.
  9. Signature recovery — ECDSA recovery of the EIP-712 digest must return quote.maker.

If any check fails, the transaction reverts with a specific error (e.g., InvalidSignature(), QuoteExpired(), NonceTooLow()).

Step 7: Position Creation

After validation, the contract:

  1. Marks the quote as used — Prevents replay by storing the digest.
  2. Creates the Position struct — Stores all deal terms on-chain.
  3. Mints an ERC-721 NFT — Minted to the buyer (maker), representing their option right.
  4. Transfers premium — Buyer (maker) pays premium to seller (taker) in the collateral token.
  5. Locks collateral — Seller (taker) locks collateral in the contract:
    • Covered Call: underlying tokens (wHYPE)
    • Cash-Secured Put: stablecoin (computed via CollateralMath.putCollateralRequired)

A QuoteExecuted event is emitted with the quote hash, position ID, maker, and taker addresses.

Quote Cancellation and Nonces

Makers have two mechanisms to invalidate outstanding quotes:

Cancel a Specific Quote

Call cancelQuote(quote) to mark a specific quote digest as used, preventing it from being executed.

Increment Nonce

Call incrementNonce() to advance the maker’s nonce. All quotes signed with a nonce below the new value become invalid. This is useful for bulk-cancelling all outstanding quotes.

Once a quote is executed on-chain, it cannot be reversed. The premium transfer and collateral lock happen atomically in the same transaction. Make sure your approvals and balances are correct before calling execute.

Last updated on