Overview
BEX LP tokens represent a share of a liquidity pool. Accurately valuing these tokens is essential for displaying balances, calculating rewards, and for on-chain operations like collateralization and liquidation. There are several methods to value LP tokens, each suited to different use cases.Methods of valuation
Informational (sum of balances)
This method is suitable for off-chain, informational, or UI purposes. It is not manipulation-resistant and should not be used for on-chain or critical financial operations. Formula: Where:- Balancei: balance of token in the pool
- Pricei: market price of token
- SupplyLP\ Tokens: total supply of LP tokens
| Token | Balance | Price (USD) | Value (USD) |
|---|---|---|---|
| $BERA | 1,000 | $10 | $10,000 |
| $HONEY | 10,000 | $1 | $10,000 |
| Total Pool Value | $20,000 | ||
| LP Token Supply | 1,000 |
- Pool Value: 1000 $BERA 10 USD + 10000 $HONEY 1 USD = 20000 USD
- LP Token Price: 20000 USD 1000 $LPTOKEN = 20 USD
Weighted pools
Weighted pools use a constant product invariant with custom weights. This method is manipulation-resistant and is recommended for on-chain or robust off-chain use.| Calculation Steps | Formula |
|---|---|
| Step 1: Pool Invariant where | |
| Step 2: Token Weighted Values | |
| Step 3: Calculate | |
| Step 4: Final LP Token Price where is the LP token supply |
| Calculation Steps | Values |
|---|---|
| Step 1: Token Weights | ($BAL) ($WETH) |
| Step 2: Oracle Prices | $4.53 ($BAL) $1090.82 ($WETH) |
| Step 3: Pool Parameters | (from pool.getInvariant())(from pool.totalSupply()) |
| Step 4: Final LP Token Price | $11.34 |
Stable pools
Stable pools are optimized for assets that trade at or near parity (e.g., stablecoins). They use the StableSwap invariant and often expose agetRate() function.
StableSwap Invariant:
Where:
- is the amplification parameter
- is the number of tokens
- are token balances
- is the invariant
getRate() function, which returns the value of 1 LP token in terms of the pool’s base asset (e.g., USD or a stablecoin):
Manual Calculation (if needed):
Where is the actual supply (use getActualSupply() for pre-minted pools).
Example:
Suppose a USDC/DAI/USDT pool with and USD as the base asset:
- LP token price: USD per LP token
Linear pools
Linear pools are designed for pairs where one token is a yield-bearing or wrapped version of the other. They use a simple linear invariant and expose agetRate() function.
Linear Pool Invariant:
Where is the rate between the wrapped and main token.
LP Token Price (using getRate):
Manual Calculation (if needed):
Where is the virtual supply (use getVirtualSupply()).
Example:
Suppose a wstETH/ETH pool with and ETH at :
- LP token price: USD per LP token
Special considerations
- Pre-minted Supply: Some pools (especially stable pools) pre-mint the maximum possible LP tokens. Always use
getActualSupply()orgetVirtualSupply()as appropriate. - Protocol Fees: Some pools accrue protocol fees, which may affect the actual value of LP tokens. Weighted and stable pools account for these in their supply functions.
- Manipulation Resistance: For on-chain or critical use, always use invariant-based or rate-based pricing, not simple sum-of-balances.
- Re-entrancy Protection: When evaluating on-chain, always check for Vault re-entrancy using
ensureNotInVaultContext(vault). - Staked LP Tokens: If LP tokens are staked, include both wallet and staked balances in your calculations.
References
- Balancer: Valuing BPT
- Balancer: Stable Math
- BEX Vault Contract
- BEX Pool Types
- BEX SDK