> For the complete documentation index, see [llms.txt](https://docs.kpk.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.kpk.io/funds/infrastructure/onchain-accounting/meta-balance-adapters/curve-gauges.md).

# Curve Gauges

Reports an account's **gauge-staked** Curve LP position across any configured gauge, plus all claimable rewards (CRV and extra reward tokens). The staked LP is decomposed pro-rata into the pool's underlying coins using the same logic as the Pools adapter. Wallet-held (unstaked) LP is the separate [Curve Pools](/funds/infrastructure/onchain-accounting/meta-balance-adapters/curve-pools.md) adapter.

* **Type:** Meta-adapter
* **protocolSubId:** `keccak256("curve-gauges")`
* **Instance key:** the gauge address, widened to bytes32.
* **Source:** [`CurveGaugesMetaBalanceAdapter.sol`](https://github.com/karpatkey/onchain-accounting/blob/main/src/balances/MetaBalanceAdapters/curve/CurveGaugesMetaBalanceAdapter.sol)

***

## Positions returned

| Leg             | PositionKind | isDebt  | Description                                                           |
| --------------- | ------------ | ------- | --------------------------------------------------------------------- |
| Staking         | `Staking`    | `false` | Pro-rata share of one pool coin, from the account's staked LP         |
| Rewards (CRV)   | `Rewards`    | `false` | Claimable CRV (lower-bound estimate); only when `CURVE_MINTER` is set |
| Rewards (extra) | `Rewards`    | `false` | Claimable amount of each extra reward token (V2+ gauges)              |

Unregistered, zero-amount, and asset-filtered tokens are skipped.

***

## Balance calculation

<figure><img src="/files/2GU7pWJqxUR3w6dBCQP7" alt="Flowchart of the Curve Gauges balance adapter: read calls derive position legs into PositionBalance entries."><figcaption><p>Curve Gauges adapter — how the underlying balances reported to the NAV Calculator are derived.</p></figcaption></figure>

**Staking legs:** with `stakedLp = gauge.balanceOf(account)`, the gauge's `lp_token()` resolves the pool (`CurvePoolLib.getPool`: self-LP if it has `coins()`, else `minter()`, else Curve's own registry). Each coin amount is:

```
amount[i] = poolBalance[i] * stakedLp / totalSupply
```

{% hint style="info" %}
**Legacy StableSwap pools resolve via Curve's registry, and the answer is validated rather than trusted.** The two heuristics above both miss the oldest generation — on 3Crv, `coins()`, `coins(int128)` and `minter()` all revert — so the pool is looked up through Curve's `AddressProvider` → registry. The reply must then answer `coins()` **and** round-trip (the registry's LP token for that pool must be the LP token asked about), because a wrong or hostile answer would decompose the position against *another pool's* balances — an over-report, the one direction this family must never take. Every hop is a bounded, guarded staticcall, so a chain without an AddressProvider degrades to the previous behaviour instead of reverting.

If the pool still cannot be resolved, the adapter reports the **staked LP token itself** as one leg rather than dropping the principal. Reverting would not help: the meta base absorbs a non-gas revert and substitutes empty legs, producing the same silent zero by another route — so the visibility has to live in the returned data. Only *structural* failure triggers this; a filtered or unregistered coin does not.
{% endhint %}

**CRV rewards** use a view-safe lower bound:

```
crvLb = max(integrate_fraction(account) - minter.minted(account, gauge), 0)
```

This is stale between checkpoints (deposit / withdraw / claim) and reads 0 for recently-transferred gauge tokens — for an exact value, `gauge.claimable_tokens(account)` must be called as a state mutation (eth\_call). The CRV leg is emitted only when `CURVE_MINTER != address(0)` (mainnet) and CRV is registered.

**Extra rewards** come from `claimable_reward(account, token)` for each `reward_tokens(i)` up to `MAX_COINS = 8` (CRV is skipped here, since it is handled via the Minter). V3+ gauges update these at most hourly, so values may be stale.

***

## Identity

* **positionId:** `abi.encode(address gauge)`
* **positionKind:** `Staking` · `Rewards`

There is no `labels` field on the position. The adapter implements `positionLabels(positionId)`, which returns `["Staking Gauge", "TOKEN0/TOKEN1/…"]` from the on-chain coin symbols — surfaced only by the verbose reads (`getAccountPositionsVerbose` / `getAccountNavVerbose`); the full breadcrumb is `[protocolName, ...labels]`.

***

## Constructor

```solidity
constructor(address minter_, address crvToken_, address navCalculator_)
```

| Parameter        | Description                                                                                   |
| ---------------- | --------------------------------------------------------------------------------------------- |
| `minter_`        | Curve Minter for CRV emission; pass `address(0)` to disable CRV tracking (L2 / non-mainnet)   |
| `crvToken_`      | CRV token address; `address(0)` to skip CRV                                                   |
| `navCalculator_` | NAVCalculator address (must be a contract); source of the asset registry and the instance set |

On L2 chains (Arbitrum, Optimism, Base, Polygon) pass `minter_ = address(0)`; LP decomposition is always attempted regardless of the minter.

***

## Registration

Registered as a meta-adapter via `addMetaBalanceAdapter(adapter)`, then per-gauge instances are added with `addMetaInstances`. Each instance coordinate is the gauge address widened to bytes32.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.kpk.io/funds/infrastructure/onchain-accounting/meta-balance-adapters/curve-gauges.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
