There are a variety of reasons that one might want to determine the value of a Balancer Pool Token (BPT). Ultimately, it comes down to assessing the value of the underlying tokens per BPT. Please pay attention to the warnings on this page, as they are critical for calculating values accurately.
If evaluating a BPT purely for informational purposes (e.g. displaying on a UI), the calculation is quite trivial.
When evaluating for mission critical operations (e.g. determining if a loan with BPT as collateral can be liquidated), however, data validity and manipulation resistance are extremely important.
Getting BPT Supply
Don't use `totalSupply` without reading this first!
Balancer Pools with pre-minted BPT will always return
There are three potential functions to query when determining the BPT supply depending on pool type. When evaluating a new pool type, ensure that you are using the correct supply function!
This is the most common/current function to call.
getActualSupply is used by the most recent versions of Weighted and Stable Pools. It accounts for pre-minted BPT as well as due protocol fees.
This is used by Linear Pools and "legacy" Stable Phantom Pools. It accounts for pre-minted BPT but does not take due protocol fees into account. The omission of protocol fee calculations in Linear Pools is intentional since they do not pay protocol fees.
totalSupply only makes sense to call for older "legacy" pools. The original Weighted and Stable Pools do not have pre-minted BPT, so they follow the typical convention of using
totalSupply to account for issued pool shares.
Informational Price Evaluation
Don't use this on-chain!
This calculation is for infomational purposes only since it can be easily manipulated.
In short, BPT value is calculated by getting all underlying balances, multiplying those by their market prices, and dividing by the total supply of LP tokens.
On-Chain Price Evaluation
Check for Balancer Vault re-entrancy on ALL on-chain price evaluations!!!
When evaluating BPT price on-chain, it is CRUCIAL to verify that the Balancer Vault is not being re-entered.
The recommended method for doing this is using Balancer's VaultReentrancyLib. Calling
ensureNotInVaultContext(vault) will perform a noop call to the Vault that will fail if an attacker is attempting a read-only re-entrancy attack.
This library can be imported from version >= 3.1.2 of v2-pool-utils.
When calculating a Weighted Pool BPT price on-chain, it's important to use a manipulation resistant technique. The below formula uses the invariant, V, instead of balances directly. While token balances are used in the calculation of the invariant, the error is bounded by the swap fees that an attacker would have to pay to significantly imbalance a pool.
Where V is the WeightedMath invariant calculated as:
Forumla derivation here.
pool.getRate() function returns the exchange rate of a BPT to the underlying base asset of the pool accounting for rate providers, if they exist. A few examples:
WETH/wstETHpool will return a rate relative to
bb-a-USDwill return a rate relative to USD, calculated as a weighted average of the underlying stablecoins (
USDT) in the nested linear pools (
Linear Pools have a
pool.getRate() function that return the exchange rate of a BPT to the underlying base asset (
mainToken) of the pool.