> For the complete documentation index, see [llms.txt](https://docs.metric.xyz/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.metric.xyz/run-a-pool/build-a-price-provider.md).

# Build a Price Provider

A Price Provider implements the pool's pricing logic and returns bid, ask and reference price.

## 1. Choose your logic

| Strategy                                   | Example logic                                                                                         |
| ------------------------------------------ | ----------------------------------------------------------------------------------------------------- |
| **Follow offchain prices**                 | Read the Compressed Oracle, Chainlink or Pyth; configure spreads and sanity checks.                   |
| **Follow another DEX onchain**             | Use another DEX's mid or TWAP as a reference or cross-check.                                          |
| **Constant price & custom spread**         | Keep the reference constant and adjust bid/ask with custom logic. Bins stay at fixed absolute prices. |
| **Discover price from trades**             | Use an `afterSwap` extension to report fills; read pool state to respond to liquidity imbalance.      |
| **Read backing for a yield-bearing asset** | Use a staking or vault conversion rate to price the token against its underlying asset.               |
| **Custom math or formula**                 | Calculate prices with a model, such as Black-Scholes with volatility inputs, HSVM or LMSR.            |

Identify required updates, including for onchain strategies. See [Oracles](/how-pools-work/oracles.md) for update infrastructure and [anchored pricing](/how-pools-work/anchored-pricing.md#anchored-pricing) for constrained custom pricing in public pools.

## 2. Implement the interface

```solidity
interface IPriceProvider {
    function token0() external view returns (address);
    function token1() external view returns (address);
    function getQuote() external returns (
        uint128 bidPrice,
        uint128 askPrice,
        uint128 referencePrice
    );
}
```

**Tokens:** `token0` and `token1` must match the pool's tokens, in the same order.<br>

**Units:** Prices are whole `token1` per whole `token0`, as [Q64.64](/reference/glossary.md) (× 2⁶⁴), whatever the token decimals. With token0 = WETH and token1 = USDC, 2,000 USDC per WETH is 2000 << 64.<br>

**Validity:** Each quote must satisfy:

* `0 < bid < ask`
* `bid < referencePrice < ask` (strictly between)
* the pool's asymmetry limit: with `r₁ = ref/bid − 1`, `r₂ = ask/ref − 1` and `M = 1 + bidAskRefAsymmetryX8/256`, the pool requires `1/M ≤ r₁/r₂ ≤ M`.

bidAskRefAsymmetryX8 can't be 0. At creation it can be at most the factory's creation cap; only the factory owner can set a higher value later. If it is type(uint16).max, the asymmetry check is off and the reference may equal bid or ask.\
\
**Failures:** If an input is stale or missing, revert. The pool wraps the revert in PriceProviderFailed and the swap fails. An invalid quote makes the pool revert with a specific error. See [Price Providers](/how-pools-work/price-providers.md) for quote semantics.\
\
**State:** getQuote() is not view. The pool calls it with a normal call, so it can update state, for example to refresh a cached price or a TWAP. Custom sources read by an APP through `staticcall` must be static.

### Reference price

Use the geometric mid, sqrt(bid \* ask), or your best estimate of fair price.

{% hint style="warning" %}
**Report an honest reference.** LP earnings on each side are measured from it, and so are the curator's and Metric's fees. Misreporting it can get the pool deprioritized or frozen.
{% endhint %}

The reference price must stay within the pool's `bidAskRefAsymmetryX8` limit.

## 3. Test and deploy

Test unequal decimals, rounding, stale or missing inputs, quoting, halt/recovery and both swap directions.

Use the provider's address when you create the pool.

For Metric routing, keep quotes caller-independent and support zero-origin simulation.

Next: [Build an extension](/run-a-pool/build-an-extension.md).
