# StateView (/docs/protocols/v4/guides/state-view)

Read Uniswap v4 pool state offchain using StateView and compare with onchain StateLibrary usage.

## StateView Overview
When building on **Uniswap v4**, you will often need to read pool state for both onchain and offchain use cases. Onchain contracts can directly invoke the [**StateLibrary**](https://github.com/Uniswap/v4-core/blob/main/src/libraries/StateLibrary.sol) to execute these reads during transactions, but offchain systems—such as frontends or analytics services—require a deployed contract with view functions. This is where [**StateView**](https://github.com/Uniswap/v4-periphery/blob/main/src/lens/StateView.sol) comes in.

> *In short: Use StateLibrary within onchain contracts and use StateView with an RPC for frontends and analytics.*

By providing a dedicated interface for offchain reads, **StateView** helps:

* Retrieve pool state without paying gas
* Simplify integration for frontends, dashboards, and analytics
* Ensure a clean separation between onchain logic and offchain queries

## Comparing Onchain and Offchain Access
If you're familiar with [Reading Pool State](/docs/protocols/v4/guides/read-pool-state), you already know that Uniswap v4 uses **extsload** for efficient data access. For onchain usage, we rely on **StateLibrary** within contracts. However, offchain clients cannot rely on an onchain library for state reads.

Instead, **StateView** provides these same calls in a single contract designed explicitly for offchain consumption.

> *Because StateLibrary operates via onchain function calls, it’s not directly accessible to offchain clients. Hence, StateView provides a simple, gas-free interface designed for frontends and analytics.*

For instance, an onchain contract might use the `StateLibrary` as follows:

```solidity
// Onchain contract using StateLibrary
contract MyProtocol {
    using StateLibrary for IPoolManager;

    function checkPoolPrice(PoolId poolId) external returns (uint160) {
        (uint160 sqrtPriceX96, , , ) = poolManager.getSlot0(poolId);
        // ... use the price in contract logic ...
        return sqrtPriceX96;
    }
}
```

By contrast, an offchain frontend or analytics service should interact with `StateView`:

```tsx
// Frontend or analytics client using StateView
const stateView = getContract({
  address: STATE_VIEW_ADDRESS,
  abi: stateViewABI
});

const { sqrtPriceX96 } = await stateView.read.getSlot0([poolId]);
// ... use the price in your application ...
```

This separation ensures that each context (onchain vs. offchain) uses the most efficient data reading pattern.

## Usage With Frontend Clients
Frontend applications frequently display real-time information about pools, positions, and other market data—without incurring transaction costs. **StateView** addresses these requirements by exposing read-only functions tailored for offchain integrations.

## Setting up with Viem
We’ll use [**viem**](https://viem.sh/), a TypeScript library for Ethereum, to demonstrate how to connect to **StateView**.

```tsx
import { createPublicClient, http } from 'viem';
import { mainnet } from 'viem/chains';

// Initialize the client
const client = createPublicClient({
  chain: mainnet,
  transport: http()
});

// Set up StateView contract instance
const stateView = getContract({
  address: STATE_VIEW_ADDRESS,
  abi: stateViewABI,
  client
})
```

> **Note:** *The stateView object comes from our getContract call above. Make sure you’ve imported stateViewABI correctly before attempting to read from the contract.*

With this setup, you can now:

* **Connect to an Ethereum network**
* **Call StateView’s read functions**
* **Retrieve pool information offchain at no gas cost**

## Handling errors and invalid pool IDs
When calling `stateView.read.<function>([poolId])`, be mindful that:

* If you pass an invalid `poolId` (typically a [`bytes32`](https://github.com/Uniswap/v4-core/blob/main/src/types/PoolId.sol#L6) in Uniswap v4), the call may revert or return unexpected data.
* Consider adding try-catch (or equivalent error handling in your framework) to gracefully handle failures if the pool does not exist or if the call fails onchain.

## Reading Pool Data
Here are common examples of how to retrieve pool data using **StateView**.

## Getting pool state
A pool’s core state, such as its current price or fees, is often necessary for frontends. Use `getSlot0`:

```tsx
// Example: Reading pool price and fees
const getPoolState = async (poolId: string) => {
  // getSlot0 returns:
  // - Current price (sqrtPriceX96) in Q64.96 fixed-point format
  // - Active tick
  // - Protocol and LP fee settings
  const [
    sqrtPriceX96,
    tick,
    protocolFee,
    lpFee
   ] = await stateView.read.getSlot0([poolId]);

  return {
    price: calculatePrice(sqrtPriceX96), // implement your math logic for Q64.96
    tick,
    protocolFee,
    lpFee
  };
};
```

**What it Returns:**

* **`sqrtPriceX96`**: The current pool price in Q64.96 fixed-point format.
* **`tick`**: The current tick in which the pool is operating.
* **`protocolFee`** and **`lpFee`**: Fee parameters for protocol and LP fee tiers.

## Getting pool liquidity
To understand how much liquidity a pool holds:

```tsx
// Example: Reading the total active liquidity of a pool
const getPoolLiquidity = async (poolId: string) => {
  // getLiquidity returns the total liquidity currently active in the pool
  const liquidity = await stateView.read.getLiquidity([poolId]);
  return liquidity;
};
```

**Why It Matters:**

* Helps gauge the depth of the pool
* Influences price impact calculations in trading
* Provides context for the pool’s capacity to absorb trades

## Core Functions and Return Types
While **StateView** exposes many functions, here are several essential calls for most offchain applications. Each function typically takes a `poolId` (of type `bytes32`) as the key input, identifying which pool to query.

1. **`getSlot0(poolId)`**
   * Returns `(uint160 sqrtPriceX96, int24 tick, uint8 protocolFee, uint8 lpFee)`.
   * Essential for displaying real-time price data and fees.
2. **`getLiquidity(poolId)`**
   * Returns `uint128 liquidity` (the total active pool liquidity).
   * Used to assess trading depth and volatility.
3. **`getPositionInfo(poolId, positionId)`**
   * Returns `(uint128 liquidity, uint256 feeGrowthInside0Last, uint256 feeGrowthInside1Last)`.
   * Critical for tracking user positions, especially to calculate earned fees over time.
4. **`getFeeGrowthGlobals(poolId)`**
   * Returns `(uint256 feeGrowthGlobal0, uint256 feeGrowthGlobal1)`.
   * Useful for analytics around total fee accumulation in the pool.

## Note on poolId and positionId
* In **Uniswap v4**, a `poolId` is typically a `bytes32` that is derived by calling
  `keccak256(abi.encode(poolKey))` where poolKey contains:
  * currency0: The lower currency address of the pool
  * currency1: The higher currency address of the pool
  * fee: The pool LP fee (uint24)
  * tickSpacing: The tick spacing value (int24)
  * hooks: The hooks contract address
* A `positionId` may also be a `bytes32` or other unique identifier that references a specific position.

## Security and Gas Considerations
* **Offchain Reads**: Calls to `StateView` are purely read-only, so they cost no gas. This makes them ideal for frequently refreshing UI/analytics data.
* **Onchain vs. Offchain**: Remember that if you need to integrate pool data into a live transaction, you must use `StateLibrary` within your smart contract.
* **Edge Cases**: Always verify the returned data before using it in your application. Network or contract errors could lead to unexpected values.

## Summary
**StateView** is a powerful and efficient way to read Uniswap v4 pool data offchain. By separating onchain logic (using `StateLibrary`) and offchain reads (using `StateView`), Uniswap ensures the best developer experience for both contexts.

To recap:

1. **Setup**: Use libraries like `viem` to connect to the Ethereum network.
2. **Read**: Call `getSlot0`, `getLiquidity`, `getPositionInfo`, and other methods for crucial state data.
3. **Handle Errors**: Implement basic checks for invalid `poolId` or connection failures.
