Curve Gauges
Reports an account's gauge-staked Curve LP position across any configured gauge, plus all claimable rewards (CRV and extra reward tokens).
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 adapter.
Type: Meta-adapter
protocolSubId:
keccak256("curve-gauges")Instance key: the gauge address, widened to bytes32.
Positions returned
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
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:
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.
CRV rewards use a view-safe lower bound:
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
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.
Last updated