Reading Protocol State
The VifReader contract provides gas-efficient methods for reading the Vif protocol state off-chain. Use it to query order book data, market information, and user positions.
Overview
VifReader is designed for off-chain reads via Etherscan, block explorers, or RPC calls. Most methods are gas-unbounded and should not be used in transactions.
Use VifReader to:- Query order book depth and liquidity
- Read specific offers and their owners
- Get market configurations
- List all active markets
- Check authorizations and fees
Setup
Before reading market data, you must register the market pair:
updateMarkets
updateMarkets(
address token0,
address token1,
uint64 units0,
uint64 units1,
uint16 tickSpacing
)Registers both directions of a market pair (e.g., WETH/USDC and USDC/WETH). The tokens are automatically ordered, so you can pass them in any order.
Behavior:- Adds the market pair if either direction is active
- Removes the pair if both directions become inactive
- Must be called before using book reading functions
Reading the Order Book
packedOfferList
packedOfferList(
bytes32 marketId,
uint40 fromId,
uint256 maxOffers
) → (
uint40 nextOfferId,
uint40[] offerIds,
uint256[] offers,
address[] owners
)Returns a paginated list of offers from the order book.
Parameters:marketId: Market identifierfromId: Offer ID to start from (0 for beginning)maxOffers: Maximum number of offers to return
nextOfferId: Next offer ID for pagination (0 if end reached)offerIds: Array of offer IDsoffers: Array of packed offer data (use LibOffer.unpack to decode)owners: Array of offer owner addresses
- Building order book displays
- Paginating through all offers
- Finding user's active offers
packedBook
packedBook(
bytes32 marketId,
uint24 fromPricePoint,
uint24 maxPricePoints
) → (
uint24 nextPricePoint,
uint256[] offerListsPacked
)Returns aggregated offer list data at each price level.
Parameters:marketId: Market identifierfromPricePoint: Index to start from (0 for best price)maxPricePoints: Maximum price levels to return
nextPricePoint: Next price index for paginationofferListsPacked: Array of packed offer list data (contains head, tail, total volume, offer count, tick)
- Getting market depth overview
- Displaying price levels with aggregated volume
- Analyzing liquidity distribution
offerListEndPoints
offerListEndPoints(
bytes32 marketId,
uint40 fromId,
uint256 maxOffers
) → (
uint40 startId,
uint256 length
)Calculates pagination endpoints for offer lists.
Parameters:marketId: Market identifierfromId: Starting offer IDmaxOffers: Maximum offers to count
startId: Actual starting offer IDlength: Number of offers available (capped at maxOffers)
- Determining pagination boundaries
- Calculating total offer counts
Reading Individual Offers
offer
offer(
bytes32 marketId,
uint40 offerId
) → (
OfferUnpacked memory offer,
address owner
)Returns unpacked offer details with owner address.
Returns an OfferUnpacked struct containing:gives: Amount offered (in units)received: Amount received from fills (in units)next: Next offer ID in listprev: Previous offer ID in listexpiry: Expiration timestamp (0 = never)provision: Provision amount (in provision units)maker: Offer owner addressisActive: Whether offer is in the booktick: Price level
- Checking specific offer details
- Monitoring offer status
- Calculating claimable amounts
offerPacked
offerPacked(
bytes32 marketId,
uint40 offerId
) → (
uint256 offer,
address owner
)Returns packed offer data as a single uint256 (more gas efficient).
Use for:- Gas-efficient offer queries
- Batch reading offers
- Off-chain processing (unpack the uint256 using LibOffer.unpack)
Reading Markets
market
market(
bytes32 marketId
) → Market memoryReturns complete market configuration.
Returns a Market struct containing:outboundToken: Token makers are sellinginboundToken: Token makers are buyingoutboundUnits: Unit size for outbound amountsinboundUnits: Unit size for inbound amountstickSpacing: Minimum tick distancefee: Protocol fee in basis pointsactive: Whether market is activeminOutboundUnits: Minimum offer size
- Getting market parameters
- Calculating unit conversions
- Checking market status
openMarkets
openMarkets() → OpenMarketsResult[]Returns all registered active market pairs.
Returns array of OpenMarketsResult containing:market01: First direction market datamarket10: Second direction market data
- Discovering all available markets
- Building market selection UIs
- Market analytics
openMarkets (paginated)
openMarkets(
uint256 from,
uint256 maxLength
) → OpenMarketsResult[]Returns a page of active markets.
Parameters:from: Index to start frommaxLength: Maximum markets to return
- On-chain market queries
- Paginated market loading
openMarketsLength
openMarketsLength() → uint256Returns the total number of registered market pairs.
Use for:- Calculating pagination
- Counting active markets
Authorization & Fees
isAuthorized
isAuthorized(
address authorizer,
address authorized
) → boolChecks if an address is authorized to act on behalf of another.
Parameters:authorizer: The user granting permissionauthorized: The address that may have permission (typically a router)
trueif authorized address can act for authorizerfalseotherwise
- Verifying router permissions
- Checking operator status
- Authorization debugging
authorizerNonce
authorizerNonce(
address authorizer
) → uint256Returns the current nonce for EIP-712 signature-based authorization.
Use for:- Building authorization signatures
- Nonce management
- Replay attack prevention
fees
fees(
address token
) → uint256Returns accumulated protocol fees for a token.
Use for:- Checking fee reserves
- Protocol analytics
- Fee monitoring
minProvision
minProvision() → uint24Returns the global minimum provision requirement (in provision units).
Use for:- Calculating provision amounts for expiring offers
- Validating offer parameters
- Cost estimation
Protocol Status
isPaused
isPaused() → boolReturns whether the Vif contract is currently paused.
Use for:- Checking if trading is available
- UI state management
- Error handling
isBlacklisted
isBlacklisted(
address user
) → boolReturns whether a user is blacklisted from using the protocol.
Parameters:user: Address to check
- Access control validation
- User status verification
- Security checks
Reading from the Vif Contract Directly
The VifReader contract wraps many Vif contract functions for convenience, but you can also read directly from the Vif contract:
Tree Reading
treeFor(bytes32 marketId) - Returns the tick tree structure for a market
Use to:
- Find best prices
- Traverse price levels
- Check active ticks
Offer List Reading
offerList(bytes32 marketId, uint24 index) - Returns offer list at a specific price index
offerListPacked(bytes32 marketId, uint24 index) - Returns packed offer list data
Use to:
- Get offers at specific price
- Check liquidity at price level
- Read head/tail pointers
Delta Reading
deltaOf(address token) (via LibDeltasExt) - Returns current flash accounting delta for a token
Use to:
- Monitor transient balances
- Debug settlement issues
- Track debt/credit state
Best Practices
For Off-Chain Applications
- Use VifReader for all queries - It provides convenient aggregation and pagination
- Register markets first - Always call
updateMarketsbefore reading book data - Paginate large queries - Use
fromIdandmaxOffersparameters to avoid timeouts - Cache results - Order book data can be cached and invalidated on events
- Listen to events - Subscribe to Vif events to know when to refresh data
For On-Chain Applications
- Avoid unbounded methods - Never call
openMarkets()or largepackedOfferListqueries in transactions - Use specific queries - Read individual offers or markets rather than lists
- Consider gas costs - Even "view" functions cost gas in transactions
- Validate data - Always check
isActivestatus on offers and markets
For UI Development
- Progressive loading - Load best prices first, then paginate deeper levels
- Event-driven updates - Refresh only affected price levels when offers change
- Error handling - Handle cases where markets aren't registered or offers don't exist
- Format units - Remember to multiply packed units by market unit sizes
Common Use Cases
Building an Order Book Display
- Call
updateMarketsto register the market pair - Use
packedBookto get aggregated depth at each price level - Use
packedOfferListto get individual offers if needed - Listen to
NewOffer,MarketOrder,OfferCancelledevents - Refresh affected price levels on events
Showing User Portfolio
- Get all markets with
openMarkets() - For each market, call
packedOfferListwith reasonable pagination - Filter offers by user address from the
ownersarray - Display offer details using returned packed data
- Monitor
OfferClaimedandOfferUpdatedevents for the user
Market Analytics
- Use
openMarkets()to discover all markets - For each market, read
market()to get configuration - Use
packedBookto calculate total liquidity - Check
fees()for each token to see protocol revenue - Track
MarketOrderevents to measure trading volume
Price Monitoring
- Register target markets with
updateMarkets - Read best price using Vif's
treeForand finding first cursor - Subscribe to
NewOfferandMarketOrderevents - Re-read best price when events indicate price may have changed
- Use
packedBookto get spread between best bid and ask
Related Concepts
- Using VifRouter - Executing trades and orders
- Markets & Units - Understanding market structure
- Offers & Lists - Offer data structures
- Tick Tree Structure - Price level organization