Docs·Metrics reference
Metrics reference
Volume
Bonding-curve volume, post-graduation pool volume and refunds — what each is summed from and why one of them is always partial.
curveVolumeWei — bonding-curve volume#
| unit | wei |
|---|---|
| derivation | Σ Bought.grossEthUsed + Σ Sold.grossCurveQuote over every launch curve of every factory in priorFactories[] and the current one |
| source | BondingCurve.Bought, BondingCurve.Sold — contracts/src/launchpad/BondingCurve.sol |
| freshness | Indexed. Carries asOfBlock. |
| coverage | FULL from indexFromBlock |
event Bought(address indexed buyer, address indexed recipient, uint256 grossEthUsed,
uint256 curveQuote, uint256 tokenAmount, uint256 tradeFee);
event Sold(address indexed seller, uint256 tokenAmount, uint256 grossCurveQuote,
uint256 ethReceived, uint256 tradeFee);Both sides are measured gross — fee included, on the same basis. That is the whole reason the field choice matters, and picking the wrong field on one side produces a figure that is net on buys and gross on sells.
| Side | Use | Relationship |
|---|---|---|
| Buy | grossEthUsed | grossEthUsed = curveQuote + tradeFee. It is the ETH actually consumed, excluding any refund. curveQuote is the net that reached the reserve. |
| Sell | grossCurveQuote | grossCurveQuote = ethReceived + tradeFee. It is what the curve gave up before the fee; ethReceived is what the seller got. |
| Completing buy | grossEthUsed | Already the capped amount: the curve sizes the trade to land exactly on the graduation target and refunds the excess. The refund is not in the event, correctly — it was never spent. |
Caveats#
| Caveat | Detail |
|---|---|
Redeemed is not volume | It is the refund hatch for a curve that completed and never graduated. Fee-free, and a reserve outflow rather than a trade. Published separately as refundedWei; never added to volume. |
tradeFeeBps is on no trade event | It is immutable on the curve, bounded by MAX_TRADE_FEE_BPS = 500. To reconstruct a historical fee rate, read the curve, or replay LaunchFactory.ConfigSet to the launch’s block. |
| A launch’s own opening buy is volume | The factory routes it through the same curve at the launch timestamp, so it emits an ordinary Bought. It is not excluded. |
poolVolumeWei — post-graduation volume#
| unit | wei |
|---|---|
| derivation | Per token, PoolMetrics.metricsOf(token).buyVolumeWei — equivalently Σ Poked.buyAddedWei. Protocol-wide, the sum over graduated tokens. |
| source | PoolMetrics.Poked, PoolMetrics.metricsOf(address) — contracts/src/predict/PoolMetrics.sol |
| freshness | On-chain accumulator, advanced by a permissionless poke(token) no more often than MIN_POKE_INTERVAL (300 s on production). |
| coverage | PARTIAL, always. See below. |
fees = (feeGrowth0X128_now − feeGrowth0X128_last) × min(liquidity_now, liquidity_last) / 2^128
volume = fees × FEE_DENOMINATOR / lpFee| Consequence | Detail |
|---|---|
| Buy side only | Fee growth is read on currency0 (ETH), so sells contribute nothing. |
| Liquidity added mid-interval books less than traded | The interval is priced at the lower of the two liquidity readings. |
| An interval can be skipped entirely | When liquidity moved by more than MAX_LIQUIDITY_DRIFT (2×), the interval is dropped and says so: PoolMetrics.VolumeIntervalSkipped(address indexed token, uint128 previousLiquidity, uint128 currentLiquidity, uint256 feeGrowthDeltaX128). |
The exact alternative, when an exact figure is needed: index Uniswap V4 PoolManager Swap events filtered to the launch’s poolId (PoolMetrics.poolIdOf(token)). That is complete in both directions. It is not the platform’s published figure because the poke series is what settlement reads, and a published number that disagrees with the settlement oracle is worse than a conservative one. Publish whichever you used, and say which.
refundedWei — refunds from ungraduated completions#
| unit | wei |
|---|---|
| derivation | Σ Redeemed.ethReceived |
| source | BondingCurve.Redeemed(address indexed holder, uint256 tokenAmount, uint256 ethReceived) · gate BondingCurve.refundOpen() |
| freshness | Indexed. Carries asOfBlock. |
| coverage | FULL |
Only possible on a curve that reached complete() and did not graduate before completedAt + GRADUATION_GRACE_PERIOD (3 days). No fee is ever taken on this path. It belongs beside volume, never inside it — see launches and graduation for how a refunding launch is counted in the graduation rate.