> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/reserve-protocol/reserve-index-dtf/llms.txt
> Use this file to discover all available pages before exploring further.

# FolioLens Contract

> Read-only interface for analyzing Folio state, auctions, and balances off-chain

## Overview

The **FolioLens** contract provides convenient read-only functions for analyzing Folio state. It's designed for off-chain use by frontends, analytics tools, and indexers. These functions are gas-intensive and should not be called on-chain.

### Key Features

* **Spot Weight Calculation**: Compute current token weights from balances
* **Batch Bid Queries**: Get all auction bids at once
* **Surplus/Deficit Analysis**: Calculate which tokens need buying or selling
* **Off-Chain Optimized**: Not intended for on-chain calls

<Warning>
  FolioLens functions are designed for off-chain analysis only. Do not call these functions from other smart contracts as they may consume excessive gas.
</Warning>

## Analysis Functions

### Get Spot Weights

Calculate token weights based on current Folio balances.

<ParamField path="folio" type="Folio">
  Folio contract to analyze
</ParamField>

```solidity FolioLens.sol theme={null}
function getSpotWeights(
    Folio folio
) external view returns (
    address[] memory tokens,
    uint256[] memory weights
)
```

**Returns:**

* `tokens`: Array of token addresses in the basket
* `weights`: Token weights in D27 format (tokens per share)

<Info>
  Weights are calculated as: `(D27 * tokenBalance) / totalSupply`. This gives the actual composition by current holdings, which may differ from target weights during rebalancing.
</Info>

### Get All Bids

Retrieve all possible bids for an auction in a single call.

<ParamField path="folio" type="Folio">
  Folio contract with active auction
</ParamField>

<ParamField path="auctionId" type="uint256">
  ID of the auction to query
</ParamField>

```solidity FolioLens.sol theme={null}
function getAllBids(
    Folio folio,
    uint256 auctionId
) external view returns (SingleBid[] memory bids)
```

**Returns:**

* Array of `SingleBid` structs for all valid token pairs

<Info>
  This function attempts to call `getBid()` for all N² token pairs. Invalid pairs (those that would revert) are filtered out. Only returns bids with non-zero amounts.
</Info>

### Surpluses and Deficits

Calculate which tokens are over/under the target limits.

<ParamField path="folio" type="Folio">
  Folio contract to analyze
</ParamField>

<ParamField path="sellLimit" type="uint256">
  Upper BU limit for selling (D18 format)
</ParamField>

<ParamField path="buyLimit" type="uint256">
  Lower BU limit for buying (D18 format)
</ParamField>

```solidity FolioLens.sol theme={null}
function surplusesAndDeficits(
    Folio folio,
    uint256 sellLimit,
    uint256 buyLimit
) external view returns (
    address[] memory tokens,
    uint256[] memory surpluses,
    uint256[] memory deficits
)
```

**Returns:**

* `tokens`: Array of token addresses
* `surpluses`: Amount above sell limit for each token (0 if not surplus)
* `deficits`: Amount below buy limit for each token (0 if not deficit)

<Warning>
  Requires `sellLimit >= buyLimit`. A token cannot have both a surplus and deficit - if one is non-zero, the other is always zero.
</Warning>

## Data Structures

### SingleBid

Represents a single auction bid for a token pair.

<ParamField path="sellToken" type="address">
  Token being sold by the Folio
</ParamField>

<ParamField path="buyToken" type="address">
  Token being bought by the Folio
</ParamField>

<ParamField path="sellAmount" type="uint256">
  Amount of sell token available
</ParamField>

<ParamField path="bidAmount" type="uint256">
  Amount of buy token required
</ParamField>

<ParamField path="price" type="uint256">
  Price in D27 format (buyTok/sellTok)
</ParamField>

```solidity theme={null}
struct SingleBid {
    address sellToken;
    address buyToken;
    uint256 sellAmount;  // {sellTok}
    uint256 bidAmount;   // {buyTok}
    uint256 price;       // D27{buyTok/sellTok}
}
```

## Usage Examples

### Analyze Current Composition

```solidity theme={null}
// Get current token weights
(address[] memory tokens, uint256[] memory weights) = 
    lens.getSpotWeights(folio);

for (uint256 i = 0; i < tokens.length; i++) {
    // weights[i] is in D27 format
    // Divide by 1e27 to get tokens per share
    uint256 tokensPerShare = weights[i] / 1e27;
}
```

### Find Best Auction Bids

```solidity theme={null}
// Get all bids for current auction
FolioLens.SingleBid[] memory bids = lens.getAllBids(folio, auctionId);

for (uint256 i = 0; i < bids.length; i++) {
    FolioLens.SingleBid memory bid = bids[i];
    
    // Calculate price impact
    uint256 priceImpact = calculatePriceImpact(
        bid.sellToken,
        bid.buyToken,
        bid.price
    );
    
    // Execute profitable bids
    if (isProfitable(priceImpact)) {
        folio.bid(
            auctionId,
            IERC20(bid.sellToken),
            IERC20(bid.buyToken),
            bid.sellAmount,
            bid.bidAmount,
            false,
            ""
        );
    }
}
```

### Calculate Rebalancing Needs

```solidity theme={null}
// Get current rebalance limits
(, , , IFolio.RebalanceLimits memory limits, , ) = folio.getRebalance();

// Calculate surpluses and deficits
(
    address[] memory tokens,
    uint256[] memory surpluses,
    uint256[] memory deficits
) = lens.surplusesAndDeficits(folio, limits.high, limits.low);

for (uint256 i = 0; i < tokens.length; i++) {
    if (surpluses[i] > 0) {
        // Token needs to be sold
        console.log("Sell", surpluses[i], "of", tokens[i]);
    } else if (deficits[i] > 0) {
        // Token needs to be bought
        console.log("Buy", deficits[i], "of", tokens[i]);
    }
}
```

## Constants

<ParamField path="D18" type="uint256" default="1e18">
  18-decimal fixed point scaling factor
</ParamField>

<ParamField path="D27" type="uint256" default="1e27">
  27-decimal fixed point scaling factor (used for weights and prices)
</ParamField>

## Integration Notes

<Info>
  **Frontend Integration**: Use these functions via `eth_call` (read-only RPC calls). Never send transactions to FolioLens.
</Info>

<Info>
  **Indexing**: These functions are useful for building subgraphs or analytics dashboards. Call them periodically to track Folio state changes.
</Info>

<Warning>
  The `getAllBids()` function may be expensive for Folios with many tokens (N² complexity). Consider using pagination or filtering for large baskets.
</Warning>

## Error Handling

Functions use `try/catch` to gracefully handle invalid states:

```solidity theme={null}
try folio.getBid(...) returns (...) {
    // Process valid bid
} catch {
    // Skip invalid pair
}
```

This ensures functions don't revert on temporary invalid states (e.g., ended auctions, removed tokens).
